diff --git a/roundup/security.py b/roundup/security.py
index 3dfa8bd442c13ec068ca90589a10e55fc9f5b9fa..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)
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 :