[PATCH 6 of 6 saem_ref] [schema] Rely on security defined in the eac cube

Sylvain Thenault sylvain.thenault at logilab.fr
Wed Mar 8 13:59:04 CET 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1488972668 -3600
#      Wed Mar 08 12:31:08 2017 +0100
# Node ID 14e7a4ba8ca43cb1f97f5ceee140c4c853652481
# Parent  87c611021e511cee3e6cb00cea92c00f8a2bb54a
[schema] Rely on security defined in the eac cube

Beside top-level entity, we now only have to define permissions for
ConceptScheme since both eac and seda have sensible defaults for their compound
tree.

diff --git a/cubicweb_saem_ref/__init__.py b/cubicweb_saem_ref/__init__.py
--- a/cubicweb_saem_ref/__init__.py
+++ b/cubicweb_saem_ref/__init__.py
@@ -17,14 +17,21 @@
 """cubicweb-saem_ref application package
 
 Référenciel de Système d'Archivage Électronique Mutualisé
 """
 
+from functools import partial
+
 from six import text_type
 
 from logilab.common.registry import objectify_predicate
 
+from cubes.compound import CompositeGraph
+
+
+ConceptSchemeGraph = partial(CompositeGraph, skiprtypes=('generated', 'used'))
+
 
 def cwuri_url(entity):
     """Return an absolute URL for entity's cwuri, handling case where ark is directly used, and so
     URL should be generated from it.
     """
