[PATCH saem v3] [security] Update security of the authority record kind relation

Sylvain Thenault sylvain.thenault at logilab.fr
Fri Apr 14 13:23:04 CEST 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1492070281 -7200
#      Thu Apr 13 09:58:01 2017 +0200
# Node ID 7e1a8f1c1102f0171f7285356b8437921dd71ebd
# Parent  99589d2ecaf8b423b184bbb6bc18af7d02c42008
# Available At http://hg.logilab.org/review/cubes/saem_ref
#              hg pull http://hg.logilab.org/review/cubes/saem_ref -r 7e1a8f1c1102
[security] Update security of the authority record kind relation

(still named agent_kind for historical reason).

In the eac cube, this relation can't be modified unless its value is 'unknown'.
Here we want to allow modification provided that the record isn't referenced by
authority_record relation which add constraint on the kind's value.

To achieve this, update the relation's permission to depends on its subject
entity's permission, then add a constraint to ensure consistency of
authority_record wrt kind's value.

Related to #16385734

diff --git a/cubicweb_saem_ref/i18n/en.po b/cubicweb_saem_ref/i18n/en.po
--- a/cubicweb_saem_ref/i18n/en.po
+++ b/cubicweb_saem_ref/i18n/en.po
@@ -180,10 +180,13 @@ msgid "This OrganizationUnit"
 msgstr ""
 
 msgid "This OrganizationUnit:"
 msgstr ""
 
+msgid "This record is used by a relation forbidding to change its type"
+msgstr ""
+
 msgid "View"
 msgstr ""
 
 msgid "Vocabularies"
 msgstr ""
diff --git a/cubicweb_saem_ref/i18n/fr.po b/cubicweb_saem_ref/i18n/fr.po
--- a/cubicweb_saem_ref/i18n/fr.po
+++ b/cubicweb_saem_ref/i18n/fr.po
@@ -186,10 +186,13 @@ msgid "This OrganizationUnit"
 msgstr "Cette unité administrative"
 
 msgid "This OrganizationUnit:"
 msgstr "Cette unité administrative :"
 
+msgid "This record is used by a relation forbidding to change its type"
+msgstr "Cette notice est utilisée dans une relation qui empêche de modifier son type"
+
 msgid "View"
 msgstr "Voir"
 
 msgid "Vocabularies"
 msgstr "Vocabulaires"
diff --git a/cubicweb_saem_ref/migration/0.15.1_Any.py b/cubicweb_saem_ref/migration/0.15.1_Any.py
--- a/cubicweb_saem_ref/migration/0.15.1_Any.py
+++ b/cubicweb_saem_ref/migration/0.15.1_Any.py
@@ -4,11 +4,11 @@ for agent in rql('DISTINCT Any X WHERE X
                  'Y eid YE, X eid >YE').entities():
     agent.cw_delete()
 commit()
 
 for ertype in ('generated', 'used', 'associated_with', 'place_address', 'new_version_of',
-               'authority_record',
+               'agent_kind', 'authority_record',
                'OrganizationUnit', 'Agent', 'ArkNameAssigningAuthority'):
     sync_schema_props_perms(ertype)
 
 
 sql("DELETE FROM container_relation WHERE EXISTS("
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
@@ -86,10 +86,26 @@ EmailAddress.remove_relation('alias')
 
 # Customization of eac schema.
 make_workflowable(eac.AuthorityRecord)
 groups_permissions(eac.AuthorityRecord)
 
+eac.agent_kind.__permissions__ = {
+    'read': ('managers', 'users', 'guests'),
+    'add': ('managers', RRQLExpression('U has_update_permission S')),
+    'delete': ('managers', RRQLExpression('U has_update_permission S')),
+}
+eac.agent_kind.constraints = [
+    RQLConstraint('NOT EXISTS(Z authority_record S)'
+                  ' OR '
+                  'EXISTS(A authority_record S, A is Agent, '
+                  '       O name "person")'
+                  ' OR '
+                  'EXISTS(OU authority_record S, OU is IN (Organization, OrganizationUnit), '
+                  '       O name "authority")',
+                  msg=_('This record is used by a relation forbidding to change its type')),
+]
+
 
 # Customization of skos schema.
 make_workflowable(ConceptScheme)
 publication_permissions(ConceptScheme)
 
diff --git a/test/test_security.py b/test/test_security.py
--- a/test/test_security.py
+++ b/test/test_security.py
@@ -45,10 +45,15 @@ class NonManagerUserTC(CubicWebTC):
             arecord = testutils.authority_record(cnx, name=u'a')
             cnx.commit()
             arecord.cw_set(record_id=u'123')
             cnx.commit()
 
+            # can change kind (unless used in constrained relation, but this is tested in
+            # unittest_schema)
+            arecord.cw_set(agent_kind=cnx.find('AgentKind', name=u'authority').one())
+            cnx.commit()
+
     def test_create_update_sedaprofile(self):
         with self.new_access(self.login).cnx() as cnx:
             profile = testutils.setup_profile(cnx)
             cnx.commit()
             profile.cw_set(user_annotation=u'meh')
diff --git a/test/unittest_schema.py b/test/unittest_schema.py
--- a/test/unittest_schema.py
+++ b/test/unittest_schema.py
@@ -90,10 +90,39 @@ class SchemaConstraintsTC(CubicWebTC):
             self.assertEqual(
                 pou.unrelated('authority_record', 'AuthorityRecord').one(),
                 cnx.find("AuthorityRecord", has_text=u"Direction de la communication").one(),
             )
 
+    def assertCantChangeRecordKind(self, arecord, kind):
+        cnx = arecord._cw
+        with self.assertValidationError(cnx) as cm:
+            arecord.cw_set(agent_kind=cnx.find('AgentKind', name=kind).one())
+        self.assertEqual(cm.exception.errors,
+                         {'agent_kind-subject':
+                          'This record is used by a relation forbidding to change its type'})
+
+    def test_authority_record_kind_consistency(self):
+        with self.admin_access.repo_cnx() as cnx:
+            arecord = testutils.authority_record(cnx, u'service', kind=u'authority')
+            testutils.organization_unit(cnx, u'unit', authority_record=arecord)
+            cnx.commit()
+
+            self.assertCantChangeRecordKind(arecord, u'person')
+
+            org = testutils.authority_with_naa(cnx)
+            org.cw_set(authority_record=arecord)
+            cnx.commit()
+            self.assertCantChangeRecordKind(arecord, u'person')
+
+            org.cw_set(authority_record=None)
+            arecord.cw_set(agent_kind=cnx.find('AgentKind', name=u'person').one())
+            cnx.commit()
+
+            testutils.agent(cnx, u'bob', authority_record=arecord)
+            cnx.commit()
+            self.assertCantChangeRecordKind(arecord, u'authority')
+
     def test_organization_unit_contact_point_in_the_same_authority(self):
         """Create two agents on two distinct authorities. Create an organization unit and check that
         interface will only show consistent proposal for contact point
         """
         with self.admin_access.repo_cnx() as cnx:


More information about the saem-devel mailing list