[PATCH saem] [security] Change permissions so that only managers can add vocabularies

Sylvain Thenault sylvain.thenault at logilab.fr
Fri Apr 21 15:06:43 CEST 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1492767681 -7200
#      Fri Apr 21 11:41:21 2017 +0200
# Node ID d9e7c44c097e5c62a0e939d34dd4793c600cf539
# Parent  390a4f075ad402d3fc81dbb7e45f1634efa58e30
# Available At http://hg.logilab.org/review/cubes/saem_ref
#              hg pull http://hg.logilab.org/review/cubes/saem_ref -r d9e7c44c097e
[security] Change permissions so that only managers can add vocabularies

while users can still add/update concepts. Update doc and test accordingly.

Closes extranet #18369309

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
@@ -31,22 +31,23 @@ from cubicweb_eac import schema as eac
 from cubicweb_seda.schema import simplified_profile
 from cubicweb_seda.schema.seda2 import SEDAArchiveTransfer
 from cubicweb_compound import utils
 
 
-def publication_permissions(cls):
+def publication_permissions(cls, groups=('managers', 'users')):
     """Set __permissions__ of `cls` entity type class preventing modification
     when not in state "draft".
     """
+    groups = ', '.join('"{}"'.format(group) for group in groups)
     cls.__permissions__ = cls.__permissions__.copy()
     cls.__permissions__['update'] = (
-        ERQLExpression('U in_group G, G name IN ("managers", "users"), '
-                       'X in_state ST, ST name "draft"'),
+        ERQLExpression('U in_group G, G name IN ({}), '
+                       'X in_state ST, ST name "draft"'.format(groups)),
     )
     cls.__permissions__['delete'] = (
-        ERQLExpression('U in_group G, G name IN ("managers", "users"), '
-                       'X in_state ST, ST name "draft"'),
+        ERQLExpression('U in_group G, G name IN ({}), '
+                       'X in_state ST, ST name "draft"'.format(groups)),
     )
     return cls
 
 
 def authority_permissions(cls):
@@ -105,11 +106,12 @@ eac.agent_kind.constraints = [
 ]
 
 
 # Customization of skos schema.
 make_workflowable(ConceptScheme)
-publication_permissions(ConceptScheme)
+publication_permissions(ConceptScheme, groups=('managers',))
+ConceptScheme.__permissions__['add'] = ('managers',)
 
 
 class Organization(EntityType):
     __permissions__ = {
         'read': ('managers', 'users', 'guests'),
diff --git a/doc/security.rst b/doc/security.rst
--- a/doc/security.rst
+++ b/doc/security.rst
@@ -23,11 +23,13 @@ Utilisateurs "standards"
   être dans le groupe "utilisateurs". De plus pour le bon fonctionnement de certain aspects métier,
   il faut les rattacher à une autorité administrative.
 
 Un utilisateur standard (dans le groupe 'utilisateurs'), rattaché à une organisation, peut :
 
-* ajouter et mettre à jour des notices d'autorité, des profils SEDA et des vocabulaires SKOS ;
+* ajouter et mettre à jour des notices d'autorité, des profils SEDA ;
+
+* ajouter et mettre à jour des concepts dans des vocabulaires SKOS existants ;
 
 * ajouter et mettre à jour des agents et unités d'organisation appartement à la même autorité
   administrative que lui.
 
 
@@ -37,9 +39,10 @@ Administrateurs
 Les utilisateurs qui sont ajoutés dans le groupe "administrateurs" ont des droits supplémentaires
 sur la plate-forme, notamment :
 
 * ajouter et modifier des utilisateurs ;
 
-* ajouter et modifier des autorités d'assignement de noms (**ARK NAA**) et des autorités administratives.
+* ajouter et modifier des autorités d'assignement de noms (**ARK NAA**), des
+  autorités administratives et des vocabulaires.
 
 Les actions spécifiques à l'administrateur sont accessibles dans l'interface web via la section
 "Administration" de la page d'accueil une fois authentifié.
diff --git a/test/test_security.py b/test/test_security.py
--- a/test/test_security.py
+++ b/test/test_security.py
@@ -69,24 +69,26 @@ class NonManagerUserTC(CubicWebTC):
                                                      u'type1')
             cnx.commit()
             type_concept = admin_scheme.reverse_in_scheme[0]
 
         with self.new_access(self.login).cnx() as cnx:
-            scheme = testutils.setup_scheme(cnx, u'my scheme',
-                                            u'lab1', u'lab2', code_keyword_type=type_concept)
-            cnx.commit()
-            scheme.add_concept(u'lab3')
-            cnx.commit()
-            scheme.cw_set(code_keyword_type=None)
+            with self.assertUnauthorized(cnx):
+                testutils.setup_scheme(cnx, u'my scheme',
+                                       u'lab1', u'lab2')
+
+            admin_scheme = cnx.entity_from_eid(admin_scheme.eid)
+            type_concept = cnx.entity_from_eid(type_concept.eid)
+            with self.assertUnauthorized(cnx):
+                admin_scheme.cw_set(title=u'code keyword types')
+            with self.assertUnauthorized(cnx):
+                admin_scheme.cw_set(code_keyword_type=type_concept)
+
+            admin_scheme.add_concept(u'type2')
             cnx.commit()
 
-            admin_scheme = cnx.entity_from_eid(admin_scheme.eid)
-            admin_scheme.cw_set(title=u'code keyword types')
-            cnx.commit()
-            admin_scheme.add_concept(u'type2')
-            cnx.commit()
-            admin_scheme.cw_set(code_keyword_type=type_concept)
+            cnx.create_entity('Label', kind=u'alternative', label=u'Le type n.1',
+                              label_of=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')
@@ -171,12 +173,15 @@ class NonManagerUserTC(CubicWebTC):
 
             with self.assertUnauthorized(cnx):
                 activity.cw_delete()
 
     def test_cannot_create_activities(self):
+        with self.admin_access.cnx() as cnx:
+            scheme = testutils.setup_scheme(cnx, u'my scheme')
+            cnx.commit()
         with self.new_access(self.login).cnx() as cnx:
-            scheme = testutils.setup_scheme(cnx, u'my scheme')
+            scheme = cnx.entity_from_eid(scheme.eid)
             concept = scheme.add_concept(u'lab3')
             profile = testutils.setup_profile(cnx)
             cnx.commit()
 
             for entity in (scheme, concept, profile):
diff --git a/test/unittest_hooks.py b/test/unittest_hooks.py
--- a/test/unittest_hooks.py
+++ b/test/unittest_hooks.py
@@ -314,11 +314,11 @@ class EntityLifeCycleTC(CubicWebTC):
             cnx.commit()
             self.bob_eid = bob.eid
 
     def _check_create(self, cnx, eid, msg):
         activity = cnx.find('Activity', type=u'create', used=eid).one()
-        self.assertEqual(activity.associated_with[0].eid, self.bob_eid)
+        self.assertEqual(activity.associated_with[0].eid, cnx.user.eid)
         self.assertEqual(activity.generated[0].eid, eid)
         self.assertEqual(activity.description, msg)
 
     def _check_modification(self, cnx, eid, msg):
         activity = cnx.find('Activity', type=u'modify', used=eid).one()
@@ -451,16 +451,20 @@ class EntityLifeCycleTC(CubicWebTC):
             cnx.commit()
             self.failIf(cnx.find('Activity', type=u'modify',
                                  used=authorityrecord.eid))
 
     def test_concept(self):
-        with self.new_access(u'bob').repo_cnx() as cnx:
+        with self.admin_access.repo_cnx() as cnx:
             scheme = cnx.create_entity('ConceptScheme', title=u'my thesaurus',
                                        ark_naa=testutils.naa(cnx))
             cnx.commit()
             # concept scheme creation
             self._check_create(cnx, scheme.eid, 'created conceptscheme')
+
+        with self.new_access(u'bob').repo_cnx() as cnx:
+            scheme = cnx.entity_from_eid(scheme.eid)
+
             concept = scheme.add_concept(u'hello')
             cnx.commit()
             # concept scheme add concept
             self._check_modification(cnx, scheme.eid, 'added in_scheme_object')
             # concept creation
@@ -486,11 +490,11 @@ class EntityLifeCycleTC(CubicWebTC):
             cnx.commit()
             self._check_modification(cnx, transfer.eid,
                                      'modified title')
 
     def test_nonregr_concept_container(self):
-        with self.new_access(u'bob').repo_cnx() as cnx:
+        with self.admin_access.repo_cnx() as cnx:
             scheme = cnx.create_entity('ConceptScheme', title=u'my thesaurus',
                                        ark_naa=testutils.naa(cnx))
             concept = scheme.add_concept(u'hello')
             cnx.commit()
             concept.cw_delete()


More information about the saem-devel mailing list