[wf] test in_state consistency 3.5
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 25 Aug 2009 13:35:01 +0200
branch3.5
changeset 2983 b458631fe347
parent 2982 1768dbe8e9b3
child 2984 31c24caf6961
[wf] test in_state consistency
entities/test/unittest_wfobjs.py
server/hooks.py
--- a/entities/test/unittest_wfobjs.py	Tue Aug 25 13:34:19 2009 +0200
+++ b/entities/test/unittest_wfobjs.py	Tue Aug 25 13:35:01 2009 +0200
@@ -103,6 +103,16 @@
         trinfo = self._test_manager_deactivate(user)
         self.assertEquals(trinfo.transition, None)
 
+    def test_set_in_state_bad_wf(self):
+        wf = add_wf(self, 'CWUser')
+        s = wf.add_state(u'foo', initial=True)
+        self.commit()
+        ex = self.assertRaises(ValidationError, self.session().unsafe_execute,
+                               'SET X in_state S WHERE X eid %(x)s, S eid %(s)s',
+                               {'x': self.user().eid, 's': s.eid}, 'x')
+        self.assertEquals(ex.errors, {'in_state': "state doesn't belong to entity's workflow. "
+                                      "You may want to set a custom workflow for this entity first."})
+
     def test_fire_transition(self):
         user = self.user()
         user.fire_transition('deactivate', comment=u'deactivate user')
--- a/server/hooks.py	Tue Aug 25 13:34:19 2009 +0200
+++ b/server/hooks.py	Tue Aug 25 13:35:01 2009 +0200
@@ -515,6 +515,26 @@
                                                    state.eid)
 
 
+def before_add_in_state(session, eidfrom, rtype, eidto):
+    """check state apply"""
+    nocheck = session.transaction_data.setdefault('skip-security', ())
+    if (eidfrom, 'in_state', eidto) in nocheck:
+        # state changed through TrInfo insertion, so we already know it's ok
+        print 'skip in_state check'
+        return
+    entity = session.entity_from_eid(eidfrom)
+    mainwf = entity.main_workflow
+    if mainwf is None:
+        msg = session._('entity has no workflow set')
+        raise ValidationError(entity.eid, {None: msg})
+    for wf in mainwf.iter_workflows():
+        if wf.state_by_eid(eidto):
+            break
+    else:
+        msg = session._("state doesn't belong to entity's workflow. You may "
+                        "want to set a custom workflow for this entity first.")
+        raise ValidationError(eidfrom, {'in_state': msg})
+
 def set_initial_state_after_add(session, entity):
     SetInitialStateOp(session, entity=entity)
 
@@ -581,6 +601,7 @@
         hm.register_hook(set_custom_workflow, 'after_add_relation', 'custom_workflow')
         hm.register_hook(del_custom_workflow, 'after_delete_relation', 'custom_workflow')
         hm.register_hook(after_del_workflow, 'after_delete_entity', 'Workflow')
+        hm.register_hook(before_add_in_state, 'before_add_relation', 'in_state')
 
 
 # CWProperty hooks #############################################################