[PATCH saem_ref V2] [hooks] Fix crash on attempt to set an email to a user

Sylvain Thenault sylvain.thenault at logilab.fr
Fri Mar 10 10:04:26 CET 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1489006048 -3600
#      Wed Mar 08 21:47:28 2017 +0100
# Node ID a8a27140a4a4fd7b12c6b881e240b7fcbfb5b35a
# Parent  3ca8d29161df269f143468ed1665495b4279618f
[hooks] Fix crash on attempt to set an email to a user

because EmailAddress is part of some container through use_email.
'primary_email' has to be explicitly skipped to avoid adding clumsy code to
detect that it's not a 'border' relation.

Closes extranet #15224342

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
@@ -31,11 +31,12 @@ from cubicweb.hooks import metadata
 
 from cubes.skos.hooks import ReplaceExternalUriByEntityHook
 
 
 # skip relation involved in the logging itself, or mirroring relation
-IGNORE_RELATIONS = set(('used', 'generated', 'associated_with', 'mirror_of'))
+IGNORE_RELATIONS = set(('used', 'generated', 'associated_with', 'mirror_of',
+                        'primary_email'))
 
 
 @objectify_predicate
 def contained_relation(cls, req, rtype, eidfrom, eidto, **kwargs):
     """Predicate that returns True for relation from/to a container or contained entity.
@@ -73,17 +74,19 @@ def qualify_relation(subj, rtype, obj):
         if o_adapter is not None:
             break
     # then check if the relation is a parent relation
     if (s_adapter is not None and s_adapter.__regid__ == 'IContained'
             and (rtype, 'subject') in s_adapter.parent_relations):
-        assert o_adapter, ('parent relation %s of contained entity #%d does not link to a '
-                           'IContainer/IContained entity' % (rtype, subj.eid))
+        if o_adapter is None:
+            # relation actually outside a container (e.g. EmailAddress use_email CWUser)
+            return []
         return [('parent', 'object', o_adapter)]
     if (o_adapter is not None and o_adapter.__regid__ == 'IContained'
             and (rtype, 'object') in o_adapter.parent_relations):
-        assert s_adapter, ('parent relation %s of contained entity #%d does not link to a '
-                           'IContainer/IContained entity' % (rtype, obj.eid))
+        if s_adapter is None:
+            # relation actually outside a container (e.g. EmailAddress use_email CWUser)
+            return []
         return [('parent', 'subject', s_adapter)]
     # from here, we can assume rtype is not a parentship relation. Notice the relation may concerns
     # to distinct container
     assert s_adapter or o_adapter
     result = []
diff --git a/test/unittest_hooks.py b/test/unittest_hooks.py
--- a/test/unittest_hooks.py
+++ b/test/unittest_hooks.py
@@ -247,10 +247,19 @@ class SAEMRefHooksTC(CubicWebTC):
             self.assertEqual(scheme.ark, '67717/Matiere')
             self.assertEqual(scheme.cwuri, 'http://dcf/res/ark:/67717/Matiere')
             self.assertEqual(concept.ark, '67717/1234')
             self.assertEqual(concept.cwuri, 'http://dcf/res/ark:/67717/1234')
 
+    def test_user_email(self):
+        # EmailAddress belong to the Organisation graph, hence may conflict with hooks when linked
+        # to a user. This is a non-regression test checking that no error is raised on attempt to
+        # add an email to a user (which is not adaptable to IContained nor IContainer)
+        with self.admin_access.repo_cnx() as cnx:
+            cnx.create_entity('EmailAddress', address=u'admin at cubicweb.org',
+                              reverse_use_email=cnx.user.eid)
+            cnx.commit()
+
 
 class AuthorityRecordHookTC(CubicWebTC):
 
     def setup_database(self):
         with self.admin_access.cnx() as cnx:


More information about the saem-devel mailing list