@@ -18,6 +18,20 @@ class Permission:
1818 - properties (optional)
1919 - check function (optional)
2020 - props_only (optional, internal field is limit_perm_to_props_only)
21+ - filter function (optional) returns filter arguments for
22+ determining which records are visible by the user. The filter
23+ function comes into play when determining if a set of nodes
24+ found via a filter call of a class can be seen by the user --
25+ the normal way would be to call the permissions for each item
26+ found, the filter call performs this on the database for all
27+ nodes.
28+ Signature of the filter function:
29+ filter(db, userid, klass)
30+ The filter must return a list of dictionaries with filter parameters.
31+ Note that sort and group parameters of the filter call should
32+ not be set by filter method (they will be overwritten) and the
33+ parameter search_matches must not be set.
34+ An empty list returned means no access for this filter method.
2135
2236 The klass may be unset, indicating that this permission is not
2337 locked to a particular class. That means there may be multiple
@@ -47,14 +61,15 @@ class Permission:
4761 limit_perm_to_props_only = False
4862
4963 def __init__ (self , name = '' , description = '' , klass = None ,
50- properties = None , check = None , props_only = None ):
64+ properties = None , check = None , props_only = None , filter = None ):
5165 from roundup .anypy import findargspec
5266 self .name = name
5367 self .description = description
5468 self .klass = klass
5569 self .properties = properties
5670 self ._properties_dict = support .TruthDict (properties )
5771 self .check = check
72+ self .filter = filter
5873 if properties is not None :
5974 # Set to None unless properties are defined.
6075 # This means that:
@@ -211,6 +226,21 @@ def addPermission (self, *permissions):
211226 self ._permissions [pn ][cn ] = dict (((False , []), (True , [])))
212227 self ._permissions [pn ][cn ][bool (p .check )].append (p )
213228
229+ def filter_iter (self , permission , classname ):
230+ """ Loop over all permissions for the current role on the class
231+ with a check method (and props_only False).
232+ """
233+ if permission not in self ._permissions :
234+ return
235+ for c in (None , classname ):
236+ if c not in self ._permissions [permission ]:
237+ continue
238+ perms = self ._permissions [permission ][c ][True ]
239+ for p in perms :
240+ if p .limit_perm_to_props_only and p .properties :
241+ continue
242+ yield p
243+
214244 def hasPermission (self , db , perm , uid , classname , property , itemid , chk ):
215245 # if itemid is given a classname must, too, checked in caller
216246 assert not itemid or classname
@@ -283,6 +313,17 @@ def __init__(self, db):
283313 from roundup import mailgw
284314 mailgw .initialiseSecurity (self )
285315
316+ def filter_iter (self , permission , userid , classname ):
317+ """ Loop over all permissions for the current user on the class
318+ with a check method (and props_only False).
319+ """
320+ for rolename in self .db .user .get_roles (userid ):
321+ if not rolename or (rolename not in self .role ):
322+ continue
323+ r = self .role [rolename ]
324+ for perm in r .filter_iter (permission , classname ):
325+ yield perm
326+
286327 def getPermission (self , permission , classname = None , properties = None ,
287328 check = None , props_only = None ):
288329 ''' Find the Permission matching the name and for the class, if the
@@ -359,6 +400,19 @@ def hasPermission(self, permission, userid, classname=None,
359400 return v
360401 return False
361402
403+ def is_filterable (self , permission , userid , classname ):
404+ """ Check if all permissions for the current user on the class
405+ with a check method (and props_only False) also have a
406+ filter method. We only consider permissions with props_only
407+ set to False. Note that this will return True if there are
408+ no permissions with a check method found, the performed
409+ checks later will find no matching records.
410+ """
411+ for perm in self .filter_iter (permission , userid , classname ):
412+ if not perm .filter :
413+ return False
414+ return True
415+
362416 def roleHasSearchPermission (self , classname , property , * rolenames ):
363417 """ For each of the given roles, check the permissions.
364418 Property can be a transitive property.
0 commit comments