diff --git a/cubicweb_saem_ref/hooks.py b/cubicweb_saem_ref/hooks.py
--- a/cubicweb_saem_ref/hooks.py
+++ b/cubicweb_saem_ref/hooks.py
@@ -456,15 +456,13 @@ class AuthorityRecordUsedBySetDefault(ho
 
 def registration_callback(vreg):
     vreg.register_all(globals().values(), __name__)
 
     from cubicweb.server import ON_COMMIT_ADD_RELATIONS
-    from . import PERMISSIONS_GRAPHS
     from cubicweb_compound import utils
+    from . import ConceptSchemeGraph
 
     # Add relations involved in a composite graph with security setup to "on
     # commit" check step.
-    schema = vreg.schema
-    for etype, graph_def in PERMISSIONS_GRAPHS.iteritems():
-        graph = graph_def(schema)
-        for rdef, __ in utils.mandatory_rdefs(schema, graph.parent_structure(etype)):
-            ON_COMMIT_ADD_RELATIONS.add(rdef.rtype)
+    graph = ConceptSchemeGraph(vreg.schema)
+    for rdef, __ in utils.mandatory_rdefs(vreg.schema, graph.parent_structure('ConceptScheme')):
+        ON_COMMIT_ADD_RELATIONS.add(rdef.rtype)
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
@@ -27,11 +27,10 @@ from cubicweb.schemas.base import Extern
 
 from cubes.skos.schema import ConceptScheme
 from cubicweb_eac.schema import AuthorityRecord, NameEntry
 from cubicweb_seda.schema import simplified_profile
 from cubicweb_seda.schema.seda2 import SEDAArchiveTransfer
-from . import PERMISSIONS_GRAPHS
 from cubicweb_compound import utils
 
 
 def publication_permissions(cls):
     """Set __permissions__ of `cls` entity type class preventing modification
@@ -388,16 +387,14 @@ class new_version_of(RelationDefinition)
     inlined = True
 
 
 def post_build_callback(schema):
     schema['simplified_profile'].rdefs['SEDAArchiveTransfer', 'Boolean'].default = True  # XXX
-    for etype, graph in PERMISSIONS_GRAPHS.iteritems():
-        if etype == 'SEDAArchiveTransfer':
-            # this compound graph as a generic 'container' relation on which security is based
-            continue
-        utils.graph_set_etypes_update_permissions(schema, graph(schema), etype)
-        utils.graph_set_write_rdefs_permissions(schema, graph(schema), etype)
+    from . import ConceptSchemeGraph
+    graph = ConceptSchemeGraph(schema)
+    utils.graph_set_etypes_update_permissions(schema, graph, 'ConceptScheme')
+    utils.graph_set_write_rdefs_permissions(schema, graph, 'ConceptScheme')
 
     # permissions override
     schema['Label'].set_action_permissions('delete', ('managers', 'users'))
     for rtype in ('in_scheme', 'broader_concept', 'label_of'):
         for rdef in schema[rtype].rdefs.values():
diff --git a/test/unittest_schema.py b/test/unittest_schema.py
--- a/test/unittest_schema.py
+++ b/test/unittest_schema.py
@@ -20,12 +20,12 @@ from datetime import date
 from contextlib import contextmanager
 
 from cubicweb import ValidationError, Unauthorized
 from cubicweb.devtools.testlib import CubicWebTC
 
-from cubicweb_saem_ref import PERMISSIONS_GRAPHS
 from cubicweb_compound.utils import optional_relations, graph_relations
+from cubicweb_saem_ref import ConceptSchemeGraph
 
 import testutils
 
 
 @contextmanager
@@ -191,106 +191,41 @@ class AuthorityRecordTC(CubicWebTC):
             for search in (u'guenievre', u'europe', u'place', u'function', u'legal status'):
                 with self.subTest(search=search):
                     self.assertEqual(cnx.execute('AuthorityRecord X WHERE X has_text %(search)s',
                                                  {'search': search}).one().eid, agent.eid)
 
-    def test_graph_structure(self):
-        graph = PERMISSIONS_GRAPHS['AuthorityRecord'](self.schema)
-        expected = {
-            'AgentFunction': {('function_agent', 'subject'): set(['AuthorityRecord'])},
-            'AgentPlace': {('place_agent', 'subject'): set(['AuthorityRecord'])},
-            'Citation': {('has_citation', 'object'): set([
-                'GeneralContext', 'Mandate', 'Occupation', 'AgentFunction',
-                'AgentPlace', 'History', 'LegalStatus',
-            ])},
-            'EACOtherRecordId': {('eac_other_record_id_of', 'subject'):
-                                 set(['AuthorityRecord'])},
-            'EACResourceRelation': {('resource_relation_agent', 'subject'):
-                                    set(['AuthorityRecord'])},
-            'EACSource': {('source_agent', 'subject'): set(['AuthorityRecord'])},
-            'GeneralContext': {('general_context_of', 'subject'): set(['AuthorityRecord'])},
-            'History': {('history_agent', 'subject'): set(['AuthorityRecord'])},
-            'LegalStatus': {('legal_status_agent', 'subject'): set(['AuthorityRecord'])},
-            'Mandate': {('mandate_agent', 'subject'): set(['AuthorityRecord'])},
-            'NameEntry': {('name_entry_for', 'subject'): set(['AuthorityRecord'])},
-            'Occupation': {('occupation_agent', 'subject'): set(['AuthorityRecord'])},
-            'PostalAddress': {('place_address', 'object'): set(['AgentPlace'])},
-            'Structure': {('structure_agent', 'subject'): set(['AuthorityRecord'])},
-        }
-        struct = dict(
-            (k, dict((rel, set(targets)) for rel, targets in v.items()))
-            for k, v in graph.parent_structure('AuthorityRecord').items())
-        self.assertEqual(struct, expected)
-
-    def test_optional_relations(self):
-        graph = PERMISSIONS_GRAPHS['AuthorityRecord'](self.schema)
-        structure = graph.parent_structure('AuthorityRecord')
-        opts = optional_relations(self.schema, structure)
-        expected = {}
-        self.assertEqual(opts, expected)
-
-    def test_relations_consistency(self):
-        graph = PERMISSIONS_GRAPHS['AuthorityRecord'](self.schema)
-        structure = graph.parent_structure('AuthorityRecord')
-        structurals, optionals, mandatories = graph_relations(
-            self.schema, structure)
-        self.assertEqual(structurals - optionals, mandatories)
-
 
 class ConceptSchemeTC(CubicWebTC):
 
     def test_graph_structure(self):
-        graph = PERMISSIONS_GRAPHS['ConceptScheme'](self.schema)
+        graph = ConceptSchemeGraph(self.schema)
         expected = {
             'Concept': {('in_scheme', 'subject'): ['ConceptScheme']},
             'Label': {('label_of', 'subject'): ['Concept']},
         }
         self.assertEqual(graph.parent_structure('ConceptScheme'),
                          expected)
 
     def test_optional_relations(self):
-        graph = PERMISSIONS_GRAPHS['ConceptScheme'](self.schema)
+        graph = ConceptSchemeGraph(self.schema)
         opts = optional_relations(self.schema,
                                   graph.parent_structure('ConceptScheme'))
         expected = {}
         self.assertEqual(opts, expected)
 
     def test_relations_consistency(self):
-        graph = PERMISSIONS_GRAPHS['ConceptScheme'](self.schema)
+        graph = ConceptSchemeGraph(self.schema)
         structure = graph.parent_structure('ConceptScheme')
         structurals, optionals, mandatories = graph_relations(
             self.schema, structure)
         self.assertEqual(structurals - optionals, mandatories)
 
 
 class SecurityTC(CubicWebTC):
     """Test case for permissions set in the schema"""
     assertUnauthorized = assertUnauthorized
 
-    def test_agentkind_type(self):
-        with self.admin_access.cnx() as cnx:
-            kind = cnx.find('AgentKind', name=u'person').one()
-            # no one can update nor delete a kind
-            with self.assertRaises(Unauthorized):
-                kind.cw_set(name=u'gloups')
-                cnx.commit()
-            cnx.rollback()
-            with self.assertRaises(Unauthorized):
-                kind.cw_delete()
-                cnx.commit()
-            cnx.rollback()
-
-    def test_agent_kind_relation(self):
-        """Test we can only change kind from unknown to another."""
-        with self.admin_access.repo_cnx() as cnx:
-            agent = testutils.authority_record(cnx, u'bob', kind=u'unknown-agent-kind')
-            cnx.commit()
-            agent.cw_set(agent_kind=cnx.find('AgentKind', name=u'person').one())
-            cnx.commit()
-            with self.assertRaises(Unauthorized):
-                agent.cw_set(agent_kind=cnx.find('AgentKind', name=u'authority').one())
-
     def test_authority_type(self):
         with self.admin_access.repo_cnx() as cnx:
             self.create_user(cnx, login=u'user', groups=('users',))
             cnx.commit()
         with self.new_access('user').client_cnx() as cnx:
@@ -357,12 +292,10 @@ class SecurityTC(CubicWebTC):
         with self.new_access('toto').client_cnx() as cnx:
             agent = cnx.find('AuthorityRecord', has_text=u'bob').one()
             # guest user can't modify an authority record
             with self.assertUnauthorized(cnx):
                 agent.cw_set(record_id=u'bobby')
-            with self.assertUnauthorized(cnx):
-                agent.reverse_function_agent[0].cw_set(name=u'director')
 
     def test_authority_record_wf_permissions(self):
         with self.admin_access.repo_cnx() as cnx:
             self.create_user(cnx, login=u'toto', groups=('users', 'guests'),
                              authority=testutils.authority_with_naa(cnx))
@@ -393,36 +326,10 @@ class SecurityTC(CubicWebTC):
         with self.new_access('toto').client_cnx() as cnx:
             profile = cnx.find('SEDAArchiveTransfer', title=u'pp').one()
             with self.assertUnauthorized(cnx):
                 profile.cw_set(title=u'qq')
 
-    def test_update_child(self):
-        with self.admin_access.repo_cnx() as cnx:
-            self.create_user(cnx, login=u'toto', groups=('users', 'guests'),
-                             authority=testutils.authority_with_naa(cnx))
-            cnx.commit()
-        with self.new_access('toto').client_cnx() as cnx:
-            record = testutils.authority_record(cnx, u'bob')
-            function = cnx.create_entity('AgentFunction', name=u'boss',
-                                         function_agent=record)
-            cnx.commit()
-            # Draft -> OK.
-            function.cw_set(name=u'grouyo')
-            cnx.commit()
-            cnx.create_entity('GeneralContext', content=u'plop',
-                              general_context_of=record)
-            cnx.commit()
-            iwf = record.cw_adapt_to('IWorkflowable')
-            iwf.fire_transition('publish')
-            cnx.commit()
-            # Published -> still OK for record.
-            record.cw_set(record_id=u'big boss')
-            cnx.commit()
-            cnx.create_entity('History', text=u'yellow sponge',
-                              history_agent=record)
-            cnx.commit()
-
     def test_sedaprofile_wf_permissions(self):
         with self.admin_access.repo_cnx() as cnx:
             profile = testutils.setup_profile(cnx, title=u'pp')
             cnx.commit()
             # Profile in draft, modifications are allowed.


More information about the saem-devel mailing list