X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=roundup%2Fsecurity.py;h=58496f452a18d35648ecb9886c4dfbaa986cce83;hb=dcce5d6b6dede488f3650e6b8ffc8939cb22a211;hp=49e447795014c40af6a5b2c521dca2fa5acfd127;hpb=4d8d40c99d434209f317e08d9977334681efd92d;p=roundup.git diff --git a/roundup/security.py b/roundup/security.py index 49e4477..58496f4 100644 --- a/roundup/security.py +++ b/roundup/security.py @@ -1,59 +1,57 @@ +"""Handle the security declarations used in Roundup trackers. +""" +__docformat__ = 'restructuredtext' + import weakref -from roundup import hyperdb, volatiledb +from roundup import hyperdb -class PermissionClass(volatiledb.VolatileClass): - ''' Include the default attributes: - - name (String) - - classname (String) - - description (String) +class Permission: + ''' Defines a Permission with the attributes + - name + - description + - klass (optional) - The classname may be unset, indicating that this permission is not + The klass may be unset, indicating that this permission is not locked to a particular class. That means there may be multiple Permissions for the same name for different classes. ''' - def __init__(self, db, classname, **properties): - """ set up the default properties - """ - if not properties.has_key('name'): - properties['name'] = hyperdb.String() - if not properties.has_key('klass'): - properties['klass'] = hyperdb.String() - if not properties.has_key('description'): - properties['description'] = hyperdb.String() - volatiledb.VolatileClass.__init__(self, db, classname, **properties) - -class RoleClass(volatiledb.VolatileClass): - ''' Include the default attributes: - - name (String, key) - - description (String) - - permissions (PermissionClass Multilink) + def __init__(self, name='', description='', klass=None): + self.name = name + self.description = description + self.klass = klass + + def __repr__(self): + return ''%(id(self), self.name, self.klass) + +class Role: + ''' Defines a Role with the attributes + - name + - description + - permissions ''' - def __init__(self, db, classname, **properties): - """ set up the default properties - """ - if not properties.has_key('name'): - properties['name'] = hyperdb.String() - if not properties.has_key('description'): - properties['description'] = hyperdb.String() - if not properties.has_key('permissions'): - properties['permissions'] = hyperdb.Multilink('permission') - volatiledb.VolatileClass.__init__(self, db, classname, **properties) - self.setkey('name') + def __init__(self, name='', description='', permissions=None): + self.name = name.lower() + self.description = description + if permissions is None: + permissions = [] + self.permissions = permissions + + def __repr__(self): + return ''%(id(self), self.name, self.permissions) class Security: def __init__(self, db): ''' Initialise the permission and role classes, and add in the base roles (for admin user). ''' - # use a weak ref to avoid circularity - self.db = weakref.proxy(db) + self.db = weakref.proxy(db) # use a weak ref to avoid circularity - # create the permission class instance (we only need one)) - self.permission = PermissionClass(db, "permission") + # permssions are mapped by name to a list of Permissions by class + self.permission = {} - # create the role class instance (we only need one) - self.role = RoleClass(db, "role") + # roles are mapped by name to the Role + self.role = {} # the default Roles self.addRole(name="User", description="A regular user, no privs") @@ -72,8 +70,9 @@ class Security: description="User may register through the email") # initialise the permissions and roles needed for the UIs - from roundup import cgi_client, mailgw - cgi_client.initialiseSecurity(self) + from roundup.cgi import client + client.initialiseSecurity(self) + from roundup import mailgw mailgw.initialiseSecurity(self) def getPermission(self, permission, classname=None): @@ -82,36 +81,38 @@ class Security: Raise ValueError if there is no exact match. ''' - perm = self.db.permission - for permissionid in perm.stringFind(name=permission): - klass = perm.get(permissionid, 'klass') - if classname is not None and classname == klass: - return permissionid - elif not classname and not klass: - return permissionid - if not classname: + if not self.permission.has_key(permission): raise ValueError, 'No permission "%s" defined'%permission + + # look through all the permissions of the given name + for perm in self.permission[permission]: + # if we're passed a classname, the permission must match + if perm.klass is not None and perm.klass == classname: + return perm + # otherwise the permission klass must be unset + elif not perm.klass and not classname: + return perm raise ValueError, 'No permission "%s" defined for "%s"'%(permission, classname) def hasPermission(self, permission, userid, classname=None): ''' Look through all the Roles, and hence Permissions, and see if "permission" is there for the specified classname. - ''' roles = self.db.user.get(userid, 'roles') if roles is None: return 0 - for rolename in roles.split(','): - if not rolename: + for rolename in [x.lower().strip() for x in roles.split(',')]: + if not rolename or not self.role.has_key(rolename): continue - roleid = self.db.role.lookup(rolename) - for permissionid in self.db.role.get(roleid, 'permissions'): - if self.db.permission.get(permissionid, 'name') != permission: - continue - klass = self.db.permission.get(permissionid, 'klass') - if klass is None or klass == classname: - return 1 + # for each of the user's Roles, check the permissions + for perm in self.role[rolename].permissions: + # permission name match? + if perm.name == permission: + # permission klass match? + if perm.klass is None or perm.klass == classname: + # we have a winner + return 1 return 0 def hasNodePermission(self, classname, nodeid, **propspec): @@ -142,20 +143,23 @@ class Security: ''' Create a new Permission with the properties defined in 'propspec' ''' - return self.db.permission.create(**propspec) + perm = Permission(**propspec) + self.permission.setdefault(perm.name, []).append(perm) + return perm def addRole(self, **propspec): ''' Create a new Role with the properties defined in 'propspec' ''' - return self.db.role.create(**propspec) + role = Role(**propspec) + self.role[role.name] = role + return role - def addPermissionToRole(self, rolename, permissionid): + def addPermissionToRole(self, rolename, permission): ''' Add the permission to the role's permission list. - 'rolename' is the name of the role to add 'permissionid'. + 'rolename' is the name of the role to add the permission to. ''' - roleid = self.db.role.lookup(rolename) - permissions = self.db.role.get(roleid, 'permissions') - permissions.append(permissionid) - self.db.role.set(roleid, permissions=permissions) + role = self.role[rolename.lower()] + role.permissions.append(permission) +# vim: set filetype=python ts=4 sw=4 et si