diff --git a/roundup/security.py b/roundup/security.py
index 2a1e520caede8f84eaa53494afc8246bfba43102..e3841ba298508776a4667d7affdc08066152e655 100644 (file)
--- a/roundup/security.py
+++ b/roundup/security.py
# we have a winner
return 1
+ def searchable(self, classname, property):
+ """ A Permission is searchable for the given permission if it
+ doesn't include a check method and otherwise matches the
+ given parameters.
+ """
+ if self.name not in ('View', 'Search'):
+ return 0
+
+ # are we checking the correct class
+ if self.klass is not None and self.klass != classname:
+ return 0
+
+ # what about property?
+ if not self._properties_dict[property]:
+ return 0
+
+ if self.check:
+ return 0
+
+ return 1
+
+
def __repr__(self):
return '<Permission 0x%x %r,%r,%r,%r>'%(id(self), self.name,
self.klass, self.properties, self.check)
self.addRole(name="Admin", description="An admin user, full privs")
self.addRole(name="Anonymous", description="An anonymous user")
- ce = self.addPermission(name="Create",
- description="User may create everthing")
- self.addPermissionToRole('Admin', ce)
- ee = self.addPermission(name="Edit",
- description="User may edit everthing")
- self.addPermissionToRole('Admin', ee)
- ae = self.addPermission(name="View",
- description="User may access everything")
- self.addPermissionToRole('Admin', ae)
+ # default permissions - Admin may do anything
+ for p in 'create edit retire view'.split():
+ p = self.addPermission(name=p.title(),
+ description="User may %s everthing"%p)
+ self.addPermissionToRole('Admin', p)
# initialise the permissions and roles needed for the UIs
from roundup.cgi import client
Note that this functionality is actually implemented by the
Permission.test() method.
'''
- roles = self.db.user.get(userid, 'roles')
- if roles is None:
- return 0
if itemid and classname is None:
raise ValueError, 'classname must accompany itemid'
- for rolename in [x.lower().strip() for x in roles.split(',')]:
+ for rolename in self.db.user.get_roles(userid):
if not rolename or not self.role.has_key(rolename):
continue
# for each of the user's Roles, check the permissions
return 1
return 0
+ def roleHasSearchPermission(self, classname, property, *rolenames):
+ """ For each of the given roles, check the permissions.
+ Property can be a transitive property.
+ """
+ perms = []
+ # pre-compute permissions
+ for rn in rolenames :
+ for perm in self.role[rn].permissions:
+ perms.append(perm)
+ # Note: break from inner loop means "found"
+ # break from outer loop means "not found"
+ cn = classname
+ prev = None
+ prop = None
+ Link = hyperdb.Link
+ Multilink = hyperdb.Multilink
+ for propname in property.split('.'):
+ if prev:
+ try:
+ cn = prop.classname
+ except AttributeError:
+ break
+ prev = propname
+ try:
+ cls = self.db.getclass(cn)
+ prop = cls.getprops()[propname]
+ except KeyError:
+ break
+ for perm in perms:
+ if perm.searchable(cn, propname):
+ break
+ else:
+ break
+ else:
+ # for Link and Multilink require search permission on label-
+ # and order-properties and on ID
+ if isinstance(prop, Multilink) or isinstance(prop, Link):
+ try:
+ cls = self.db.getclass(prop.classname)
+ except KeyError:
+ return 0
+ props = dict.fromkeys(('id', cls.labelprop(), cls.orderprop()))
+ for p in props.iterkeys():
+ for perm in perms:
+ if perm.searchable(prop.classname, p):
+ break
+ else:
+ return 0
+ return 1
+ return 0
+
+ def hasSearchPermission(self, userid, classname, property):
+ '''Look through all the Roles, and hence Permissions, and
+ see if "permission" exists given the constraints of
+ classname and property.
+
+ A search permission is granted if we find a 'View' or
+ 'Search' permission for the user which does *not* include
+ a check function. If such a permission is found, the user may
+ search for the given property in the given class.
+
+ Note that classname *and* property are mandatory arguments.
+
+ Contrary to hasPermission, the search will *not* match if
+ there are additional constraints (namely a search function)
+ on a Permission found.
+
+ Concerning property, the Permission matched must have
+ either no properties listed or the property must appear in
+ the list.
+ '''
+ roles = [r for r in self.db.user.get_roles(userid)
+ if r and self.role.has_key(r)]
+ return self.roleHasSearchPermission (classname, property, *roles)
+
def addPermission(self, **propspec):
''' Create a new Permission with the properties defined in
'propspec'. See the Permission class for the possible
role = self.role[rolename.lower()]
role.permissions.append(permission)
+ # Convenience methods for removing non-allowed properties from a
+ # filterspec or sort/group list
+
+ def filterFilterspec(self, userid, classname, filterspec):
+ """ Return a filterspec that has all non-allowed properties removed.
+ """
+ return dict ([(k, v) for k, v in filterspec.iteritems()
+ if self.hasSearchPermission(userid,classname,k)])
+
+ def filterSortspec(self, userid, classname, sort):
+ """ Return a sort- or group-list that has all non-allowed properties
+ removed.
+ """
+ if isinstance(sort, tuple) and sort[0] in '+-':
+ sort = [sort]
+ return [(d, p) for d, p in sort
+ if self.hasSearchPermission(userid,classname,p)]
+
# vim: set filetype=python sts=4 sw=4 et si :