server/hooks.py
author Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
Thu, 12 Nov 2009 18:27:59 +0100
branchstable
changeset 3834 e3e64352063d
parent 3773 14fde27a70a2
child 3859 85e6ba89837a
permissions -rw-r--r--
[javascript] fid form / onfailure behaviour If onfailure is specified, it should be done _before_ any default / standard CW action is done. The callback signature should be the same as the onsuccess one. If the onfailure callback returns true, the default actions will still take place afterwards, otherwise (i.e. return false), the processing stops directly after the callback.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""Core hooks: check schema validity, unsure we are not deleting necessary
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
entities...
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     4
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1802
diff changeset
     5
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     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
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     9
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    10
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 479
diff changeset
    11
from datetime import datetime
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    12
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    13
from cubicweb import UnknownProperty, ValidationError, BadConnectionId
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
    14
from cubicweb.schema import RQLVocabularyConstraint
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    15
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
    16
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
    17
                                        get_user_sessions, rproperty)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
from cubicweb.server.repository import FTIndexEntityOp
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
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
    20
# 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
    21
# 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
    22
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
    23
                                '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
    24
                                '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
    25
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
    26
                                '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
    27
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
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
def relation_deleted(session, eidfrom, rtype, eidto):
2101
08003e0354a7 update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    30
    session.transaction_data.setdefault('pendingrelations', []).append(
08003e0354a7 update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    31
        (eidfrom, rtype, eidto))
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
    32
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
    33
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
    34
    """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
    35
    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
    36
    # 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
    37
    # 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
    38
    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
    39
        eschema.eid = session.unsafe_execute(
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
    40
            '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
    41
            {'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
    42
    return eschema.eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    43
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
    44
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
    45
# base meta-data handling ######################################################
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
def setctime_before_add_entity(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
    """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
    49
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
    this is a conveniency hook, you shouldn't have to disable it
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
    """
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
    52
    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
    53
    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
    54
    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
    55
    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
    56
        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
    57
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
def setmtime_before_update_entity(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
    """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
    61
    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
    62
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
    63
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
class SetCreatorOp(PreCommitOperation):
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
    65
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
    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
    67
        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
    68
        if self.entity.eid in session.transaction_data.get('pendingeids', ()):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
            # entity have been created and deleted in the same transaction
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
            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
    71
        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
    72
            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
    73
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
def setowner_after_add_entity(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
    """create a new entity -> set owner and creator metadata"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
    asession = session.actual_session()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
    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
    79
        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
    80
        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
    81
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
def setis_after_add_entity(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
    """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
    85
    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
    86
        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
    87
    try:
3693
92581287726f [optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
    88
        #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
    89
        #                     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
    90
        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
    91
                           % (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
    92
    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
    93
        # 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
    94
        return
3693
92581287726f [optimisation] insert is / is_instance_of using sql
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
    95
    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
    96
        #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
    97
        #                     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
    98
        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
    99
                           % (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
   100
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
def setowner_after_add_user(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   103
    """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
   104
    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
   105
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
def fti_update_after_add_relation(session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
    """sync fulltext index when relevant relation is added. Reindexing the
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
    contained entity is enough since it will implicitly reindex the container
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
    entity.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
    ftcontainer = session.repo.schema.rschema(rtype).fulltext_container
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   113
    if ftcontainer == 'subject':
2195
58bef4f707ce update calls to a deprecated method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2101
diff changeset
   114
        FTIndexEntityOp(session, entity=session.entity_from_eid(eidto))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
    elif ftcontainer == 'object':
2195
58bef4f707ce update calls to a deprecated method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2101
diff changeset
   116
        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
   117
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   118
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
def fti_update_after_delete_relation(session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
    """sync fulltext index when relevant relation is deleted. Reindexing both
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
    entities is necessary.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
    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
   124
        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
   125
        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
   126
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   127
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
class SyncOwnersOp(PreCommitOperation):
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   129
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
    def precommit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
        self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
                                    'NOT EXISTS(X owned_by U, X eid %(x)s)',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
                                    {'c': self.compositeeid, 'x': self.composedeid},
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
                                    ('c', 'x'))
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   135
2603
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
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
def sync_owner_after_add_composite_relation(session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   138
    """when adding composite relation, the composed should have the same owners
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
    has the composite
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
    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
   142
        # skip this special composite relation # XXX (syt) why?
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
        return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
    composite = rproperty(session, rtype, eidfrom, eidto, 'composite')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
    if composite == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
        SyncOwnersOp(session, compositeeid=eidfrom, composedeid=eidto)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
    elif composite == 'object':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   148
        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
   149
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   150
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   151
def _register_metadata_hooks(hm):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
    """register meta-data related hooks on the hooks manager"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   153
    hm.register_hook(setctime_before_add_entity, 'before_add_entity', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   154
    hm.register_hook(setmtime_before_update_entity, 'before_update_entity', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   155
    hm.register_hook(setowner_after_add_entity, 'after_add_entity', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   156
    hm.register_hook(sync_owner_after_add_composite_relation, 'after_add_relation', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   157
    hm.register_hook(fti_update_after_add_relation, 'after_add_relation', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   158
    hm.register_hook(fti_update_after_delete_relation, 'after_delete_relation', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   159
    if 'is' in hm.schema:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   160
        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
   161
    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
   162
        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
   163
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   164
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
# core hooks ##################################################################
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   166
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
class DelayedDeleteOp(PreCommitOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
    """delete the object of composite relation except if the relation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   169
    has actually been redirected to another composite
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
    """
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   171
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
    def precommit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   173
        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
   174
        # 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
   175
        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
   176
                self.eid in session.transaction_data.get('neweids', ())):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
            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
   178
            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
   179
                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
   180
            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
   181
                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
   182
            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
   183
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   184
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
def handle_composite_before_del_relation(session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
    """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
   187
    # 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
   188
    # 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
   189
    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
   190
    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
   191
        return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
    composite = rproperty(session, rtype, eidfrom, eidto, 'composite')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
    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
   194
        DelayedDeleteOp(session, eid=eidto, rtype=rtype, role='object')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
    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
   196
        DelayedDeleteOp(session, eid=eidfrom, rtype=rtype, role='subject')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   198
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
def before_del_group(session, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
    """check that we don't remove the owners group"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   201
    check_internal_entity(session, eid, ('owners',))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
# schema validation hooks #####################################################
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   205
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
class CheckConstraintsOperation(LateOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
    """check a new relation satisfy its constraints
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
    def precommit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
        eidfrom, rtype, eidto = self.rdef
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   211
        # first check related entities have not been deleted in the same
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
        # transaction
2101
08003e0354a7 update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   213
        pending = self.session.transaction_data.get('pendingeids', ())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   214
        if eidfrom in pending:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   215
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
        if eidto in pending:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   218
        for constraint in self.constraints:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   219
            try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
                constraint.repo_check(self.session, eidfrom, rtype, eidto)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
            except NotImplementedError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
                self.critical('can\'t check constraint %s, not supported',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
                              constraint)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   224
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
        pass
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   227
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   228
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
def cstrcheck_after_add_relation(session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
    """check the relation satisfy its constraints
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
    this is delayed to a precommit time operation since other relation which
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   233
    will make constraint satisfied may be added later.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
    """
3685
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   235
    if session.is_super_session:
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   236
        return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   237
    constraints = rproperty(session, rtype, eidfrom, eidto, 'constraints')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
    if constraints:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
        CheckConstraintsOperation(session, constraints=constraints,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
                                  rdef=(eidfrom, rtype, eidto))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
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
   243
    if session.is_super_session:
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   244
        return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   245
    eschema = entity.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   246
    for attr, val in entity.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   247
        if val is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   248
            continue
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3685
diff changeset
   249
        if eschema.subjrels[attr].final and \
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   250
               eschema.has_unique_values(attr):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   251
            rql = '%s X WHERE X %s %%(val)s' % (entity.e_schema, attr)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   252
            rset = session.unsafe_execute(rql, {'val': val})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   253
            if rset and rset[0][0] != entity.eid:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   254
                msg = session._('the value "%s" is already used, use another one')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   255
                raise ValidationError(entity.eid, {attr: msg % val})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   256
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   257
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
   258
    if session.is_super_session:
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   259
        return
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   260
    schema = session.vreg.schema
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   261
    for attr in entity.edited_attributes:
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3685
diff changeset
   262
        if schema.rschema(attr).final:
3554
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   263
            constraints = [c for c in entity.e_schema.constraints(attr)
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   264
                           if isinstance(c, RQLVocabularyConstraint)]
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   265
            if constraints:
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   266
                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
   267
                                          constraints=constraints)
26e586f3c15c [schema] make RQL* constraints usable w/ attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3528
diff changeset
   268
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   269
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
class CheckRequiredRelationOperation(LateOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
    """checking relation cardinality has to be done after commit in
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
    case the relation is being replaced
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   273
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
    eid, rtype = None, None
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   275
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   276
    def precommit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   277
        # recheck pending eids
2101
08003e0354a7 update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   278
        if self.eid in self.session.transaction_data.get('pendingeids', ()):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   279
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   280
        if self.session.unsafe_execute(*self._rql()).rowcount < 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
            etype = self.session.describe(self.eid)[0]
2241
fcf08ac5f8c0 translate schema types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2195
diff changeset
   282
            _ = self.session._
fcf08ac5f8c0 translate schema types
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2195
diff changeset
   283
            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
   284
            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
   285
            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
   286
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   288
        pass
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   289
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   290
    def _rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   291
        raise NotImplementedError()
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   292
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   293
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
class CheckSRelationOp(CheckRequiredRelationOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   295
    """check required subject relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
    def _rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
        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
   298
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   299
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   300
class CheckORelationOp(CheckRequiredRelationOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   301
    """check required object relation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
    def _rql(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   303
        return 'Any S WHERE O eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   305
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
def checkrel_if_necessary(session, opcls, rtype, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
    """check an equivalent operation has not already been added"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
    for op in session.pending_operations:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
        if isinstance(op, opcls) and op.rtype == rtype and op.eid == eid:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
            break
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        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
   313
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   314
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
def cardinalitycheck_after_add_entity(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   316
    """check cardinalities are satisfied"""
3685
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   317
    if session.is_super_session:
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   318
        return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   319
    eid = entity.eid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
    for rschema, targetschemas, x in entity.e_schema.relation_definitions():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
        # 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
   322
        if rschema.type in DONT_CHECK_RTYPES_ON_ADD:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
            continue
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
        if x == 'subject':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   325
            subjtype = entity.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   326
            objtype = targetschemas[0].type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   327
            cardindex = 0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   328
            opcls = CheckSRelationOp
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   329
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   330
            subjtype = targetschemas[0].type
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   331
            objtype = entity.e_schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
            cardindex = 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   333
            opcls = CheckORelationOp
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   334
        card = rschema.rproperty(subjtype, objtype, 'cardinality')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
        if card[cardindex] in '1+':
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   336
            checkrel_if_necessary(session, opcls, rschema.type, eid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   338
def cardinalitycheck_before_del_relation(session, eidfrom, rtype, eidto):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   339
    """check cardinalities are satisfied"""
3685
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   340
    if session.is_super_session:
6f807804f1d0 no integrity check for super session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3662
diff changeset
   341
        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
   342
    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
   343
        return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   344
    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
   345
    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
   346
    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
   347
        return
2101
08003e0354a7 update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   348
    pendingeids = session.transaction_data.get('pendingeids', ())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   349
    if card[0] in '1+' and not eidfrom in pendingeids:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
        checkrel_if_necessary(session, CheckSRelationOp, rtype, eidfrom)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   351
    if card[1] in '1+' and not eidto in pendingeids:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   352
        checkrel_if_necessary(session, CheckORelationOp, rtype, eidto)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   353
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   354
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   355
def _register_core_hooks(hm):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   356
    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
   357
    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
   358
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   359
    #hm.register_hook(cstrcheck_before_update_entity, 'before_update_entity', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
    hm.register_hook(cardinalitycheck_after_add_entity, 'after_add_entity', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   361
    hm.register_hook(cardinalitycheck_before_del_relation, 'before_delete_relation', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   362
    hm.register_hook(cstrcheck_after_add_relation, 'after_add_relation', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   363
    hm.register_hook(uniquecstrcheck_before_modification, 'before_add_entity', '')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   364
    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
   365
    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
   366
    hm.register_hook(cstrcheck_after_update_attributes, 'after_update_entity', '')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   367
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   368
# user/groups synchronisation #################################################
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   369
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   370
class GroupOperation(Operation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   371
    """base class for group operation"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   372
    geid = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
    def __init__(self, session, *args, **kwargs):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
        """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
   375
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   376
        we may temporarily loose right access during a commit event, so
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
        no query should be emitted while comitting
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
        rql = 'Any N WHERE G eid %(x)s, G name N'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
        result = session.execute(rql, {'x': kwargs['geid']}, 'x', build_descr=False)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   381
        Operation.__init__(self, session, *args, **kwargs)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   382
        self.group = result[0][0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   384
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   385
class DeleteGroupOp(GroupOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   386
    """synchronize user when a in_group relation has been deleted"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   387
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   388
        """the observed connections pool has been commited"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
        groups = self.cnxuser.groups
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   390
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   391
            groups.remove(self.group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   392
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   393
            self.error('user %s not in group %s',  self.cnxuser, self.group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   394
            return
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   395
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   396
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   397
def after_del_in_group(session, fromeid, rtype, toeid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   398
    """modify user permission, need to update users"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   399
    for session_ in get_user_sessions(session.repo, fromeid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   400
        DeleteGroupOp(session, cnxuser=session_.user, geid=toeid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   401
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   402
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   403
class AddGroupOp(GroupOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   404
    """synchronize user when a in_group relation has been added"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   405
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   406
        """the observed connections pool has been commited"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   407
        groups = self.cnxuser.groups
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   408
        if self.group in groups:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   409
            self.warning('user %s already in group %s', self.cnxuser,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   410
                         self.group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   411
            return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   412
        groups.add(self.group)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   413
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   414
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   415
def after_add_in_group(session, fromeid, rtype, toeid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   416
    """modify user permission, need to update users"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   417
    for session_ in get_user_sessions(session.repo, fromeid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   418
        AddGroupOp(session, cnxuser=session_.user, geid=toeid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   419
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   420
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   421
class DelUserOp(Operation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   422
    """synchronize user when a in_group relation has been added"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   423
    def __init__(self, session, cnxid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   424
        self.cnxid = cnxid
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   425
        Operation.__init__(self, session)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   426
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   427
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   428
        """the observed connections pool has been commited"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   429
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   430
            self.repo.close(self.cnxid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   431
        except BadConnectionId:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   432
            pass # already closed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   433
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   434
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   435
def after_del_user(session, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   436
    """modify user permission, need to update users"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   437
    for session_ in get_user_sessions(session.repo, eid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   438
        DelUserOp(session, session_.id)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   439
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   440
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   441
def _register_usergroup_hooks(hm):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   442
    """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
   443
    hm.register_hook(after_del_user, 'after_delete_entity', 'CWUser')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   444
    hm.register_hook(after_add_in_group, 'after_add_relation', 'in_group')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   445
    hm.register_hook(after_del_in_group, 'after_delete_relation', 'in_group')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   446
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   447
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   448
# workflow handling ###########################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   449
2992
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   450
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
   451
2949
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   452
def _change_state(session, x, oldstate, newstate):
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   453
    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
   454
    nocheck.add((x, 'in_state', oldstate))
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   455
    nocheck.add((x, 'in_state', newstate))
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   456
    # 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
   457
    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
   458
    # 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
   459
    # 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
   460
    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
   461
       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
   462
        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
   463
    session.add_relation(x, 'in_state', newstate)
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   464
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   465
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   466
class FireAutotransitionOp(PreCommitOperation):
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   467
    """try to fire auto transition after state changes"""
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   468
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   469
    def precommit_event(self):
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   470
        session = self.session
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   471
        entity = self.entity
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   472
        autotrs = list(entity.possible_transitions('auto'))
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   473
        if autotrs:
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   474
            assert len(autotrs) == 1
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   475
            entity.fire_transition(autotrs[0])
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   476
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   477
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   478
def before_add_trinfo(session, entity):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   479
    """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
   480
    * wf_info_for inlined relation is set
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   481
    * by_transition or to_state (managers only) inlined relation is set
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
    """
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   483
    # 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
   484
    try:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   485
        foreid = entity['wf_info_for']
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   486
    except KeyError:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   487
        msg = session._('mandatory relation')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   488
        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
   489
    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
   490
    # 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
   491
    # entity's workflow
2978
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   492
    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
   493
        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
   494
        wf = session.entity_from_eid(wfeid)
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   495
    else:
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   496
        wf = forentity.current_workflow
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   497
    if wf is None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   498
        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
   499
        raise ValidationError(entity.eid, {None: msg})
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   500
    # then check it has a state set
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   501
    fromstate = forentity.current_state
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   502
    if fromstate is None:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   503
        msg = session._('related entity has no state')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   504
        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
   505
    # 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
   506
    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
   507
    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
   508
    # no investigate the requested state change...
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   509
    try:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   510
        treid = entity['by_transition']
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   511
    except KeyError:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   512
        # 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
   513
        # specified (and valid)
2992
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   514
        if not cowpowers:
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   515
            msg = session._('mandatory relation')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   516
            raise ValidationError(entity.eid, {'by_transition': msg})
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   517
        deststateeid = entity.get('to_state')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   518
        if not deststateeid:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   519
            msg = session._('mandatory relation')
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   520
            raise ValidationError(entity.eid, {'by_transition': msg})
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   521
        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
   522
        if deststate is None:
14fde27a70a2 don't allow that even with cow powers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3693
diff changeset
   523
            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
   524
            raise ValidationError(entity.eid, {'to_state': msg})
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   525
    else:
2992
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   526
        # 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
   527
        # subworkflow
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   528
        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
   529
        if swtr is None:
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   530
            if tr is None:
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   531
                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
   532
                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
   533
            if not tr.has_input_state(fromstate):
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   534
                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
   535
                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
   536
            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
   537
                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
   538
                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
   539
        if entity.get('to_state'):
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   540
            deststateeid = entity['to_state']
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   541
            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
   542
                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
   543
                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
   544
            if swtr is None:
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   545
                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
   546
                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
   547
                    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
   548
                    raise ValidationError(entity.eid, {'to_state': msg})
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   549
        else:
2992
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   550
            deststateeid = tr.destination().eid
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   551
    # 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
   552
    entity['from_state'] = fromstate.eid
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   553
    entity['to_state'] = deststateeid
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   554
    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
   555
    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
   556
    nocheck.add((entity.eid, 'to_state', deststateeid))
3528
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   557
    FireAutotransitionOp(session, entity=forentity)
77a69de16709 support for automatic transition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3508
diff changeset
   558
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   559
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   560
def after_add_trinfo(session, entity):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   561
    """change related entity state"""
2949
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   562
    _change_state(session, entity['wf_info_for'],
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   563
                  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
   564
    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
   565
    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
   566
        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
   567
    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
   568
        SubWorkflowExitOp(session, forentity=forentity, trinfo=entity)
9eeadad82d93 defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3628
diff changeset
   569
9eeadad82d93 defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3628
diff changeset
   570
class SubWorkflowExitOp(PreCommitOperation):
9eeadad82d93 defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3628
diff changeset
   571
    def precommit_event(self):
9eeadad82d93 defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3628
diff changeset
   572
        session = self.session
9eeadad82d93 defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3628
diff changeset
   573
        forentity = self.forentity
9eeadad82d93 defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3628
diff changeset
   574
        trinfo = self.trinfo
2992
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   575
        # 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
   576
        wftr = forentity.subworkflow_input_transition()
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   577
        if wftr is None:
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   578
            # inconsistency detected
3662
9eeadad82d93 defer trinfo creation when cancelling subworkflow
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3628
diff changeset
   579
            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
   580
            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
   581
        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
   582
        if tostate is not None:
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   583
            # reached an exit point
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   584
            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
   585
            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
   586
            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
   587
            # XXX iirk
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   588
            req = forentity.req
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   589
            forentity.req = session.super_session
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   590
            try:
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   591
                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
   592
                                                tr=wftr)
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   593
            finally:
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   594
                forentity.req = req
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   595
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   597
class SetInitialStateOp(PreCommitOperation):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   598
    """make initial state be a default state"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   599
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   600
    def precommit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   601
        session = self.session
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   602
        entity = self.entity
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   603
        # if there is an initial state and the entity's state is not set,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   604
        # 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
   605
        pendingeids = session.transaction_data.get('pendingeids', ())
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   606
        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
   607
               entity.main_workflow:
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   608
            state = entity.main_workflow.initial
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   609
            if state:
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   610
                # 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
   611
                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
   612
                                                   state.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   613
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   614
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   615
def set_initial_state_after_add(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   616
    SetInitialStateOp(session, entity=entity)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   617
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   618
2983
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   619
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
   620
    """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
   621
    """
3508
d9915224f9a5 [B] server: fix initial data structure in session.transaction_data
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3071
diff changeset
   622
    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
   623
    if (eidfrom, 'in_state', eidto) in nocheck:
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   624
        # 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
   625
        return
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   626
    entity = session.entity_from_eid(eidfrom)
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   627
    mainwf = entity.main_workflow
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   628
    if mainwf is None:
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   629
        msg = session._('entity has no workflow set')
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   630
        raise ValidationError(entity.eid, {None: msg})
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   631
    for wf in mainwf.iter_workflows():
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   632
        if wf.state_by_eid(eidto):
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   633
            break
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   634
    else:
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   635
        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
   636
                        "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
   637
        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
   638
    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
   639
        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
   640
        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
   641
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   642
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   643
class CheckTrExitPoint(PreCommitOperation):
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   644
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   645
    def precommit_event(self):
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   646
        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
   647
        outputs = set()
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   648
        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
   649
            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
   650
                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
   651
                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
   652
            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
   653
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   654
a5b8bf107a1a [wf] test and hooks for WorkflowTransition support
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2985
diff changeset
   655
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
   656
    CheckTrExitPoint(session, treid=eidfrom)
2983
b458631fe347 [wf] test in_state consistency
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2978
diff changeset
   657
2949
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   658
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   659
class WorkflowChangedOp(PreCommitOperation):
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   660
    """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
   661
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   662
    def precommit_event(self):
2985
79185b3ccf2c cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2983
diff changeset
   663
        # notice that enforcement that new workflow apply to the entity's type is
79185b3ccf2c cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2983
diff changeset
   664
        # 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
   665
        session = self.session
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   666
        pendingeids = session.transaction_data.get('pendingeids', ())
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   667
        if self.eid in pendingeids:
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   668
            return
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   669
        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
   670
        # 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
   671
        # transaction
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   672
        mainwf = entity.main_workflow
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   673
        if mainwf.eid == self.wfeid:
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   674
            deststate = mainwf.initial
2949
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   675
            if not deststate:
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   676
                msg = session._('workflow has no initial state')
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   677
                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
   678
            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
   679
                # nothing to do
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   680
                return
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   681
            # 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
   682
            if not entity.workflow_history:
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   683
                if entity.current_state.eid != deststate.eid:
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   684
                    _change_state(session, entity.eid,
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   685
                                  entity.current_state.eid, deststate.eid)
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   686
                return
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   687
            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
   688
            msg %= session._(mainwf.name)
d8c5ad14ab8e [wf] distinguish main workflow / current workflow
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2949
diff changeset
   689
            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
   690
            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
   691
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   692
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   693
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
   694
    WorkflowChangedOp(session, eid=eidfrom, wfeid=eidto)
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   695
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   696
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   697
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
   698
    entity = session.entity_from_eid(eidfrom)
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   699
    typewf = entity.cwetype_workflow()
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   700
    if typewf is not None:
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   701
        WorkflowChangedOp(session, eid=eidfrom, wfeid=typewf.eid)
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   702
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   703
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   704
def after_del_workflow(session, eid):
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   705
    # workflow cleanup
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   706
    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
   707
    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
   708
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   709
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   710
def _register_wf_hooks(hm):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   711
    """register workflow related hooks on the hooks manager"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   712
    if 'in_state' in hm.schema:
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2909
diff changeset
   713
        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
   714
        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
   715
        #hm.register_hook(relation_deleted, 'before_delete_relation', 'in_state')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   716
        for eschema in hm.schema.entities():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   717
            if 'in_state' in eschema.subject_relations():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   718
                hm.register_hook(set_initial_state_after_add, 'after_add_entity',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   719
                                 str(eschema))
2949
a2aa2c51f3be test and implements workflow changes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2920
diff changeset
   720
        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
   721
        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
   722
        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
   723
        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
   724
        hm.register_hook(after_add_subworkflow_exit, 'after_add_relation', 'subworkflow_exit')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   725
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   726
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   727
# CWProperty hooks #############################################################
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   728
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   729
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   730
class DelCWPropertyOp(Operation):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   731
    """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
   732
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   733
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   734
        """the observed connections pool has been commited"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   735
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   736
            del self.epropdict[self.key]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   737
        except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   738
            self.error('%s has no associated value', self.key)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   739
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   740
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   741
class ChangeCWPropertyOp(Operation):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   742
    """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
   743
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   744
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
        """the observed connections pool has been commited"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   746
        self.epropdict[self.key] = self.value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   747
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   748
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   749
class AddCWPropertyOp(Operation):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
    """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
   751
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
    def commit_event(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   753
        """the observed connections pool has been commited"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   754
        eprop = self.eprop
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   755
        if not eprop.for_user:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   756
            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
   757
        # if for_user is set, update is handled by a ChangeCWPropertyOp operation
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   759
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   760
def after_add_eproperty(session, entity):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   761
    key, value = entity.pkey, entity.value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   762
    try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   763
        value = session.vreg.typed_value(key, value)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   764
    except UnknownProperty:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   765
        raise ValidationError(entity.eid, {'pkey': session._('unknown property key')})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   766
    except ValueError, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   767
        raise ValidationError(entity.eid, {'value': session._(str(ex))})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   768
    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
   769
        session.add_relation(entity.eid, 'for_user', session.user.eid)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   770
    else:
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   771
        AddCWPropertyOp(session, eprop=entity)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   772
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   773
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   774
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
   775
    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
   776
            '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
   777
        return
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   778
    key, value = entity.pkey, entity.value
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   779
    try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   780
        value = session.vreg.typed_value(key, value)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   781
    except UnknownProperty:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   782
        return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   783
    except ValueError, ex:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   784
        raise ValidationError(entity.eid, {'value': session._(str(ex))})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   785
    if entity.for_user:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   786
        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
   787
            ChangeCWPropertyOp(session, epropdict=session_.user.properties,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   788
                              key=key, value=value)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   789
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   790
        # site wide properties
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1263
diff changeset
   791
        ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   792
                          key=key, value=value)
1802
d628defebc17 delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1398
diff changeset
   793
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   794
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   795
def before_del_eproperty(session, eid):
2101
08003e0354a7 update transaction data api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   796
    for eidfrom, rtype, eidto in session.transaction_data.get('pendingrelations', ()):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   797
        if rtype == 'for_user' and eidfrom == eid:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   798
            # if for_user was set, delete has already been handled
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   799
            break
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   800
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   801
        key = session.execute('Any K WHERE P eid %(x)s, P pkey K',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   802
                              {'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
   803
        DelCWPropertyOp(session, epropdict=session.vreg.eprop_values, key=key)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   804
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   805
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   806
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
   807
    if not session.describe(fromeid)[0] == 'CWProperty':
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   808
        return
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   809
    key, value = session.execute('Any K,V WHERE P eid %(x)s,P pkey K,P value V',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   810
                                 {'x': fromeid}, 'x')[0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   811
    if session.vreg.property_info(key)['sitewide']:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   812
        raise ValidationError(fromeid,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   813
                              {'for_user': session._("site-wide property can't be set for user")})
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   814
    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
   815
        ChangeCWPropertyOp(session, epropdict=session_.user.properties,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   816
                          key=key, value=value)
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
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   819
def before_del_for_user(session, fromeid, rtype, toeid):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   820
    key = session.execute('Any K WHERE P eid %(x)s, P pkey K',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   821
                          {'x': fromeid}, 'x')[0][0]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   822
    relation_deleted(session, fromeid, rtype, toeid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
    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
   824
        DelCWPropertyOp(session, epropdict=session_.user.properties, key=key)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
2603
e47d63351891 [R hooks] optmize insertion by using direct repository methods when possible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2463
diff changeset
   826
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   827
def _register_eproperty_hooks(hm):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   828
    """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
   829
    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
   830
    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
   831
    hm.register_hook(before_del_eproperty, 'before_delete_entity', 'CWProperty')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   832
    hm.register_hook(after_add_for_user, 'after_add_relation', 'for_user')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   833
    hm.register_hook(before_del_for_user, 'before_delete_relation', 'for_user')