Skip to content

Commit 6b81886

Browse files
committed
Add check_factory
For Permission objects where we're given a filter function but no check function, manufacture a check function.
1 parent bb08d50 commit 6b81886

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

roundup/security.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ def __init__(self, name='', description='', klass=None,
8989

9090
if check is None:
9191
self.check_version = 0
92+
if filter is not None:
93+
if klass is None:
94+
s = "Definition of a filter function" \
95+
" needs a check function if no klass is given"
96+
raise ValueError(s)
97+
self.check = self.check_factory(klass, filter)
98+
self.check_version = 1
9299
else:
93100
args = findargspec.findargspec(check)
94101
# args[2] is the keywords argument. Leave it as a subscript and
@@ -102,6 +109,18 @@ def __init__(self, name='', description='', klass=None,
102109
# function definition is function(db, userid, itemid, **other)
103110
self.check_version = 2
104111

112+
def check_factory(self, klass, filter_function):
113+
""" When a Permission defines a filter function but no check
114+
function, we manufacture a check function here
115+
"""
116+
def check(db, userid, itemid):
117+
cls = db.getclass(klass)
118+
args = filter_function(db, userid, cls)
119+
for a in args:
120+
if cls.filter([itemid], **a):
121+
return True
122+
return check
123+
105124
def test(self, db, permission, classname, property, userid, itemid):
106125
''' Test permissions 5 args:
107126
permission - string like Edit, Register etc. Required, no wildcard.

test/db_test_base.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,25 @@ def filter(db, userid, klass):
30493049
# User may see own and public queries
30503050
self.assertEqual(r, ['5', '6', '4', '3', '2', '1'])
30513051

3052+
def testFilteringWithManufacturedCheckFunction(self):
3053+
# We define a permission with a filter function but no check
3054+
# function. The check function is manufactured automatically.
3055+
# Then we test the manufactured *check* function only by turning
3056+
# off the filter function.
3057+
view_query = self.setupQuery()
3058+
3059+
def filter(db, userid, klass):
3060+
return [dict(filterspec = dict(private_for=['-1', userid]))]
3061+
perm = self.db.security.addPermission
3062+
p = perm(name='View', klass='query', filter=filter)
3063+
self.db.security.addPermissionToRole("User", p)
3064+
# Turn filtering off
3065+
self.db.config.RDBMS_DEBUG_FILTER = True
3066+
filt = self.db.query.filter_with_permissions
3067+
r = filt(None, {}, sort=[('+', 'name')])
3068+
# User may see own and public queries
3069+
self.assertEqual(r, ['5', '6', '4', '3', '2', '1'])
3070+
30523071
# XXX add sorting tests for other types
30533072

30543073
# nuke and re-create db for restore

0 commit comments

Comments
 (0)