# HG changeset patch # User Ralf Schlatterbeck # Date 1731331945 -3600 # Node ID e9af087437593b8de90e4995747fa9f3da1fa4f3 # Parent 67a0fc4f99346b84c6ae376488644cd1ea9eae54 Add check_factory For Permission objects where we're given a filter function but no check function, manufacture a check function. diff -r 67a0fc4f9934 -r e9af08743759 roundup/security.py --- a/roundup/security.py Mon Nov 11 11:25:55 2024 +0100 +++ b/roundup/security.py Mon Nov 11 14:32:25 2024 +0100 @@ -89,6 +89,13 @@ if check is None: self.check_version = 0 + if filter is not None: + if klass is None: + s = "Definition of a filter function" \ + " needs a check function if no klass is given" + raise ValueError(s) + self.check = self.check_factory(klass, filter) + self.check_version = 1 else: args = findargspec.findargspec(check) # args[2] is the keywords argument. Leave it as a subscript and @@ -102,6 +109,18 @@ # function definition is function(db, userid, itemid, **other) self.check_version = 2 + def check_factory(self, klass, filter_function): + """ When a Permission defines a filter function but no check + function, we manufacture a check function here + """ + def check(db, userid, itemid): + cls = db.getclass(klass) + args = filter_function(db, userid, cls) + for a in args: + if cls.filter([itemid], **a): + return True + return check + def test(self, db, permission, classname, property, userid, itemid): ''' Test permissions 5 args: permission - string like Edit, Register etc. Required, no wildcard. diff -r 67a0fc4f9934 -r e9af08743759 test/db_test_base.py --- a/test/db_test_base.py Mon Nov 11 11:25:55 2024 +0100 +++ b/test/db_test_base.py Mon Nov 11 14:32:25 2024 +0100 @@ -3049,6 +3049,25 @@ # User may see own and public queries self.assertEqual(r, ['5', '6', '4', '3', '2', '1']) + def testFilteringWithManufacturedCheckFunction(self): + # We define a permission with a filter function but no check + # function. The check function is manufactured automatically. + # Then we test the manufactured *check* function only by turning + # off the filter function. + view_query = self.setupQuery() + + def filter(db, userid, klass): + return [dict(filterspec = dict(private_for=['-1', userid]))] + perm = self.db.security.addPermission + p = perm(name='View', klass='query', filter=filter) + self.db.security.addPermissionToRole("User", p) + # Turn filtering off + self.db.config.RDBMS_DEBUG_FILTER = True + filt = self.db.query.filter_with_permissions + r = filt(None, {}, sort=[('+', 'name')]) + # User may see own and public queries + self.assertEqual(r, ['5', '6', '4', '3', '2', '1']) + # XXX add sorting tests for other types # nuke and re-create db for restore