X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=roundup%2Fsecurity.py;h=e9f196efd74a7146e6c927b43c06f8c692976c55;hb=7425e946ef03a8d6e916ce9903b6a8135649e339;hp=7475ca62eb9067272f1088094522ee4cee47a452;hpb=c4bc35e8d1ce1e803c3efa0e64d3dd2d9be3bf03;p=roundup.git diff --git a/roundup/security.py b/roundup/security.py index 7475ca6..e9f196e 100644 --- a/roundup/security.py +++ b/roundup/security.py @@ -1,59 +1,53 @@ 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 + 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") @@ -63,37 +57,58 @@ class Security: ee = self.addPermission(name="Edit", description="User may edit everthing") self.addPermissionToRole('Admin', ee) - ae = self.addPermission(name="Access", + ae = self.addPermission(name="View", description="User may access everything") self.addPermissionToRole('Admin', ae) - ae = self.addPermission(name="Assign", - description="User may be assigned to anything") - self.addPermissionToRole('Admin', ae) reg = self.addPermission(name="Register Web", description="User may register through the web") - self.addPermissionToRole('Anonymous', reg) reg = self.addPermission(name="Register Email", description="User may register through the email") - self.addPermissionToRole('Anonymous', reg) # 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 hasClassPermission(self, classname, permission, userid): + def getPermission(self, permission, classname=None): + ''' Find the Permission matching the name and for the class, if the + classname is specified. + + Raise ValueError if there is no exact match. + ''' + 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') - for roleid in roles: - 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 + if roles is None: + return 0 + for rolename in roles.split(','): + if not rolename: + continue + # 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): @@ -124,20 +139,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] + role.permissions.append(permission) +# vim: set filetype=python ts=4 sw=4 et si