I've returned your favor with an equally long e-mail...
At 01:02 AM 1/11/2001 +0000, Tom Schwaller wrote:
>a lot more. See the development in Zope: PAMUser, SMBUser, NTUser,
>IMAPUser,...
I added notes for these.
>Ah, Memory: User Caching comes to my mind. One need to know how many
>users are in Memory (logged in, the famous: "there are 100 Users logged in")
>and a mechanism to dynamically put Users in Memory (when they log in)
>and to throw them away again (with an activity manager. Simple Session
>timeouts are not enough. I think a method for throwing a user out of
>memory is enough, one can then implement different cache clearing strategies
>(with dervied classes). In my case this would be: no activity for 5
>Minutes => put user out of memory. It would be a bad idea to suck
>everything into memory and then manipulate the data there (I have
>thousands of users!). I would use a general cache manager class which
>could be used for other things to (reminds me of EJB technology).
>SQLCache, FilesystemCache,...
I added all of this as well. For the generic cache manager, I put a
question about it. I don't think I have the mindset to approach the general
cache manager tonight. Although, I certainly welcome any willing person to
throw a spec out there if they like. :-)
>As in the Session case, on could configure some aspects in
>Application.config
>
>'UserStore': SQL, # for the default persistance mechanism
>'UserTimeOut': 10, # much more agressive than sessions, which can stay
>longer,
> # at least on the filesystem or in a database
Is your UserTimeOut:
1. the time after which a user object is pushed out of memory (and onto
storage if changed)?
2. the time after which a user is considered logged out due to inactivity?
My first thought is that UserManager would have both.
>'UserTimeoutStrategy': 'Timeout strategy classname'
> # if you log access to userdata, you already have
> # a memory clearing strategy by sweeping
> # periodically over the "in memory" users
> # an throwing away the unused
What is this? Is there a class interface you would propose for it?
> > def addUser(self, user):
> > def userForId(self, id):
> > def userForName(self, name):
> > def users(self): # returns list of all users
>
>Users in memory or generally all users? The last case
>is quite usesless with thousands of users.
I augmented the interface to have "currentUsers()" which is in memory.
users() is not useless. I would be bothered if I could not easily iterate
through all the users on a site. I might wish to put together some kind of
report about them...
>Does the UserManager handle authentication?
>
>authenticateUserWithID(self, name, password)
>authenticateUserWithName(self, name, password)
Added.
> > def setUserClass(self, userClass):
>
>Waht is the exact meaning ot this method?
>Set the Persistance mechanism?
A vague thought on my part that perhaps UserManager would have a
createUser() method. That way you wouldn't have to import the user class or
even know what it was. WebKit code might look something like:
userMgr = self.application().userManager()
user = userMgr.createUser('chuck', 'foobar')
user.addRole('admin')
I guess I'm thinking that addRole() might take either a string with the
name of the role or the role object. If that's confusing, we could have
addRole() and addRoleNamed() instead.
> > class User:
> > '''
> > attributes:
> > name
> > password
> > e-mail (? do we need this separate or does it go in
> values below?)
> > id (simply number, used internally for indexing (like
> prehaps an indexed
> > INT column in SQL)
> > externalId (longer more cryptic string for setting
> permanent cookies on
> > the browser. not guessable; therefore prevents imposters)
>
>very good idea..
>
> > lastLogin
>
>lastActivity (a timestamp, usefull for clearing the data out of memory.
>see above)
Added.
>createDate , when the user got his account (=> "is member since ....").
>If you forget to collect this kind of data, you will never get it again
>(I made this mistake some time ago :-))
Added.
> > values (dictionary with any info you like)
> > '''
> > def value(self, name, default=_NoDefault):
> > def setValue(self, name, value):
>
>setValues(self, **args): e.g. setValues(id=10, name=me,
>password='secret', ...)
>same for __init__(self, **args)
Hmmm, does setValues() replace the values in existence. e.g. if my values
are {'x': 1} does setValues({'y': 2}) give {'y': 2} or {'x': 1, 'y': 2}?
Also, I was going to have actual attributes for the well known items such
as name and password.
>the "getDomains" stuff from Zope is not necessary....
Good since I don't know what it is. Although I will be attending the Zope
tutorial at python9. :-)
I'll try not to heckle the instructor.
> > Roles
> > -----
> >
> > class Role:
> > '''
> > attributes:
> > name
> > comment
> > data (dictionary with any info you like)
>
>data extendible or just a specified dictionary format,
>which could be populated by Configuration files?
Er, I should have called this values as well, although I'm wondering if
that's really necessary. It makes more sense with Users where there can
often be a lot ad hoc items you might like to add. That's probably not the
case with Role.
Removed for now.
And I changed 'comment' to 'description'.
I also added a note that we would want a WebKit servlet based admin page
for managing users and roles.
Gee, it's funny how projects always blow up so quickly. :-)
>class RoleUserManager (UserManager) # was remark from Geoff
>
> > def addRole(self, role):
>
>how do you construct role?
There was a Role class just above this. You instantiate it.
> > def roleForName(self, name):
>
>class RoleUser (User): # was remark from Geoff
>
> > '''
> > attributes:
> > roles (list of roles the user belongs to)
> > roleNames (dictionary keyed by role name; for quick
> look up)
> > '''
> > def playsRole(self, roleOrName):
>
>does this mean the same as hasRole(self, roleOrName) ore something else?
Sort of. Again I forgot to complete my thought in this area. I'd like to
allow for hierarchical roles. e.g., a particular role can inherit another
role. Sort of like exceptions in Python. A KeyError is also a LookupError,
so if you capture LookupError, you also capture KeyError.
Likewise if an Admin is a PowerUser, then saying
user.playsRole('PowerUser') captures admins as well.
I have added a new HierRole class. I don't like the name. Feel free to suggest.
> > def roles(self):
> > def setRoles(self, listOfRoles):
> >
> > Role notes:
> > - We could augment Page (or even Servlet) to disallow serving
> content if
> > the user doesn't play any of the roles required by the Page. Each page
>
>cool. Could also be interesting to be able to configure through
>something like RolesUser.config which uses setRoles() with data from this
>file.
Yes. I added a note that more specs on configuration are needed. I think
those will come more naturally (or at least safely) after the class API has
settled down.
> > would advertise a dictionary mapping operation names ('view', 'edit', etc.)
> > to a list or set of roles that are allowed to do so.
>
>Puhh, was exhausting writing this mail ... I have a lot
>more to tell here, but I think this is enough for
>a first run. I hope you find time to start writing the
>UserKit :-)
Well I've incorporated all your suggestions and more. I'll post a new copy.
>your APIs are very clear, which makes coding in Webware
>a real pleasure.
Thanks.
>I took a lok at SessionMemoryStore.py. I think
>there you have the same problem with many sessions.
>You need to clear some sessions out more agressively, otherwise
>your applications blows up in an uncontrollable way
>with many users (I'll try to use the megacool httpsession.py
>to produce this effect)
An explosion derived from beating up WebKit with httpsession.py would be
really sweet.
>I'm thinking also about a project here
>
>SessionMemoryFilesystemStore.py (put some of the stuff dynamically
>to the filesystem, when memory grows to much. depending on user
>activity)
I'd be interested to know the stats surrounding this. How many simultaneous
users do you get before memory becomes an issue? How much memory is saved
when pushing them out to disk?
Also, you can always switch to the file store if you were in an immediate bind.
>SessionSQLStore.py
>
>or is anybody else working on that?
Not that I know of.
-Chuck
|