author | Sylvain Thénault <sylvain.thenault@logilab.fr> |
Tue, 09 Feb 2010 12:39:23 +0100 | |
branch | stable |
changeset 4516 | 00d2ef9f1754 |
parent 4514 | 5bb1d39ea0da |
permissions | -rw-r--r-- |
0 | 1 |
"""Core hooks: check schema validity, unsure we are not deleting necessary |
2 |
entities... |
|
3 |
||
4 |
:organization: Logilab |
|
4212
ab6573088b4a
update copyright: welcome 2010
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4119
diff
changeset
|
5 |
:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
0 | 6 |
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
1977
606923dff11b
big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1802
diff
changeset
|
7 |
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
0 | 8 |
""" |
9 |
__docformat__ = "restructuredtext en" |
|
10 |
||
4489
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
11 |
from threading import Lock |
1016
26387b836099
use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents:
479
diff
changeset
|
12 |
from datetime import datetime |
0 | 13 |
|
14 |
from cubicweb import UnknownProperty, ValidationError, BadConnectionId |
|
3978
2c95e3033f64
finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3887
diff
changeset
|
15 |
from cubicweb.schema import RQLConstraint, RQLUniqueConstraint |
0 | 16 |
from cubicweb.server.pool import Operation, LateOperation, PreCommitOperation |
3773
14fde27a70a2
don't allow that even with cow powers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3693
diff
changeset
|
17 |
from cubicweb.server.hookhelper import (check_internal_entity, |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
18 |
get_user_sessions, rproperty) |
0 | 19 |
from cubicweb.server.repository import FTIndexEntityOp |
20 |
||
2605
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
21 |
# special relations that don't have to be checked for integrity, usually |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
22 |
# because they are handled internally by hooks (so we trust ourselves) |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
23 |
DONT_CHECK_RTYPES_ON_ADD = set(('owned_by', 'created_by', |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
24 |
'is', 'is_instance_of', |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
25 |
'wf_info_for', 'from_state', 'to_state')) |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
26 |
DONT_CHECK_RTYPES_ON_DEL = set(('is', 'is_instance_of', |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
27 |
'wf_info_for', 'from_state', 'to_state')) |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
28 |
|
4489
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
29 |
_UNIQUE_CONSTRAINTS_LOCK = Lock() |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
30 |
|
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
31 |
class _ReleaseUniqueConstraintsHook(Operation): |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
32 |
def commit_event(self): |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
33 |
pass |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
34 |
def postcommit_event(self): |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
35 |
_release_unique_cstr_lock(self.session) |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
36 |
def rollback_event(self): |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
37 |
_release_unique_cstr_lock(self.session) |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
38 |
|
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
39 |
def _acquire_unique_cstr_lock(session): |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
40 |
"""acquire the _UNIQUE_CONSTRAINTS_LOCK for the session. |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
41 |
|
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
42 |
This lock used to avoid potential integrity pb when checking |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
43 |
RQLUniqueConstraint in two different transactions, as explained in |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
44 |
http://intranet.logilab.fr/jpl/ticket/36564 |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
45 |
""" |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
46 |
asession = session.actual_session() |
4514
5bb1d39ea0da
fix constraint hook: a session may be involved in multiple transaction at time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4496
diff
changeset
|
47 |
if 'uniquecstrholder' in asession.transaction_data: |
4489
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
48 |
return |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
49 |
_UNIQUE_CONSTRAINTS_LOCK.acquire() |
4514
5bb1d39ea0da
fix constraint hook: a session may be involved in multiple transaction at time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4496
diff
changeset
|
50 |
asession.transaction_data['uniquecstrholder'] = True |
4489
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
51 |
# register operation responsible to release the lock on commit/rollback |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
52 |
_ReleaseUniqueConstraintsHook(asession) |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
53 |
|
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
54 |
def _release_unique_cstr_lock(session): |
4514
5bb1d39ea0da
fix constraint hook: a session may be involved in multiple transaction at time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4496
diff
changeset
|
55 |
if 'uniquecstrholder' in session.transaction_data: |
5bb1d39ea0da
fix constraint hook: a session may be involved in multiple transaction at time
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4496
diff
changeset
|
56 |
del session.transaction_data['uniquecstrholder'] |
4489
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
57 |
_UNIQUE_CONSTRAINTS_LOCK.release() |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
58 |
|
2605
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
59 |
|
0 | 60 |
def relation_deleted(session, eidfrom, rtype, eidto): |
2101
08003e0354a7
update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
61 |
session.transaction_data.setdefault('pendingrelations', []).append( |
08003e0354a7
update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
62 |
(eidfrom, rtype, eidto)) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
63 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
64 |
def eschema_type_eid(session, etype): |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
65 |
"""get eid of the CWEType entity for the given yams type""" |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
66 |
eschema = session.repo.schema.eschema(etype) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
67 |
# eschema.eid is None if schema has been readen from the filesystem, not |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
68 |
# from the database (eg during tests) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
69 |
if eschema.eid is None: |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
70 |
eschema.eid = session.unsafe_execute( |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
71 |
'Any X WHERE X is CWEType, X name %(name)s', |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
72 |
{'name': str(etype)})[0][0] |
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
73 |
return eschema.eid |
0 | 74 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
75 |
|
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
76 |
# base meta-data handling ###################################################### |
0 | 77 |
|
78 |
def setctime_before_add_entity(session, entity): |
|
79 |
"""before create a new entity -> set creation and modification date |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
80 |
|
0 | 81 |
this is a conveniency hook, you shouldn't have to disable it |
82 |
""" |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
83 |
timestamp = datetime.now() |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
84 |
entity.setdefault('creation_date', timestamp) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
85 |
entity.setdefault('modification_date', timestamp) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
86 |
if not session.get_shared_data('do-not-insert-cwuri'): |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
87 |
entity.setdefault('cwuri', u'%seid/%s' % (session.base_url(), entity.eid)) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
88 |
|
0 | 89 |
|
90 |
def setmtime_before_update_entity(session, entity): |
|
91 |
"""update an entity -> set modification date""" |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
92 |
entity.setdefault('modification_date', datetime.now()) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
93 |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
94 |
|
0 | 95 |
class SetCreatorOp(PreCommitOperation): |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
96 |
|
0 | 97 |
def precommit_event(self): |
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
98 |
session = self.session |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
99 |
if self.entity.eid in session.transaction_data.get('pendingeids', ()): |
0 | 100 |
# entity have been created and deleted in the same transaction |
101 |
return |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
102 |
if not self.entity.created_by: |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
103 |
session.add_relation(self.entity.eid, 'created_by', session.user.eid) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
104 |
|
0 | 105 |
|
106 |
def setowner_after_add_entity(session, entity): |
|
107 |
"""create a new entity -> set owner and creator metadata""" |
|
108 |
asession = session.actual_session() |
|
109 |
if not asession.is_internal_session: |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
110 |
session.add_relation(entity.eid, 'owned_by', asession.user.eid) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
111 |
SetCreatorOp(asession, entity=entity) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
112 |
|
0 | 113 |
|
114 |
def setis_after_add_entity(session, entity): |
|
115 |
"""create a new entity -> set is relation""" |
|
1250
5c20a7f13c84
new recreate argument to extid2eid when an external source want to recreate entities previously imported with a predictable ext id
sylvain.thenault@logilab.fr
parents:
479
diff
changeset
|
116 |
if hasattr(entity, '_cw_recreating'): |
5c20a7f13c84
new recreate argument to extid2eid when an external source want to recreate entities previously imported with a predictable ext id
sylvain.thenault@logilab.fr
parents:
479
diff
changeset
|
117 |
return |
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
118 |
try: |
3693
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
119 |
#session.add_relation(entity.eid, 'is', |
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
120 |
# eschema_type_eid(session, entity.id)) |
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
121 |
session.system_sql('INSERT INTO is_relation(eid_from,eid_to) VALUES (%s,%s)' |
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
122 |
% (entity.eid, eschema_type_eid(session, entity.id))) |
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
123 |
except IndexError: |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
124 |
# during schema serialization, skip |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
125 |
return |
3693
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
126 |
for etype in entity.e_schema.ancestors() + [entity.e_schema]: |
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
127 |
#session.add_relation(entity.eid, 'is_instance_of', |
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
128 |
# eschema_type_eid(session, etype)) |
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
129 |
session.system_sql('INSERT INTO is_instance_of_relation(eid_from,eid_to) VALUES (%s,%s)' |
92581287726f
[optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3689
diff
changeset
|
130 |
% (entity.eid, eschema_type_eid(session, etype))) |
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
131 |
|
0 | 132 |
|
133 |
def setowner_after_add_user(session, entity): |
|
134 |
"""when a user has been created, add owned_by relation on itself""" |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
135 |
session.add_relation(entity.eid, 'owned_by', entity.eid) |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
136 |
|
0 | 137 |
|
138 |
def fti_update_after_add_relation(session, eidfrom, rtype, eidto): |
|
139 |
"""sync fulltext index when relevant relation is added. Reindexing the |
|
140 |
contained entity is enough since it will implicitly reindex the container |
|
141 |
entity. |
|
142 |
""" |
|
143 |
ftcontainer = session.repo.schema.rschema(rtype).fulltext_container |
|
144 |
if ftcontainer == 'subject': |
|
2195
58bef4f707ce
update calls to a deprecated method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2101
diff
changeset
|
145 |
FTIndexEntityOp(session, entity=session.entity_from_eid(eidto)) |
0 | 146 |
elif ftcontainer == 'object': |
2195
58bef4f707ce
update calls to a deprecated method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2101
diff
changeset
|
147 |
FTIndexEntityOp(session, entity=session.entity_from_eid(eidfrom)) |
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
148 |
|
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
149 |
|
0 | 150 |
def fti_update_after_delete_relation(session, eidfrom, rtype, eidto): |
151 |
"""sync fulltext index when relevant relation is deleted. Reindexing both |
|
152 |
entities is necessary. |
|
153 |
""" |
|
154 |
if session.repo.schema.rschema(rtype).fulltext_container: |
|
2195
58bef4f707ce
update calls to a deprecated method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2101
diff
changeset
|
155 |
FTIndexEntityOp(session, entity=session.entity_from_eid(eidto)) |
58bef4f707ce
update calls to a deprecated method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2101
diff
changeset
|
156 |
FTIndexEntityOp(session, entity=session.entity_from_eid(eidfrom)) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
157 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
158 |
|
0 | 159 |
class SyncOwnersOp(PreCommitOperation): |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
160 |
|
0 | 161 |
def precommit_event(self): |
162 |
self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,' |
|
163 |
'NOT EXISTS(X owned_by U, X eid %(x)s)', |
|
164 |
{'c': self.compositeeid, 'x': self.composedeid}, |
|
165 |
('c', 'x')) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
166 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
167 |
|
0 | 168 |
def sync_owner_after_add_composite_relation(session, eidfrom, rtype, eidto): |
169 |
"""when adding composite relation, the composed should have the same owners |
|
170 |
has the composite |
|
171 |
""" |
|
172 |
if rtype == 'wf_info_for': |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
173 |
# skip this special composite relation # XXX (syt) why? |
0 | 174 |
return |
175 |
composite = rproperty(session, rtype, eidfrom, eidto, 'composite') |
|
176 |
if composite == 'subject': |
|
177 |
SyncOwnersOp(session, compositeeid=eidfrom, composedeid=eidto) |
|
178 |
elif composite == 'object': |
|
179 |
SyncOwnersOp(session, compositeeid=eidto, composedeid=eidfrom) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
180 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
181 |
|
0 | 182 |
def _register_metadata_hooks(hm): |
183 |
"""register meta-data related hooks on the hooks manager""" |
|
184 |
hm.register_hook(setctime_before_add_entity, 'before_add_entity', '') |
|
185 |
hm.register_hook(setmtime_before_update_entity, 'before_update_entity', '') |
|
186 |
hm.register_hook(setowner_after_add_entity, 'after_add_entity', '') |
|
187 |
hm.register_hook(sync_owner_after_add_composite_relation, 'after_add_relation', '') |
|
188 |
hm.register_hook(fti_update_after_add_relation, 'after_add_relation', '') |
|
189 |
hm.register_hook(fti_update_after_delete_relation, 'after_delete_relation', '') |
|
190 |
if 'is' in hm.schema: |
|
191 |
hm.register_hook(setis_after_add_entity, 'after_add_entity', '') |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
192 |
if 'CWUser' in hm.schema: |
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
193 |
hm.register_hook(setowner_after_add_user, 'after_add_entity', 'CWUser') |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
194 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
195 |
|
0 | 196 |
# core hooks ################################################################## |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
197 |
|
0 | 198 |
class DelayedDeleteOp(PreCommitOperation): |
199 |
"""delete the object of composite relation except if the relation |
|
200 |
has actually been redirected to another composite |
|
201 |
""" |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
202 |
|
0 | 203 |
def precommit_event(self): |
204 |
session = self.session |
|
2607
5d889b4928bb
[F hooks] skip new eids as well as pending ones in DelayedDelete operation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2606
diff
changeset
|
205 |
# don't do anything if the entity is being created or deleted |
5d889b4928bb
[F hooks] skip new eids as well as pending ones in DelayedDelete operation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2606
diff
changeset
|
206 |
if not (self.eid in session.transaction_data.get('pendingeids', ()) or |
5d889b4928bb
[F hooks] skip new eids as well as pending ones in DelayedDelete operation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2606
diff
changeset
|
207 |
self.eid in session.transaction_data.get('neweids', ())): |
0 | 208 |
etype = session.describe(self.eid)[0] |
3568
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
209 |
if self.role == 'subject': |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
210 |
rql = 'DELETE %s X WHERE X eid %%(x)s, NOT X %s Y' |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
211 |
else: # self.role == 'object': |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
212 |
rql = 'DELETE %s X WHERE X eid %%(x)s, NOT Y %s X' |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
213 |
session.unsafe_execute(rql % (etype, self.rtype), {'x': self.eid}, 'x') |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
214 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
215 |
|
0 | 216 |
def handle_composite_before_del_relation(session, eidfrom, rtype, eidto): |
217 |
"""delete the object of composite relation""" |
|
3568
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
218 |
# if the relation is being delete, don't delete composite's components |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
219 |
# automatically |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
220 |
pendingrdefs = session.transaction_data.get('pendingrdefs', ()) |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
221 |
if (session.describe(eidfrom)[0], rtype, session.describe(eidto)[0]) in pendingrdefs: |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
222 |
return |
0 | 223 |
composite = rproperty(session, rtype, eidfrom, eidto, 'composite') |
224 |
if composite == 'subject': |
|
3568
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
225 |
DelayedDeleteOp(session, eid=eidto, rtype=rtype, role='object') |
0 | 226 |
elif composite == 'object': |
3568
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
227 |
DelayedDeleteOp(session, eid=eidfrom, rtype=rtype, role='subject') |
0 | 228 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
229 |
|
0 | 230 |
def before_del_group(session, eid): |
231 |
"""check that we don't remove the owners group""" |
|
232 |
check_internal_entity(session, eid, ('owners',)) |
|
233 |
||
234 |
||
235 |
# schema validation hooks ##################################################### |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
236 |
|
0 | 237 |
class CheckConstraintsOperation(LateOperation): |
238 |
"""check a new relation satisfy its constraints |
|
239 |
""" |
|
240 |
def precommit_event(self): |
|
241 |
eidfrom, rtype, eidto = self.rdef |
|
242 |
# first check related entities have not been deleted in the same |
|
243 |
# transaction |
|
2101
08003e0354a7
update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
244 |
pending = self.session.transaction_data.get('pendingeids', ()) |
0 | 245 |
if eidfrom in pending: |
246 |
return |
|
247 |
if eidto in pending: |
|
248 |
return |
|
249 |
for constraint in self.constraints: |
|
4489
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
250 |
# XXX |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
251 |
# * lock RQLConstraint as well? |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
252 |
# * use a constraint id to use per constraint lock and avoid |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
253 |
# unnecessary commit serialization ? |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
254 |
if isinstance(constraint, RQLUniqueConstraint): |
63128e8b9af9
fix security issue #36564 (integrity error w/ RQLUniqueConstraint) by using a global lock serializing commit when some RQLUniqueConstraint is encountered.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
255 |
_acquire_unique_cstr_lock(self.session) |
0 | 256 |
try: |
257 |
constraint.repo_check(self.session, eidfrom, rtype, eidto) |
|
258 |
except NotImplementedError: |
|
259 |
self.critical('can\'t check constraint %s, not supported', |
|
260 |
constraint) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
261 |
|
0 | 262 |
def commit_event(self): |
263 |
pass |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
264 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
265 |
|
0 | 266 |
def cstrcheck_after_add_relation(session, eidfrom, rtype, eidto): |
267 |
"""check the relation satisfy its constraints |
|
268 |
||
269 |
this is delayed to a precommit time operation since other relation which |
|
270 |
will make constraint satisfied may be added later. |
|
271 |
""" |
|
3685
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
272 |
if session.is_super_session: |
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
273 |
return |
0 | 274 |
constraints = rproperty(session, rtype, eidfrom, eidto, 'constraints') |
275 |
if constraints: |
|
3978
2c95e3033f64
finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3887
diff
changeset
|
276 |
# XXX get only RQL[Unique]Constraints? |
0 | 277 |
CheckConstraintsOperation(session, constraints=constraints, |
278 |
rdef=(eidfrom, rtype, eidto)) |
|
279 |
||
280 |
def uniquecstrcheck_before_modification(session, entity): |
|
3685
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
281 |
if session.is_super_session: |
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
282 |
return |
0 | 283 |
eschema = entity.e_schema |
4111
1fda1d356741
use edited_attributes and uniformize attribute schema retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3978
diff
changeset
|
284 |
for attr in entity.edited_attributes: |
4116 | 285 |
val = entity[attr] |
0 | 286 |
if val is None: |
287 |
continue |
|
3689
deb13e88e037
follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3685
diff
changeset
|
288 |
if eschema.subjrels[attr].final and \ |
0 | 289 |
eschema.has_unique_values(attr): |
290 |
rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr) |
|
291 |
rset = session.unsafe_execute(rql, {'val': val}) |
|
292 |
if rset and rset[0][0] != entity.eid: |
|
293 |
msg = session._('the value "%s" is already used, use another one') |
|
294 |
raise ValidationError(entity.eid, {attr: msg % val}) |
|
295 |
||
3978
2c95e3033f64
finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3887
diff
changeset
|
296 |
|
3554
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
297 |
def cstrcheck_after_update_attributes(session, entity): |
3685
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
298 |
if session.is_super_session: |
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
299 |
return |
4119
85bb30fb6d9b
fix name error
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents:
4116
diff
changeset
|
300 |
eschema = entity.e_schema |
3554
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
301 |
for attr in entity.edited_attributes: |
4111
1fda1d356741
use edited_attributes and uniformize attribute schema retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3978
diff
changeset
|
302 |
if eschema.subjrels[attr].final: |
3554
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
303 |
constraints = [c for c in entity.e_schema.constraints(attr) |
3978
2c95e3033f64
finish yesterday work on rql constraints:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3887
diff
changeset
|
304 |
if isinstance(c, (RQLConstraint, RQLUniqueConstraint))] |
3554
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
305 |
if constraints: |
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
306 |
CheckConstraintsOperation(session, rdef=(entity.eid, attr, None), |
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
307 |
constraints=constraints) |
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
308 |
|
0 | 309 |
|
310 |
class CheckRequiredRelationOperation(LateOperation): |
|
311 |
"""checking relation cardinality has to be done after commit in |
|
312 |
case the relation is being replaced |
|
313 |
""" |
|
314 |
eid, rtype = None, None |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
315 |
|
0 | 316 |
def precommit_event(self): |
317 |
# recheck pending eids |
|
2101
08003e0354a7
update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
318 |
if self.eid in self.session.transaction_data.get('pendingeids', ()): |
0 | 319 |
return |
3887
130ac9aee402
remove bad invisible character
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3886
diff
changeset
|
320 |
if self.rtype in self.session.transaction_data.get('pendingrtypes', ()): |
3886
6389e5d6edcb
check we're not deleting the relation before checking its cardinality...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3859
diff
changeset
|
321 |
return |
0 | 322 |
if self.session.unsafe_execute(*self._rql()).rowcount < 1: |
323 |
etype = self.session.describe(self.eid)[0] |
|
2241
fcf08ac5f8c0
translate schema types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2195
diff
changeset
|
324 |
_ = self.session._ |
fcf08ac5f8c0
translate schema types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2195
diff
changeset
|
325 |
msg = _('at least one relation %(rtype)s is required on %(etype)s (%(eid)s)') |
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
326 |
msg %= {'rtype': _(self.rtype), 'etype': _(etype), 'eid': self.eid} |
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
327 |
raise ValidationError(self.eid, {self.rtype: msg}) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
328 |
|
0 | 329 |
def commit_event(self): |
330 |
pass |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
331 |
|
0 | 332 |
def _rql(self): |
333 |
raise NotImplementedError() |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
334 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
335 |
|
0 | 336 |
class CheckSRelationOp(CheckRequiredRelationOperation): |
337 |
"""check required subject relation""" |
|
338 |
def _rql(self): |
|
339 |
return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
340 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
341 |
|
0 | 342 |
class CheckORelationOp(CheckRequiredRelationOperation): |
343 |
"""check required object relation""" |
|
344 |
def _rql(self): |
|
345 |
return 'Any S WHERE O eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x' |
|
346 |
||
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
347 |
|
0 | 348 |
def checkrel_if_necessary(session, opcls, rtype, eid): |
349 |
"""check an equivalent operation has not already been added""" |
|
350 |
for op in session.pending_operations: |
|
351 |
if isinstance(op, opcls) and op.rtype == rtype and op.eid == eid: |
|
352 |
break |
|
353 |
else: |
|
354 |
opcls(session, rtype=rtype, eid=eid) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
355 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
356 |
|
0 | 357 |
def cardinalitycheck_after_add_entity(session, entity): |
358 |
"""check cardinalities are satisfied""" |
|
3685
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
359 |
if session.is_super_session: |
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
360 |
return |
0 | 361 |
eid = entity.eid |
362 |
for rschema, targetschemas, x in entity.e_schema.relation_definitions(): |
|
363 |
# skip automatically handled relations |
|
2605
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
364 |
if rschema.type in DONT_CHECK_RTYPES_ON_ADD: |
0 | 365 |
continue |
366 |
if x == 'subject': |
|
367 |
subjtype = entity.e_schema |
|
368 |
objtype = targetschemas[0].type |
|
369 |
cardindex = 0 |
|
370 |
opcls = CheckSRelationOp |
|
371 |
else: |
|
372 |
subjtype = targetschemas[0].type |
|
373 |
objtype = entity.e_schema |
|
374 |
cardindex = 1 |
|
375 |
opcls = CheckORelationOp |
|
376 |
card = rschema.rproperty(subjtype, objtype, 'cardinality') |
|
377 |
if card[cardindex] in '1+': |
|
378 |
checkrel_if_necessary(session, opcls, rschema.type, eid) |
|
379 |
||
380 |
def cardinalitycheck_before_del_relation(session, eidfrom, rtype, eidto): |
|
381 |
"""check cardinalities are satisfied""" |
|
3685
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
382 |
if session.is_super_session: |
6f807804f1d0
no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3662
diff
changeset
|
383 |
return |
2605
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
384 |
if rtype in DONT_CHECK_RTYPES_ON_DEL: |
c4f6a53884ec
[R hooks] use DONT_CHECK_RTYPES_ON_[ADD|DEL] constant, don't check wf related internal relations
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2603
diff
changeset
|
385 |
return |
0 | 386 |
card = rproperty(session, rtype, eidfrom, eidto, 'cardinality') |
2745
0dafa29ace1f
[schema migration] test reproducing pb when deleting a relation definition with mandatory card and without removing the associated rtype + fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2695
diff
changeset
|
387 |
pendingrdefs = session.transaction_data.get('pendingrdefs', ()) |
0dafa29ace1f
[schema migration] test reproducing pb when deleting a relation definition with mandatory card and without removing the associated rtype + fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2695
diff
changeset
|
388 |
if (session.describe(eidfrom)[0], rtype, session.describe(eidto)[0]) in pendingrdefs: |
0dafa29ace1f
[schema migration] test reproducing pb when deleting a relation definition with mandatory card and without removing the associated rtype + fix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2695
diff
changeset
|
389 |
return |
2101
08003e0354a7
update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
390 |
pendingeids = session.transaction_data.get('pendingeids', ()) |
0 | 391 |
if card[0] in '1+' and not eidfrom in pendingeids: |
392 |
checkrel_if_necessary(session, CheckSRelationOp, rtype, eidfrom) |
|
393 |
if card[1] in '1+' and not eidto in pendingeids: |
|
394 |
checkrel_if_necessary(session, CheckORelationOp, rtype, eidto) |
|
395 |
||
396 |
||
397 |
def _register_core_hooks(hm): |
|
398 |
hm.register_hook(handle_composite_before_del_relation, 'before_delete_relation', '') |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
399 |
hm.register_hook(before_del_group, 'before_delete_entity', 'CWGroup') |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
400 |
|
0 | 401 |
#hm.register_hook(cstrcheck_before_update_entity, 'before_update_entity', '') |
402 |
hm.register_hook(cardinalitycheck_after_add_entity, 'after_add_entity', '') |
|
403 |
hm.register_hook(cardinalitycheck_before_del_relation, 'before_delete_relation', '') |
|
404 |
hm.register_hook(cstrcheck_after_add_relation, 'after_add_relation', '') |
|
405 |
hm.register_hook(uniquecstrcheck_before_modification, 'before_add_entity', '') |
|
406 |
hm.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '') |
|
3554
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
407 |
hm.register_hook(cstrcheck_after_update_attributes, 'after_add_entity', '') |
26e586f3c15c
[schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3528
diff
changeset
|
408 |
hm.register_hook(cstrcheck_after_update_attributes, 'after_update_entity', '') |
0 | 409 |
|
410 |
# user/groups synchronisation ################################################# |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
411 |
|
0 | 412 |
class GroupOperation(Operation): |
413 |
"""base class for group operation""" |
|
414 |
geid = None |
|
415 |
def __init__(self, session, *args, **kwargs): |
|
416 |
"""override to get the group name before actual groups manipulation: |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
417 |
|
0 | 418 |
we may temporarily loose right access during a commit event, so |
419 |
no query should be emitted while comitting |
|
420 |
""" |
|
421 |
rql = 'Any N WHERE G eid %(x)s, G name N' |
|
422 |
result = session.execute(rql, {'x': kwargs['geid']}, 'x', build_descr=False) |
|
423 |
Operation.__init__(self, session, *args, **kwargs) |
|
424 |
self.group = result[0][0] |
|
425 |
||
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
426 |
|
0 | 427 |
class DeleteGroupOp(GroupOperation): |
428 |
"""synchronize user when a in_group relation has been deleted""" |
|
429 |
def commit_event(self): |
|
430 |
"""the observed connections pool has been commited""" |
|
431 |
groups = self.cnxuser.groups |
|
432 |
try: |
|
433 |
groups.remove(self.group) |
|
434 |
except KeyError: |
|
435 |
self.error('user %s not in group %s', self.cnxuser, self.group) |
|
436 |
return |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
437 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
438 |
|
0 | 439 |
def after_del_in_group(session, fromeid, rtype, toeid): |
440 |
"""modify user permission, need to update users""" |
|
441 |
for session_ in get_user_sessions(session.repo, fromeid): |
|
442 |
DeleteGroupOp(session, cnxuser=session_.user, geid=toeid) |
|
443 |
||
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
444 |
|
0 | 445 |
class AddGroupOp(GroupOperation): |
446 |
"""synchronize user when a in_group relation has been added""" |
|
447 |
def commit_event(self): |
|
448 |
"""the observed connections pool has been commited""" |
|
449 |
groups = self.cnxuser.groups |
|
450 |
if self.group in groups: |
|
451 |
self.warning('user %s already in group %s', self.cnxuser, |
|
452 |
self.group) |
|
453 |
return |
|
454 |
groups.add(self.group) |
|
455 |
||
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
456 |
|
0 | 457 |
def after_add_in_group(session, fromeid, rtype, toeid): |
458 |
"""modify user permission, need to update users""" |
|
459 |
for session_ in get_user_sessions(session.repo, fromeid): |
|
460 |
AddGroupOp(session, cnxuser=session_.user, geid=toeid) |
|
461 |
||
462 |
||
463 |
class DelUserOp(Operation): |
|
464 |
"""synchronize user when a in_group relation has been added""" |
|
465 |
def __init__(self, session, cnxid): |
|
466 |
self.cnxid = cnxid |
|
467 |
Operation.__init__(self, session) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
468 |
|
0 | 469 |
def commit_event(self): |
470 |
"""the observed connections pool has been commited""" |
|
471 |
try: |
|
472 |
self.repo.close(self.cnxid) |
|
473 |
except BadConnectionId: |
|
474 |
pass # already closed |
|
475 |
||
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
476 |
|
0 | 477 |
def after_del_user(session, eid): |
478 |
"""modify user permission, need to update users""" |
|
479 |
for session_ in get_user_sessions(session.repo, eid): |
|
480 |
DelUserOp(session, session_.id) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
481 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
482 |
|
0 | 483 |
def _register_usergroup_hooks(hm): |
484 |
"""register user/group related hooks on the hooks manager""" |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
485 |
hm.register_hook(after_del_user, 'after_delete_entity', 'CWUser') |
0 | 486 |
hm.register_hook(after_add_in_group, 'after_add_relation', 'in_group') |
487 |
hm.register_hook(after_del_in_group, 'after_delete_relation', 'in_group') |
|
488 |
||
489 |
||
490 |
# workflow handling ########################################################### |
|
491 |
||
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
492 |
from cubicweb.entities.wfobjs import WorkflowTransition, WorkflowException |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
493 |
|
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
494 |
def _change_state(session, x, oldstate, newstate): |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
495 |
nocheck = session.transaction_data.setdefault('skip-security', set()) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
496 |
nocheck.add((x, 'in_state', oldstate)) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
497 |
nocheck.add((x, 'in_state', newstate)) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
498 |
# delete previous state first in case we're using a super session |
3039
7d5a4d27d052
[multi-sources] in ms config, don't try to delete previous state in some condition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2992
diff
changeset
|
499 |
fromsource = session.describe(x)[1] |
7d5a4d27d052
[multi-sources] in ms config, don't try to delete previous state in some condition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2992
diff
changeset
|
500 |
# don't try to remove previous state if in_state isn't stored in the system |
7d5a4d27d052
[multi-sources] in ms config, don't try to delete previous state in some condition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2992
diff
changeset
|
501 |
# source |
7d5a4d27d052
[multi-sources] in ms config, don't try to delete previous state in some condition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2992
diff
changeset
|
502 |
if fromsource == 'system' or \ |
7d5a4d27d052
[multi-sources] in ms config, don't try to delete previous state in some condition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2992
diff
changeset
|
503 |
not session.repo.sources_by_uri[fromsource].support_relation('in_state'): |
7d5a4d27d052
[multi-sources] in ms config, don't try to delete previous state in some condition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2992
diff
changeset
|
504 |
session.delete_relation(x, 'in_state', oldstate) |
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
505 |
session.add_relation(x, 'in_state', newstate) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
506 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
507 |
|
3528
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
508 |
class FireAutotransitionOp(PreCommitOperation): |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
509 |
"""try to fire auto transition after state changes""" |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
510 |
|
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
511 |
def precommit_event(self): |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
512 |
session = self.session |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
513 |
entity = self.entity |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
514 |
autotrs = list(entity.possible_transitions('auto')) |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
515 |
if autotrs: |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
516 |
assert len(autotrs) == 1 |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
517 |
entity.fire_transition(autotrs[0]) |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
518 |
|
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
519 |
|
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
520 |
def before_add_trinfo(session, entity): |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
521 |
"""check the transition is allowed, add missing information. Expect that: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
522 |
* wf_info_for inlined relation is set |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
523 |
* by_transition or to_state (managers only) inlined relation is set |
0 | 524 |
""" |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
525 |
# first retreive entity to which the state change apply |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
526 |
try: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
527 |
foreid = entity['wf_info_for'] |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
528 |
except KeyError: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
529 |
msg = session._('mandatory relation') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
530 |
raise ValidationError(entity.eid, {'wf_info_for': msg}) |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
531 |
forentity = session.entity_from_eid(foreid) |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
532 |
# then check it has a workflow set, unless we're in the process of changing |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
533 |
# entity's workflow |
2978
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
534 |
if session.transaction_data.get((forentity.eid, 'customwf')): |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
535 |
wfeid = session.transaction_data[(forentity.eid, 'customwf')] |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
536 |
wf = session.entity_from_eid(wfeid) |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
537 |
else: |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
538 |
wf = forentity.current_workflow |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
539 |
if wf is None: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
540 |
msg = session._('related entity has no workflow set') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
541 |
raise ValidationError(entity.eid, {None: msg}) |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
542 |
# then check it has a state set |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
543 |
fromstate = forentity.current_state |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
544 |
if fromstate is None: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
545 |
msg = session._('related entity has no state') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
546 |
raise ValidationError(entity.eid, {None: msg}) |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
547 |
# True if we are coming back from subworkflow |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
548 |
swtr = session.transaction_data.pop((forentity.eid, 'subwfentrytr'), None) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
549 |
cowpowers = session.is_super_session or 'managers' in session.user.groups |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
550 |
# no investigate the requested state change... |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
551 |
try: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
552 |
treid = entity['by_transition'] |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
553 |
except KeyError: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
554 |
# no transition set, check user is a manager and destination state is |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
555 |
# specified (and valid) |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
556 |
if not cowpowers: |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
557 |
msg = session._('mandatory relation') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
558 |
raise ValidationError(entity.eid, {'by_transition': msg}) |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
559 |
deststateeid = entity.get('to_state') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
560 |
if not deststateeid: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
561 |
msg = session._('mandatory relation') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
562 |
raise ValidationError(entity.eid, {'by_transition': msg}) |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
563 |
deststate = wf.state_by_eid(deststateeid) |
3773
14fde27a70a2
don't allow that even with cow powers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3693
diff
changeset
|
564 |
if deststate is None: |
14fde27a70a2
don't allow that even with cow powers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3693
diff
changeset
|
565 |
msg = entity.req._("state doesn't belong to entity's current workflow") |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
566 |
raise ValidationError(entity.eid, {'to_state': msg}) |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
567 |
else: |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
568 |
# check transition is valid and allowed, unless we're coming back from |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
569 |
# subworkflow |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
570 |
tr = session.entity_from_eid(treid) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
571 |
if swtr is None: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
572 |
if tr is None: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
573 |
msg = session._("transition doesn't belong to entity's workflow") |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
574 |
raise ValidationError(entity.eid, {'by_transition': msg}) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
575 |
if not tr.has_input_state(fromstate): |
3859
85e6ba89837a
more helpful error message
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3773
diff
changeset
|
576 |
_ = session._ |
4098
eb4722dd5f86
[i18n] use named substitutions for proper localization
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3978
diff
changeset
|
577 |
msg = _("transition %(tr)s isn't allowed from %(st)s") % {'tr': _(tr.name), |
eb4722dd5f86
[i18n] use named substitutions for proper localization
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3978
diff
changeset
|
578 |
'st': _(fromstate.name), |
eb4722dd5f86
[i18n] use named substitutions for proper localization
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3978
diff
changeset
|
579 |
} |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
580 |
raise ValidationError(entity.eid, {'by_transition': msg}) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
581 |
if not tr.may_be_fired(foreid): |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
582 |
msg = session._("transition may not be fired") |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
583 |
raise ValidationError(entity.eid, {'by_transition': msg}) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
584 |
if entity.get('to_state'): |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
585 |
deststateeid = entity['to_state'] |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
586 |
if not cowpowers and deststateeid != tr.destination().eid: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
587 |
msg = session._("transition isn't allowed") |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
588 |
raise ValidationError(entity.eid, {'by_transition': msg}) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
589 |
if swtr is None: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
590 |
deststate = session.entity_from_eid(deststateeid) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
591 |
if not cowpowers and deststate is None: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
592 |
msg = entity.req._("state doesn't belong to entity's workflow") |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
593 |
raise ValidationError(entity.eid, {'to_state': msg}) |
0 | 594 |
else: |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
595 |
deststateeid = tr.destination().eid |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
596 |
# everything is ok, add missing information on the trinfo entity |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
597 |
entity['from_state'] = fromstate.eid |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
598 |
entity['to_state'] = deststateeid |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
599 |
nocheck = session.transaction_data.setdefault('skip-security', set()) |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
600 |
nocheck.add((entity.eid, 'from_state', fromstate.eid)) |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
601 |
nocheck.add((entity.eid, 'to_state', deststateeid)) |
3528
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
602 |
FireAutotransitionOp(session, entity=forentity) |
77a69de16709
support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3508
diff
changeset
|
603 |
|
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
604 |
|
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
605 |
def after_add_trinfo(session, entity): |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
606 |
"""change related entity state""" |
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
607 |
_change_state(session, entity['wf_info_for'], |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
608 |
entity['from_state'], entity['to_state']) |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
609 |
forentity = session.entity_from_eid(entity['wf_info_for']) |
3568
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
610 |
assert forentity.current_state.eid == entity['to_state'], ( |
87a7ca9d8ce6
[hooks] don't delete composed of a composite where relation is being removed from the schema
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3554
diff
changeset
|
611 |
forentity.eid, forentity.current_state.name) |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
612 |
if forentity.main_workflow.eid != forentity.current_workflow.eid: |
3662
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
613 |
SubWorkflowExitOp(session, forentity=forentity, trinfo=entity) |
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
614 |
|
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
615 |
class SubWorkflowExitOp(PreCommitOperation): |
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
616 |
def precommit_event(self): |
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
617 |
session = self.session |
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
618 |
forentity = self.forentity |
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
619 |
trinfo = self.trinfo |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
620 |
# we're in a subworkflow, check if we've reached an exit point |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
621 |
wftr = forentity.subworkflow_input_transition() |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
622 |
if wftr is None: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
623 |
# inconsistency detected |
3662
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
624 |
msg = session._("state doesn't belong to entity's current workflow") |
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
625 |
raise ValidationError(self.trinfo.eid, {'to_state': msg}) |
9eeadad82d93
defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
3628
diff
changeset
|
626 |
tostate = wftr.get_exit_point(forentity, trinfo['to_state']) |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
627 |
if tostate is not None: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
628 |
# reached an exit point |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
629 |
msg = session._('exiting from subworkflow %s') |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
630 |
msg %= session._(forentity.current_workflow.name) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
631 |
session.transaction_data[(forentity.eid, 'subwfentrytr')] = True |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
632 |
# XXX iirk |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
633 |
req = forentity.req |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
634 |
forentity.req = session.super_session |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
635 |
try: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
636 |
trinfo = forentity.change_state(tostate, msg, u'text/plain', |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
637 |
tr=wftr) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
638 |
finally: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
639 |
forentity.req = req |
0 | 640 |
|
641 |
||
642 |
class SetInitialStateOp(PreCommitOperation): |
|
643 |
"""make initial state be a default state""" |
|
644 |
||
645 |
def precommit_event(self): |
|
646 |
session = self.session |
|
647 |
entity = self.entity |
|
648 |
# if there is an initial state and the entity's state is not set, |
|
649 |
# use the initial state as a default state |
|
2101
08003e0354a7
update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
650 |
pendingeids = session.transaction_data.get('pendingeids', ()) |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
651 |
if not entity.eid in pendingeids and not entity.in_state and \ |
2978
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
652 |
entity.main_workflow: |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
653 |
state = entity.main_workflow.initial |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
654 |
if state: |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
655 |
# use super session to by-pass security checks |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
656 |
session.super_session.add_relation(entity.eid, 'in_state', |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
657 |
state.eid) |
0 | 658 |
|
659 |
||
660 |
def set_initial_state_after_add(session, entity): |
|
661 |
SetInitialStateOp(session, entity=entity) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
662 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
663 |
|
2983
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
664 |
def before_add_in_state(session, eidfrom, rtype, eidto): |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
665 |
"""check state apply, in case of direct in_state change using unsafe_execute |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
666 |
""" |
3508
d9915224f9a5
[B] server: fix initial data structure in session.transaction_data
Julien Jehannet <julien.jehannet@logilab.fr>
parents:
3071
diff
changeset
|
667 |
nocheck = session.transaction_data.setdefault('skip-security', set()) |
2983
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
668 |
if (eidfrom, 'in_state', eidto) in nocheck: |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
669 |
# state changed through TrInfo insertion, so we already know it's ok |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
670 |
return |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
671 |
entity = session.entity_from_eid(eidfrom) |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
672 |
mainwf = entity.main_workflow |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
673 |
if mainwf is None: |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
674 |
msg = session._('entity has no workflow set') |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
675 |
raise ValidationError(entity.eid, {None: msg}) |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
676 |
for wf in mainwf.iter_workflows(): |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
677 |
if wf.state_by_eid(eidto): |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
678 |
break |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
679 |
else: |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
680 |
msg = session._("state doesn't belong to entity's workflow. You may " |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
681 |
"want to set a custom workflow for this entity first.") |
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
682 |
raise ValidationError(eidfrom, {'in_state': msg}) |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
683 |
if entity.current_workflow and wf.eid != entity.current_workflow.eid: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
684 |
msg = session._("state doesn't belong to entity's current workflow") |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
685 |
raise ValidationError(eidfrom, {'in_state': msg}) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
686 |
|
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
687 |
|
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
688 |
class CheckTrExitPoint(PreCommitOperation): |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
689 |
|
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
690 |
def precommit_event(self): |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
691 |
tr = self.session.entity_from_eid(self.treid) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
692 |
outputs = set() |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
693 |
for ep in tr.subworkflow_exit: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
694 |
if ep.subwf_state.eid in outputs: |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
695 |
msg = self.session._("can't have multiple exits on the same state") |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
696 |
raise ValidationError(self.treid, {'subworkflow_exit': msg}) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
697 |
outputs.add(ep.subwf_state.eid) |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
698 |
|
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
699 |
|
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
700 |
def after_add_subworkflow_exit(session, eidfrom, rtype, eidto): |
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
701 |
CheckTrExitPoint(session, treid=eidfrom) |
2983
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
702 |
|
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
703 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
704 |
class WorkflowChangedOp(PreCommitOperation): |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
705 |
"""fix entity current state when changing its workflow""" |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
706 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
707 |
def precommit_event(self): |
2985 | 708 |
# notice that enforcement that new workflow apply to the entity's type is |
709 |
# done by schema rule, no need to check it here |
|
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
710 |
session = self.session |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
711 |
pendingeids = session.transaction_data.get('pendingeids', ()) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
712 |
if self.eid in pendingeids: |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
713 |
return |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
714 |
entity = session.entity_from_eid(self.eid) |
2978
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
715 |
# check custom workflow has not been rechanged to another one in the same |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
716 |
# transaction |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
717 |
mainwf = entity.main_workflow |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
718 |
if mainwf.eid == self.wfeid: |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
719 |
deststate = mainwf.initial |
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
720 |
if not deststate: |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
721 |
msg = session._('workflow has no initial state') |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
722 |
raise ValidationError(entity.eid, {'custom_workflow': msg}) |
2978
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
723 |
if mainwf.state_by_eid(entity.current_state.eid): |
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
724 |
# nothing to do |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
725 |
return |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
726 |
# if there are no history, simply go to new workflow's initial state |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
727 |
if not entity.workflow_history: |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
728 |
if entity.current_state.eid != deststate.eid: |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
729 |
_change_state(session, entity.eid, |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
730 |
entity.current_state.eid, deststate.eid) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
731 |
return |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
732 |
msg = session._('workflow changed to "%s"') |
2978
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
733 |
msg %= session._(mainwf.name) |
d8c5ad14ab8e
[wf]Â distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2949
diff
changeset
|
734 |
session.transaction_data[(entity.eid, 'customwf')] = self.wfeid |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
735 |
entity.change_state(deststate, msg, u'text/plain') |
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
736 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
737 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
738 |
def set_custom_workflow(session, eidfrom, rtype, eidto): |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
739 |
WorkflowChangedOp(session, eid=eidfrom, wfeid=eidto) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
740 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
741 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
742 |
def del_custom_workflow(session, eidfrom, rtype, eidto): |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
743 |
entity = session.entity_from_eid(eidfrom) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
744 |
typewf = entity.cwetype_workflow() |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
745 |
if typewf is not None: |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
746 |
WorkflowChangedOp(session, eid=eidfrom, wfeid=typewf.eid) |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
747 |
|
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
748 |
|
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
749 |
def after_del_workflow(session, eid): |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
750 |
# workflow cleanup |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
751 |
session.execute('DELETE State X WHERE NOT X state_of Y') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
752 |
session.execute('DELETE Transition X WHERE NOT X transition_of Y') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
753 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
754 |
|
0 | 755 |
def _register_wf_hooks(hm): |
756 |
"""register workflow related hooks on the hooks manager""" |
|
757 |
if 'in_state' in hm.schema: |
|
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
758 |
hm.register_hook(before_add_trinfo, 'before_add_entity', 'TrInfo') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
759 |
hm.register_hook(after_add_trinfo, 'after_add_entity', 'TrInfo') |
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
760 |
#hm.register_hook(relation_deleted, 'before_delete_relation', 'in_state') |
0 | 761 |
for eschema in hm.schema.entities(): |
762 |
if 'in_state' in eschema.subject_relations(): |
|
763 |
hm.register_hook(set_initial_state_after_add, 'after_add_entity', |
|
764 |
str(eschema)) |
|
2949
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
765 |
hm.register_hook(set_custom_workflow, 'after_add_relation', 'custom_workflow') |
a2aa2c51f3be
test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2920
diff
changeset
|
766 |
hm.register_hook(del_custom_workflow, 'after_delete_relation', 'custom_workflow') |
2920
64322aa83a1d
start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2909
diff
changeset
|
767 |
hm.register_hook(after_del_workflow, 'after_delete_entity', 'Workflow') |
2983
b458631fe347
[wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2978
diff
changeset
|
768 |
hm.register_hook(before_add_in_state, 'before_add_relation', 'in_state') |
2992
a5b8bf107a1a
[wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2985
diff
changeset
|
769 |
hm.register_hook(after_add_subworkflow_exit, 'after_add_relation', 'subworkflow_exit') |
0 | 770 |
|
771 |
||
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
772 |
# CWProperty hooks ############################################################# |
0 | 773 |
|
774 |
||
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
775 |
class DelCWPropertyOp(Operation): |
0 | 776 |
"""a user's custom properties has been deleted""" |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
777 |
|
0 | 778 |
def commit_event(self): |
779 |
"""the observed connections pool has been commited""" |
|
780 |
try: |
|
781 |
del self.epropdict[self.key] |
|
782 |
except KeyError: |
|
783 |
self.error('%s has no associated value', self.key) |
|
784 |
||
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
785 |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
786 |
class ChangeCWPropertyOp(Operation): |
0 | 787 |
"""a user's custom properties has been added/changed""" |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
788 |
|
0 | 789 |
def commit_event(self): |
790 |
"""the observed connections pool has been commited""" |
|
791 |
self.epropdict[self.key] = self.value |
|
792 |
||
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
793 |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
794 |
class AddCWPropertyOp(Operation): |
0 | 795 |
"""a user's custom properties has been added/changed""" |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
796 |
|
0 | 797 |
def commit_event(self): |
798 |
"""the observed connections pool has been commited""" |
|
799 |
eprop = self.eprop |
|
800 |
if not eprop.for_user: |
|
801 |
self.repo.vreg.eprop_values[eprop.pkey] = eprop.value |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
802 |
# if for_user is set, update is handled by a ChangeCWPropertyOp operation |
0 | 803 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
804 |
|
0 | 805 |
def after_add_eproperty(session, entity): |
806 |
key, value = entity.pkey, entity.value |
|
807 |
try: |
|
808 |
value = session.vreg.typed_value(key, value) |
|
809 |
except UnknownProperty: |
|
810 |
raise ValidationError(entity.eid, {'pkey': session._('unknown property key')}) |
|
811 |
except ValueError, ex: |
|
812 |
raise ValidationError(entity.eid, {'value': session._(str(ex))}) |
|
813 |
if not session.user.matching_groups('managers'): |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
814 |
session.add_relation(entity.eid, 'for_user', session.user.eid) |
0 | 815 |
else: |
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
816 |
AddCWPropertyOp(session, eprop=entity) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
817 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
818 |
|
0 | 819 |
def after_update_eproperty(session, entity): |
2695
56439c45781c
[hooks] check key or value is actually edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2607
diff
changeset
|
820 |
if not ('pkey' in entity.edited_attributes or |
56439c45781c
[hooks] check key or value is actually edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2607
diff
changeset
|
821 |
'value' in entity.edited_attributes): |
56439c45781c
[hooks] check key or value is actually edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2607
diff
changeset
|
822 |
return |
0 | 823 |
key, value = entity.pkey, entity.value |
824 |
try: |
|
825 |
value = session.vreg.typed_value(key, value) |
|
826 |
except UnknownProperty: |
|
827 |
return |
|
828 |
except ValueError, ex: |
|
829 |
raise ValidationError(entity.eid, {'value': session._(str(ex))}) |
|
830 |
if entity.for_user: |
|
831 |
for session_ in get_user_sessions(session.repo, entity.for_user[0].eid): |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
832 |
ChangeCWPropertyOp(session, epropdict=session_.user.properties, |
0 | 833 |
key=key, value=value) |
834 |
else: |
|
835 |
# site wide properties |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
836 |
ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values, |
0 | 837 |
key=key, value=value) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
838 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
839 |
|
0 | 840 |
def before_del_eproperty(session, eid): |
2101
08003e0354a7
update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
841 |
for eidfrom, rtype, eidto in session.transaction_data.get('pendingrelations', ()): |
0 | 842 |
if rtype == 'for_user' and eidfrom == eid: |
843 |
# if for_user was set, delete has already been handled |
|
844 |
break |
|
845 |
else: |
|
846 |
key = session.execute('Any K WHERE P eid %(x)s, P pkey K', |
|
847 |
{'x': eid}, 'x')[0][0] |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
848 |
DelCWPropertyOp(session, epropdict=session.vreg.eprop_values, key=key) |
0 | 849 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
850 |
|
0 | 851 |
def after_add_for_user(session, fromeid, rtype, toeid): |
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
852 |
if not session.describe(fromeid)[0] == 'CWProperty': |
0 | 853 |
return |
854 |
key, value = session.execute('Any K,V WHERE P eid %(x)s,P pkey K,P value V', |
|
855 |
{'x': fromeid}, 'x')[0] |
|
856 |
if session.vreg.property_info(key)['sitewide']: |
|
857 |
raise ValidationError(fromeid, |
|
858 |
{'for_user': session._("site-wide property can't be set for user")}) |
|
859 |
for session_ in get_user_sessions(session.repo, toeid): |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
860 |
ChangeCWPropertyOp(session, epropdict=session_.user.properties, |
0 | 861 |
key=key, value=value) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
862 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
863 |
|
0 | 864 |
def before_del_for_user(session, fromeid, rtype, toeid): |
865 |
key = session.execute('Any K WHERE P eid %(x)s, P pkey K', |
|
866 |
{'x': fromeid}, 'x')[0][0] |
|
867 |
relation_deleted(session, fromeid, rtype, toeid) |
|
868 |
for session_ in get_user_sessions(session.repo, toeid): |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
869 |
DelCWPropertyOp(session, epropdict=session_.user.properties, key=key) |
0 | 870 |
|
2603
e47d63351891
[R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2463
diff
changeset
|
871 |
|
0 | 872 |
def _register_eproperty_hooks(hm): |
873 |
"""register workflow related hooks on the hooks manager""" |
|
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
874 |
hm.register_hook(after_add_eproperty, 'after_add_entity', 'CWProperty') |
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
875 |
hm.register_hook(after_update_eproperty, 'after_update_entity', 'CWProperty') |
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
1263
diff
changeset
|
876 |
hm.register_hook(before_del_eproperty, 'before_delete_entity', 'CWProperty') |
0 | 877 |
hm.register_hook(after_add_for_user, 'after_add_relation', 'for_user') |
878 |
hm.register_hook(before_del_for_user, 'before_delete_relation', 'for_user') |