[PATCH 3 of 4 saem_ref] Prevent deprecation of a concept scheme used by a relation type

Denis Laxalde denis.laxalde at logilab.fr
Fri Apr 13 14:35:09 CEST 2018


# HG changeset patch
# User Denis Laxalde <denis.laxalde at logilab.fr>
# Date 1523620800 -7200
#      Fri Apr 13 14:00:00 2018 +0200
# Node ID a65281f047d17567eb836c7193817555453bd302
# Parent  ac4b89c371aaeba271419859171cc860e016f5e7
# Available At http://hg.logilab.org/review/cubes/saem_ref
#              hg pull http://hg.logilab.org/review/cubes/saem_ref -r a65281f047d1
# EXP-Topic CONSEJIRA-447
Prevent deprecation of a concept scheme used by a relation type

ConceptScheme entities may used to qualify a relation type through the
"scheme_relation_type" relation in order to restrict Concept entities as
possible targets of that relation. We must not be able to deprecate a
ConceptScheme used in such cases.

This is implemented in a hook because it's not possible to express this
in workflow permissions because group permissions would be checked first
and, if they succeed, RQL conditions will not be checked. Also, this is
arguably more an integrity check than a permission check, so a hook is
fine.

CONSEJIRA-447

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
@@ -482,6 +482,28 @@ class UnlinkDeprecatedProfileFromOrganiz
                          {'x': self.entity.for_entity.eid})
 
 
+class CheckSchemeRelationTypeBeforeDeprecation(hook.Hook):
+    """Prevent ConceptScheme deprecation if it used as a "scheme_relation_type".
+    """
+    __select__ = (
+        hook.Hook.__select__
+        & on_fire_transition('ConceptScheme', 'deprecate')
+    )
+    __regid__ = 'saem.check-scheme-relation-type-before-deprecation'
+    events = ('after_add_entity',)
+
+    def __call__(self):
+        rset = self._cw.execute('Any RT,N WHERE X scheme_relation_type RT, RT name N, X eid %(x)s',
+                                {'x': self.entity.for_entity.eid})
+        if rset:
+            msg = _('this concept scheme is used in the following relations: %(names)s')
+            raise ValidationError(
+                self.entity.for_entity.eid,
+                {'scheme_relation_type': msg},
+                msgargs={'names': ', '.join('%s #%d' % (name, eid) for eid, name in rset.rows)},
+            )
+
+
 # Relations deposit agent - archival agent  ####################################
 
 class DontDeleteUnitIfArchival(hook.Hook):
diff --git a/test/unittest_hooks.py b/test/unittest_hooks.py
--- a/test/unittest_hooks.py
+++ b/test/unittest_hooks.py
@@ -662,5 +662,25 @@ class SEDAArchiveTransferHooksTC(CubicWe
             self.assertFalse(organization_unit.use_profile)
 
 
+class ConceptSchemeWorkflowPermissionsTC(CubicWebTC):
+
+    configcls = PostgresApptestConfiguration
+
+    def test_cannot_deprecate_used_vocabulary(self):
+        with self.admin_access.cnx() as cnx:
+            scheme = testutils.scheme_for_type(cnx, u'seda_keyword_type_to', None,
+                                               u'type1')
+            cnx.commit()
+            scheme.cw_adapt_to('IWorkflowable').fire_transition('publish')
+            cnx.commit()
+            assert scheme.scheme_relation_type
+            with self.assertRaises(ValidationError) as cm:
+                scheme.cw_adapt_to('IWorkflowable').fire_transition('deprecate')
+            cnx.rollback()
+            self.assertIn(
+                'this concept scheme is used in the following relations: seda_keyword_type_to #',
+                str(cm.exception))
+
+
 if __name__ == '__main__':
     unittest.main()



More information about the saem-devel mailing list