[PATCH 4 of 4 saem_ref] [security] Set permissions on OrganizationUnit and Agent according to user's authority

Sylvain Thenault sylvain.thenault at logilab.fr
Wed Apr 12 09:07:46 CEST 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1491979091 -7200
#      Wed Apr 12 08:38:11 2017 +0200
# Node ID bab1f00019729b02899bd025614502ac8a7700c8
# Parent  640ee7534e097d84f9c30d91d714749ec20d1ee2
[security] Set permissions on OrganizationUnit and Agent according to user's authority

Related to extranet #16383144

diff --git a/cubicweb_saem_ref/schema.py b/cubicweb_saem_ref/schema.py
--- a/cubicweb_saem_ref/schema.py
+++ b/cubicweb_saem_ref/schema.py
@@ -47,10 +47,24 @@ def publication_permissions(cls):
                        'X in_state ST, ST name "draft"'),
     )
     return cls
 
 
+def authority_permissions(cls):
+    """Set __permissions__ of `cls` entity type class to ensure user can
+    create/update/delete provided its authority is the same as the entity's
+    authority.
+    """
+    cls.__permissions__ = {
+        'read': ('managers', 'users', 'guests'),
+        'add': ('managers', ERQLExpression('U authority A, X authority A')),
+        'update': ('managers', ERQLExpression('U authority A, X authority A')),
+        'delete': ('managers', ERQLExpression('U authority A, X authority A')),
+    }
+    return cls
+
+
 def groups_permissions(cls):
     """Set __permissions__ of `cls` entity type class preventing modification
     when user is not in managers or users group.
     """
     cls.__permissions__ = cls.__permissions__.copy()
@@ -88,22 +102,17 @@ class Organization(EntityType):
         'delete': ('managers', ),
     }
     name = String(required=True, fulltextindexed=True, unique=True)
 
 
+ at authority_permissions
 class OrganizationUnit(WorkflowableEntityType):
-    __permissions__ = {
-        'read': ('managers', 'users', 'guests'),
-        'add': ('managers', ),
-        'update': ('managers', ),
-        'delete': ('managers', ),
-    }
     __unique_together__ = [('name', 'authority')]
     name = String(required=True, fulltextindexed=True)
 
 
- at groups_permissions
+ at authority_permissions
 class Agent(WorkflowableEntityType):
     __unique_together__ = [('name', 'authority')]
     name = String(required=True, fulltextindexed=True)
 
 
diff --git a/test/test_security.py b/test/test_security.py
--- a/test/test_security.py
+++ b/test/test_security.py
@@ -81,21 +81,61 @@ class NonManagerUserTC(CubicWebTC):
             cnx.commit()
             admin_scheme.cw_set(code_keyword_type=type_concept)
             cnx.commit()
 
     def test_create_update_agent_in_own_organization(self):
+        with self.admin_access.cnx() as cnx:
+            other_authority = testutils.authority_with_naa(cnx, name=u'other authority')
+            other_agent = testutils.agent(cnx, u'bob', authority=other_authority)
+            cnx.commit()
+            other_authority_eid = other_authority.eid
+            other_agent_eid = other_agent.eid
+
         with self.new_access(self.login).cnx() as cnx:
             agent = testutils.agent(cnx, u'bob', authority=self.authority_eid)
             cnx.commit()
             agent.cw_set(name=u'bobby')
             cnx.commit()
+            agent.cw_delete()
+            cnx.commit()
 
-    def test_cannot_create_organizationunit(self):
+            with self.assertUnauthorized(cnx):
+                testutils.agent(cnx, u'other bob', authority=other_authority_eid)
+
+            other_agent = cnx.entity_from_eid(other_agent_eid)
+            with self.assertUnauthorized(cnx):
+                other_agent.cw_set(name=u'bobby')
+            with self.assertUnauthorized(cnx):
+                other_agent.cw_delete()
+
+    def test_create_update_organizationunit_in_own_organization(self):
+        with self.admin_access.cnx() as cnx:
+            other_authority = testutils.authority_with_naa(cnx, name=u'other authority')
+            other_unit = testutils.organization_unit(
+                cnx, u'arch', archival_roles=[u'archival'], authority=other_authority)
+            cnx.commit()
+            other_authority_eid = other_authority.eid
+            other_unit_eid = other_unit.eid
+
         with self.new_access(self.login).cnx() as cnx:
+            unit = testutils.organization_unit(
+                cnx, u'arch', archival_roles=[u'archival'], authority=self.authority_eid)
+            cnx.commit()
+            unit.cw_set(name=u'archi')
+            cnx.commit()
+            unit.cw_delete()
+            cnx.commit()
+
             with self.assertUnauthorized(cnx):
                 testutils.organization_unit(
-                    cnx, u'arch', archival_roles=(u'archival', ))
+                    cnx, u'other arch', archival_roles=[u'archival'], authority=other_authority_eid)
+
+            other_unit = cnx.entity_from_eid(other_unit_eid)
+            with self.assertUnauthorized(cnx):
+                other_unit.cw_set(name=u'archi')
+            with self.assertUnauthorized(cnx):
+                other_unit.cw_delete()
 
     def test_cannot_modify_activities(self):
         with self.new_access(self.login).cnx() as cnx:
             arecord = testutils.authority_record(cnx, name=u'a')
             cnx.commit()


More information about the saem-devel mailing list