The following is my design for a personal project. This project is a learning exercise so any help offered is very much appreciated.
* Name: Session * Defn: a period of interaction between a user and the system. * * - during a Session, a user is Engaged in some task or activity. * - a Session may be not bound by connect-disconnect
* Name: User (Account does not represent user, represents record) * Defn: representation of actor who is registered for using the system
* Name: Engagement (Interaction?, Activity?) * Defn: activity or task that may be Engaged in during a Session.
If this is not clear in any way, please let me know. Engagement is an interface. An actor is some outside influence (standard definition).
I now have to decide if "logging in" will be a way to create a session:
"a period of interaction between a valid user and the system."
or if "logging in" is something that an actor may be engaged in during a session.
On one hand, I introduce complexity above Session, leaving it less general. This means that the system will handle states of connection in different ways, before stating that it is indeed a session.
On the other hand, there would be two states of Session: valid, invalid (pending a login). But this points at there being two different classes altogether...
At this moment, I'm considering saying that Session is an interface, and two classes implement it: ValidSession, and InvalidSession (PendingSession?). But then whats the proper way to let whoever 'owns' a session switch it to the different type? (without introducing unneccisary complexity)
Finding yourself tempted to change an object from one class to another is a classic indicator for State pattern. An object might play different roles at different times, such as a teacher taking a course and becomming a student, or a user being non-validated before login and validated after login.
State pattern says when the state changes from non-validated to validated we switch from one behavior object to another. Consider ...
IBehavior - interface with methods like viewGeneralData that anybody can do and editSensitiveData that only validated users can do.
NonValidatedUser implements IBehavior. Handles viewGeneralData, but throws an exception on editSensitiveData.
ValidatedUser implements IBehavior. Handles viewGeneralData and handles editSensitiveData.
When a user first hits the system, mySession.setBehavior(nonValidatedUser). Later when the log in, mySession.setBehavior(validatedUser).
Zat make sense? If so, think of several ways to avoid duplicating the code for viewGeneralData.
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Joined: Sep 07, 2004
I was uneasy over the State pattern, so I drew out how it would all work with it included, and here's what I came up with:
The way that would be implemented is by having session delegate to it's behaviour, correct? The behaviour then delegates to an engagement. The actual behaviour that there is variation of is "what an actor is allowed to engage in". In this case, no engagements at all (invalid) or all engagements (valid). The reasoning for adding a state pattern is intact, but then behaviour sounds odd. Really it's just a restriction upon engaging in anything. I tell it to behave as allowing engagements to happen, or not. The one State would allow "setEngagement", the other would not allow this method (exception perhaps). Rather than setting the state - there will always be only these two states (I'd like to give permissions to the User class later on) it seems better to simply define a method, isValid...
This leads me to refine quite a few things.
I've recognized a new class, called activity. The name may not be correct yet.
The way I'm envisioning it, is "an actor engages in a number of activities for a period of time". So for example, I engage in monitoring a well-site, then I engage in choosing a new activity (I dont know if this is appropriate yet), then I engage in something else. So then, the engagement is based completley on the activity. Activities have "engage(User?):Engagement". Sessions "becomeEngaged(Engagement)" (not yet a perfect method name, users are really the ones who do that). Who handles this interaction I don't yet know...
As for the first two options I was considering:
It makes more sense now to think of a Session as only being one with an identified user. Wait, I've just remembered the act of registration. This pushes me towards the 'improved' second option then...
Engagements may include logging on, registering, and so on. However, they're linked to each other. The current engagement is what defines what your next engagement will be. So, "logging on" is your first engagement. As the current engagement sets the rules, you must cease it in the right way: by logging in (changing user from undefined to whatever you are). It then leads you to your next engagement.
How does all this sound? If I didn't properly address/understand the state pattern please let me know.
Joined: Jan 29, 2003
For things that one user can do that another user cannot do I usually go to an authorization framework. The API is usually "can userid x do thing y". Until a user logs in, their userid is "default" or "unknown". After login you know a real userid. Userid might be all that's required in the session.
Variations: In my current system, when a user logs in they get a security token. This is used to see if they truly have a current security session (separate from HTTP session) and to make it harder to pretend to be somebody else, say by changing the userid in a cookie or something. The vendor framework we're using has an optional access type like read, update, create, delete, execute, so that can be part of the api. The full thing is more like:
There's a whole data model behind the SecurityHelper: Users have roles, roles have resources, the "relationship" between roles & resources has an access type bitmap. I think this is pretty common stuff.
Joined: Sep 07, 2004
I was worried about how accidental disconnects would be handled, this solves those problems quite nicley. Thank you.
This token... it can be seen as a password for a session then? How do you see session as being defined?
For the resource, you're saying that it would not allow the user to access it unless that user had permission then? Is the check done on every interaction with the resource?