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

Sylvain Thénault sylvain.thenault at logilab.fr
Thu Mar 9 11:04:29 CET 2017



Le 08/03/2017 à 13:59, Sylvain Thenault a écrit :
> # 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
> +
this should be spelled cubicweb_compound, I'll send a V2 of this single
patch

> +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.
>

-- 
Sylvain Thénault, LOGILAB, Paris (01.45.32.03.12) - Toulouse (05.62.17.16.42)
Formations Python, Debian, Méth. Agiles: http://www.logilab.fr/formations
Développement logiciel sur mesure:       http://www.logilab.fr/services
CubicWeb, the semantic web framework:    http://www.cubicweb.org



More information about the saem-devel mailing list