At 01:27 PM 7/19/00 -0500, Phillip J. Eby wrote:
Hm. I don't think this could be classed as a "minor" change, however, since it has impact on ownership, for example. What's the path of the user folder which is above "/", for example? The whole thing is useless if these extra users can't be owners, and the ownership machinery right now wants an access path. I think perhaps we should go the fishbowl route on this, if only to make sure that Jim doesn't have a heart attack when he gets back. :)
Looks like I was wrong. This was in fact quite a minor patch. I've only tested this lightly so far, but if anyone else wants to try it out, here it is. Note that the new "access" file format looks like this: # Lines beginning with '#' are comments # # First user in file is "super" user, unless roles # are specified, in which case there is NO superuser # superusername:{SHA}fsjdflfs:domain1.com # # Format for all other users is name:pw:domains:roles # somemanager:{SHA}rr70flksf::Manager Editor SomeotherRole somedeveloper:{CRYPT}flsdajfd:domain2.com:Manager You can access a dictionary of all the "access" file users by importing rootUsers from AccessControl.SpecialUsers. It is a dictionary mapping user names to user objects. Be sure to use __of__ to wrap them to your UserFolder if you are adding support for this to a UserFolder variant. I have not yet added support for this to LoginManager, but as you'll see from the changes to the basic UserFolder, it is probably not going to be at all difficult to do so. Patch follows; watch out for line wrapping... Index: User.py =================================================================== RCS file: /cvs-repository/Zope2/lib/python/AccessControl/User.py,v retrieving revision 1.112 diff -u -r1.112 User.py --- User.py 2000/07/11 18:42:48 1.112 +++ User.py 2000/07/23 01:38:51 @@ -314,13 +314,30 @@ 'No access file found at %s - see INSTALL.txt' % INSTANCE_HOME ) try: - data=split(strip(f.readline()),':') - f.close() - _remote_user_mode=not data[1] - try: ds=split(data[2], ' ') - except: ds=[] - super=Super(data[0],data[1],('manage',), ds) - del data + d=f.readlines(); f.close(); del f + rootUsers = SpecialUsers.rootUsers = {} + + for data in map(strip,d): + if not data or data[0]=='#': continue + data=split(data+':::',':') # allow for missing fields + + n = data[0] + ds = split(strip(data[2])) # space-delimited domains + pw = data[1] + r = split(strip(data[3])) # space-delimited roles + + if rootUsers or r: + # If not first user in file, or if roles are specified, + # user is a "normal" user object + rootUsers[n] = SimpleUser(n,data[1],tuple(split(data[3])),data[2]) + else: + super = rootUsers[n] = Super(n,pw,('manage',), ds) + _remote_user_mode=not pw + + del data,n,ds,pw,r + + del d + except: raise 'InstallError', 'Invalid format for access file - see INSTALL.txt' @@ -383,6 +400,11 @@ """ try: return self.getUser(id) except: + + # Don't return the superuser, so that super can't own things + if rootUsers.has_key(id) and id!=super.getUserName(): + return rootUsers[id].__of__(self) + if default is _marker: raise return default @@ -405,7 +427,6 @@ _remote_user_mode=_remote_user_mode - _super=super _nobody=nobody def validate(self,request,auth='',roles=None): @@ -440,11 +461,11 @@ return None name,password=tuple(split(decodestring(split(auth)[-1]), ':', 1)) - # Check for superuser - super=self._super - if self._isTop() and (name==super.getUserName()) and \ - super.authenticate(password, request): - return super + # Check for superuser/root users + if self._isTop() and rootUsers.has_key(name): + user = rootUsers[name].__of__(self) + if user.authenticate(password, request): + return user # Try to get user user=self.getUser(name) @@ -508,10 +529,9 @@ return ob return None - # Check for superuser - super=self._super - if self._isTop() and (name==super.getUserName()): - return super + # Check for superuser/root users + if self._isTop() and rootUsers.has_key(name): + return rootUsers[name].__of__(self) # Try to get user user=self.getUser(name) @@ -560,7 +580,7 @@ title ='Illegal value', message='Password and confirmation must be specified', action ='manage_main') - if self.getUser(name) or (name==self._super.getUserName()): + if self.getUser(name) or (rootUsers.has_key(name)): return MessageDialog( title ='Illegal value', message='A user with the specified name already exists',