# HG changeset patch # User Sylvain Thénault # Date 1479736527 -3600 # Node ID dfcc3f74b3c8a16e295e7e2944900ea3f9d7da57 # Parent 002007272a766de4aa60845d1ffe9f67110f8afa [schema/optimization] Wrap rql expressions into EXISTS node when checking individual permissions Some RQL expression may retrieve several results. It makes sense to wrap them into an EXISTS node to optimized things a bit. This is already done by security insertion of 'read' rql expressions. diff -r 002007272a76 -r dfcc3f74b3c8 cubicweb/schema.py --- a/cubicweb/schema.py Fri Nov 18 17:44:52 2016 +0100 +++ b/cubicweb/schema.py Mon Nov 21 14:55:27 2016 +0100 @@ -325,6 +325,7 @@ keyarg = None rqlst.recover() return rql, found, keyarg + rqlst.where = nodes.Exists(rqlst.where) return rqlst.as_string(), None, None def _check(self, _cw, **kwargs): diff -r 002007272a76 -r dfcc3f74b3c8 cubicweb/test/unittest_schema.py --- a/cubicweb/test/unittest_schema.py Fri Nov 18 17:44:52 2016 +0100 +++ b/cubicweb/test/unittest_schema.py Mon Nov 21 14:55:27 2016 +0100 @@ -575,5 +575,31 @@ for r, role in schema[etype].composite_rdef_roles])) +class CWShemaTC(CubicWebTC): + + def test_transform_has_permission_match(self): + with self.admin_access.repo_cnx() as cnx: + eschema = cnx.vreg.schema['EmailAddress'] + rql_exprs = eschema.get_rqlexprs('update') + self.assertEqual(len(rql_exprs), 1) + self.assertEqual(rql_exprs[0].expression, + 'P use_email X, U has_update_permission P') + rql, found, keyarg = rql_exprs[0].transform_has_permission() + self.assertEqual(rql, 'Any X,P WHERE P use_email X, X eid %(x)s') + self.assertEqual(found, [(u'update', 1)]) + self.assertEqual(keyarg, None) + + def test_transform_has_permission_no_match(self): + with self.admin_access.repo_cnx() as cnx: + eschema = cnx.vreg.schema['EmailAddress'] + rql_exprs = eschema.get_rqlexprs('read') + self.assertEqual(len(rql_exprs), 1) + self.assertEqual(rql_exprs[0].expression, + 'U use_email X') + rql, found, keyarg = rql_exprs[0].transform_has_permission() + self.assertEqual(rql, 'Any X WHERE EXISTS(U use_email X, X eid %(x)s, U eid %(u)s)') + self.assertEqual(found, None) + self.assertEqual(keyarg, None) + if __name__ == '__main__': unittest_main()