[schema/optimization] Wrap rql expressions into EXISTS node when checking individual permissions
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 21 Nov 2016 14:55:27 +0100
changeset 11852 dfcc3f74b3c8
parent 11851 002007272a76
child 11853 c71339453c1e
[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.
cubicweb/schema.py
cubicweb/test/unittest_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):
--- 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()