[PATCH 1 of 3 saem v3] [security] Fix permissions of the use_profile relation

Philippe Pepiot philippe.pepiot at logilab.fr
Fri Apr 28 16:44:39 CEST 2017


On 04/27/2017 02:34 PM, Sylvain Thenault wrote:
> # HG changeset patch
> # User Sylvain Thénault <sylvain.thenault at logilab.fr>
> # Date 1492789034 -7200
> #      Fri Apr 21 17:37:14 2017 +0200
> # Node ID 365aacf5e5f9915c253359e572385d011a3f793d
> # Parent  4d82b62b0e74e4d39153fd0ba395926139ef032e
> # Available At http://hg.logilab.org/review/cubes/saem_ref
> #              hg pull http://hg.logilab.org/review/cubes/saem_ref -r 365aacf5e5f9
> [security] Fix permissions of  the use_profile relation
>
> They should be editable depending on the permission of the associated
> organization unit.
>
> Security is set using a decorator that will be reused in later changeset.
>
> Also, add use_profile relation to the structure that control copy, as it should
> not be copied.
>
> diff --git a/cubicweb_saem_ref/migration/0.15.3_Any.py b/cubicweb_saem_ref/migration/0.15.3_Any.py
> --- a/cubicweb_saem_ref/migration/0.15.3_Any.py
> +++ b/cubicweb_saem_ref/migration/0.15.3_Any.py
> @@ -1,4 +1,4 @@
> -for etype in ('ChronologicalRelation', 'HierarchicalRelation', 'AssociationRelation'):
> +for etype in ('ChronologicalRelation', 'HierarchicalRelation',
> +              'AssociationRelation', 'ConceptScheme',
> +              'use_profile'):
>      sync_schema_props_perms(etype)
> -
> -sync_schema_props_perms('ConceptScheme')

unrelated

