hooks/workflow.py
changeset 4835 13b0b96d7982
parent 4719 aaed3f813ef8
child 5030 5238d9a8dfee
equal deleted inserted replaced
4834:b718626a0e60 4835:13b0b96d7982
    17 
    17 
    18 def _change_state(session, x, oldstate, newstate):
    18 def _change_state(session, x, oldstate, newstate):
    19     nocheck = session.transaction_data.setdefault('skip-security', set())
    19     nocheck = session.transaction_data.setdefault('skip-security', set())
    20     nocheck.add((x, 'in_state', oldstate))
    20     nocheck.add((x, 'in_state', oldstate))
    21     nocheck.add((x, 'in_state', newstate))
    21     nocheck.add((x, 'in_state', newstate))
    22     # delete previous state first in case we're using a super session,
    22     # delete previous state first unless in_state isn't stored in the system
    23     # unless in_state isn't stored in the system source
    23     # source
    24     fromsource = session.describe(x)[1]
    24     fromsource = session.describe(x)[1]
    25     if fromsource == 'system' or \
    25     if fromsource == 'system' or \
    26            not session.repo.sources_by_uri[fromsource].support_relation('in_state'):
    26            not session.repo.sources_by_uri[fromsource].support_relation('in_state'):
    27         session.delete_relation(x, 'in_state', oldstate)
    27         session.delete_relation(x, 'in_state', oldstate)
    28     session.add_relation(x, 'in_state', newstate)
    28     session.add_relation(x, 'in_state', newstate)
    40         # use the initial state as a default state
    40         # use the initial state as a default state
    41         if not (session.deleted_in_transaction(entity.eid) or entity.in_state) \
    41         if not (session.deleted_in_transaction(entity.eid) or entity.in_state) \
    42                and entity.current_workflow:
    42                and entity.current_workflow:
    43             state = entity.current_workflow.initial
    43             state = entity.current_workflow.initial
    44             if state:
    44             if state:
    45                 # use super session to by-pass security checks
    45                 session.add_relation(entity.eid, 'in_state', state.eid)
    46                 session.super_session.add_relation(entity.eid, 'in_state',
       
    47                                                    state.eid)
       
    48 
    46 
    49 
    47 
    50 class _FireAutotransitionOp(hook.Operation):
    48 class _FireAutotransitionOp(hook.Operation):
    51     """try to fire auto transition after state changes"""
    49     """try to fire auto transition after state changes"""
    52 
    50 
   120         if tostate is not None:
   118         if tostate is not None:
   121             # reached an exit point
   119             # reached an exit point
   122             msg = session._('exiting from subworkflow %s')
   120             msg = session._('exiting from subworkflow %s')
   123             msg %= session._(forentity.current_workflow.name)
   121             msg %= session._(forentity.current_workflow.name)
   124             session.transaction_data[(forentity.eid, 'subwfentrytr')] = True
   122             session.transaction_data[(forentity.eid, 'subwfentrytr')] = True
   125             # XXX iirk
   123             forentity.change_state(tostate, msg, u'text/plain', tr=wftr)
   126             req = forentity._cw
       
   127             forentity._cw = session.super_session
       
   128             try:
       
   129                 trinfo = forentity.change_state(tostate, msg, u'text/plain',
       
   130                                                 tr=wftr)
       
   131             finally:
       
   132                 forentity._cw = req
       
   133 
   124 
   134 
   125 
   135 # hooks ########################################################################
   126 # hooks ########################################################################
   136 
   127 
   137 class WorkflowHook(hook.Hook):
   128 class WorkflowHook(hook.Hook):
   193         if fromstate is None:
   184         if fromstate is None:
   194             msg = session._('related entity has no state')
   185             msg = session._('related entity has no state')
   195             raise ValidationError(entity.eid, {None: msg})
   186             raise ValidationError(entity.eid, {None: msg})
   196         # True if we are coming back from subworkflow
   187         # True if we are coming back from subworkflow
   197         swtr = session.transaction_data.pop((forentity.eid, 'subwfentrytr'), None)
   188         swtr = session.transaction_data.pop((forentity.eid, 'subwfentrytr'), None)
   198         cowpowers = session.is_super_session or 'managers' in session.user.groups
   189         cowpowers = ('managers' in session.user.groups
       
   190                      or not session.write_security)
   199         # no investigate the requested state change...
   191         # no investigate the requested state change...
   200         try:
   192         try:
   201             treid = entity['by_transition']
   193             treid = entity['by_transition']
   202         except KeyError:
   194         except KeyError:
   203             # no transition set, check user is a manager and destination state
   195             # no transition set, check user is a manager and destination state
   264         if forentity.main_workflow.eid != forentity.current_workflow.eid:
   256         if forentity.main_workflow.eid != forentity.current_workflow.eid:
   265             _SubWorkflowExitOp(self._cw, forentity=forentity, trinfo=trinfo)
   257             _SubWorkflowExitOp(self._cw, forentity=forentity, trinfo=trinfo)
   266 
   258 
   267 
   259 
   268 class CheckInStateChangeAllowed(WorkflowHook):
   260 class CheckInStateChangeAllowed(WorkflowHook):
   269     """check state apply, in case of direct in_state change using unsafe_execute
   261     """check state apply, in case of direct in_state change using unsafe execute
   270     """
   262     """
   271     __regid__ = 'wfcheckinstate'
   263     __regid__ = 'wfcheckinstate'
   272     __select__ = WorkflowHook.__select__ & hook.match_rtype('in_state')
   264     __select__ = WorkflowHook.__select__ & hook.match_rtype('in_state')
   273     events = ('before_add_relation',)
   265     events = ('before_add_relation',)
   274 
   266 
   305         if self._cw.added_in_transaction(self.eidfrom):
   297         if self._cw.added_in_transaction(self.eidfrom):
   306             # new entity, not needed
   298             # new entity, not needed
   307             return
   299             return
   308         entity = self._cw.entity_from_eid(self.eidfrom)
   300         entity = self._cw.entity_from_eid(self.eidfrom)
   309         try:
   301         try:
   310             entity.set_attributes(modification_date=datetime.now(),
   302             entity.set_attributes(modification_date=datetime.now())
   311                                   _cw_unsafe=True)
       
   312         except RepositoryError, ex:
   303         except RepositoryError, ex:
   313             # usually occurs if entity is coming from a read-only source
   304             # usually occurs if entity is coming from a read-only source
   314             # (eg ldap user)
   305             # (eg ldap user)
   315             self.warning('cant change modification date for %s: %s', entity, ex)
   306             self.warning('cant change modification date for %s: %s', entity, ex)
   316 
   307