> 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
> @@ -48,11 +48,11 @@ def publication_permissions(cls, groups=
>                         'X in_state ST, ST name "draft"'.format(groups)),
>      )
>      return cls
>
>
> -def authority_permissions(cls):
> +def authority_permissions_etype(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__ = {
> @@ -62,10 +62,23 @@ def authority_permissions(cls):
>          'delete': ('managers', ERQLExpression('U authority A, X authority A')),
>      }
>      return cls
>
>
> +def authority_permissions_rdef(cls):
> +    """Set __permissions__ of `cls` relation definition class to ensure user can
> +    create/delete provided its authority is the same as the relation subject's
> +    authority.
> +    """
> +    cls.__permissions__ = {
> +        'read': ('managers', 'users', 'guests'),
> +        'add': ('managers', RRQLExpression('U authority A, S authority A')),
> +        'delete': ('managers', RRQLExpression('U authority A, S 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()
> @@ -130,17 +143,17 @@ class Organization(EntityType):
>          'delete': ('managers', ),
>      }
>      name = String(required=True, fulltextindexed=True, unique=True)
>
>
> - at authority_permissions
> + at authority_permissions_etype
>  class OrganizationUnit(WorkflowableEntityType):
>      __unique_together__ = [('name', 'authority')]
>      name = String(required=True, fulltextindexed=True)
>
>
> - at authority_permissions
> + at authority_permissions_etype
>  class Agent(WorkflowableEntityType):
>      __unique_together__ = [('name', 'authority')]
>      name = String(required=True, fulltextindexed=True)
>
>
> @@ -445,10 +458,11 @@ publication_permissions(SEDAArchiveTrans
>
>
>  simplified_profile.default = True
>
>
> + at authority_permissions_rdef
>  class use_profile(RelationDefinition):
>      subject = 'OrganizationUnit'
>      object = 'SEDAArchiveTransfer'
>      cardinality = '**'
>      constraints = [RQLConstraint('S archival_role R, R name "deposit"'),
> diff --git a/cubicweb_saem_ref/site_cubicweb.py b/cubicweb_saem_ref/site_cubicweb.py
> --- a/cubicweb_saem_ref/site_cubicweb.py
> +++ b/cubicweb_saem_ref/site_cubicweb.py
> @@ -156,13 +156,14 @@ def get_store(cnx):
>  # causes problem because it belongs to several graphs with different compound
>  # implementation (using "container" relation or not)
>  seda.GRAPH_SKIP_ETYPES.add('Activity')
>  # also, the new_version_of relation should not be considered as part of the
>  # graph (as for e.g. container or clone_of)
> -seda.GRAPH_SKIP_RTYPES.add('new_version_of')
> -Entity.cw_skip_copy_for.append(('new_version_of', 'subject'))
> -Entity.cw_skip_copy_for.append(('new_version_of', 'object'))
> +for rtype in ('new_version_of', 'use_profile'):
> +    seda.GRAPH_SKIP_RTYPES.add(rtype)
> +    Entity.cw_skip_copy_for.append((rtype, 'subject'))
> +    Entity.cw_skip_copy_for.append((rtype, 'object'))
>
>
>  ####################################################################################################
>  # temporary monkey-patches #########################################################################
>  ####################################################################################################
> diff --git a/test/test_security.py b/test/test_security.py
> --- a/test/test_security.py
> +++ b/test/test_security.py
> @@ -157,34 +157,43 @@ class NonManagerUserTC(CubicWebTC):
>      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)
> +            profile = testutils.setup_profile(cnx)
>              cnx.commit()
> +            profile.cw_adapt_to('IWorkflowable').fire_transition('publish')
> +            cnx.commit()
> +
>              other_authority_eid = other_authority.eid
>              other_unit_eid = other_unit.eid
> +            profile_eid = profile.eid
>
>          with self.new_access(self.login).cnx() as cnx:
> +            roles = (u'archival', u'deposit')
>              unit = testutils.organization_unit(
> -                cnx, u'arch', archival_roles=[u'archival'], authority=self.authority_eid)
> +                cnx, u'arch', archival_roles=roles, authority=self.authority_eid)
>              cnx.commit()
> -            unit.cw_set(name=u'archi')
> +            unit.cw_set(name=u'archi',
> +                        use_profile=profile_eid)
>              cnx.commit()
>              unit.cw_delete()
>              cnx.commit()
>              arecord = testutils.authority_record(cnx, name=u'arch', kind=u'authority')
>              unit.cw_set(authority_record=arecord)
>              cnx.commit()
>
>              with self.assertUnauthorized(cnx):
>                  testutils.organization_unit(
> -                    cnx, u'other arch', archival_roles=[u'archival'], authority=other_authority_eid)
> +                    cnx, u'other arch', archival_roles=roles, 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_set(use_profile=profile_eid)
> +            with self.assertUnauthorized(cnx):
>                  other_unit.cw_delete()
>              with self.assertUnauthorized(cnx):
>                  other_arecord = testutils.authority_record(cnx, name=u'other arch',
>                                                             kind=u'authority')
>                  other_unit.cw_set(authority_record=other_arecord)
> diff --git a/test/unittest_entities_container.py b/test/unittest_entities_container.py
> --- a/test/unittest_entities_container.py
> +++ b/test/unittest_entities_container.py
> @@ -82,25 +82,26 @@ class TreeTC(CubicWebTC):
>              transfer = testutils.setup_profile(cnx)
>              unit, unit_alt, unit_alt_seq = testutils.create_archive_unit(transfer)
>              testutils.create_data_object(transfer)
>              cnx.commit()
>              transfer.cw_adapt_to('IWorkflowable').fire_transition('publish')
> -            agent = testutils.organization_unit(cnx, u'bob', archival_roles=['deposit'],
> -                                                use_profile=transfer)
> +            testutils.organization_unit(cnx, u'bob', archival_roles=['deposit'],
> +                                        use_profile=transfer)
>              cnx.commit()
>
>              clone = testutils.setup_profile(cnx, title=u'Clone', new_version_of=transfer)
>              cnx.commit()
>
>              # ark and cwuri should not have been copied
>              self.assertNotEqual(clone.ark, transfer.ark)
>              self.assertNotEqual(clone.cwuri, transfer.cwuri)
>
> -            # Everything else should have been copied (but other parts of the test live in the seda
> +            # Everything else beside some explicitly skipped relations should
> +            # have been copied (but other parts of the test live in the seda
>              # cube)
> -            self.assertEqual(clone.reverse_use_profile[0].eid,
> -                             agent.eid)
> +            self.assertEqual(clone.ark_naa[0].eid, transfer.ark_naa[0].eid)
> +            self.assertEqual(len(clone.reverse_use_profile), 0)
>
>
>  if __name__ == '__main__':
>      import unittest
>      unittest.main()
>



More information about the saem-devel mailing list