Exemplo n.º 1
0
  def getInfoFor(self, ob, name, default):
    '''
    Allows the user to request information provided by the
    workflow.  This method must perform its own security checks.
    '''
    vdef = getattr(self, name, _MARKER)
    for r, v in six.iteritems(self.getVariableValueDict()):
      if r == name:
        vdef = v
        break
    if vdef is _MARKER:
      return default
    if not vdef.checkGuard(getSecurityManager(), self, ob):
      return default
    status = self._getStatusOf(ob)
    variable_default_expression = vdef.getVariableDefaultExpression()
    if status is not None and name in status:
      value = status[name]
    # Not set yet.  Use a default.
    elif variable_default_expression is not None:
      ec = createExpressionContext(StateChangeInfo(ob, self, status))
      value = variable_default_expression(ec)
    else:
      value = ''

    return value
Exemplo n.º 2
0
 def activeScript(self, script_name, ob_url, status, tdef_id):
   script = self.scripts[script_name]
   ob = self.unrestrictedTraverse(ob_url)
   tdef = self.interactions.get(tdef_id)
   sci = StateChangeInfo(
                 ob, self, status, tdef, None, None, None)
   script(sci)
Exemplo n.º 3
0
    def search(self, info=None, **kw):
        """ Perform the search corresponding to this worklist

        Returns sequence of ZCatalog brains
        - info is a mapping for resolving formatted string variable references
        - additional keyword/value pairs may be used to restrict the query
        """
        if not self.var_matches:
            return

        if info is None:
            info = {}

        catalog = getToolByName(self, 'portal_catalog')
        criteria = {}

        for key, values in self.var_matches.items():
            if isinstance(values, Expression):
                wf = self.getWorkflow()
                portal = wf._getPortalRoot()
                context = createExprContext(StateChangeInfo(portal, wf))
                criteria[key] = values(context)
            else:
                criteria[key] = [x % info for x in values]

        criteria.update(kw)

        return catalog.searchResults(**criteria)
Exemplo n.º 4
0
    def getCatalogVariablesFor(self, ob):
        '''
        Allows this workflow to make workflow-specific variables
        available to the catalog, making it possible to implement
        worklists in a simple way.
        Returns a mapping containing the catalog variables
        that apply to ob.
        '''
        res = {}
        status = self._getStatusOf(ob)
        for id, vdef in self.variables.items():
            if vdef.for_catalog:
                if status.has_key(id):
                    value = status[id]

                # Not set yet.  Use a default.
                elif vdef.default_expr is not None:
                    ec = createExprContext(StateChangeInfo(ob, self, status))
                    value = vdef.default_expr(ec)
                else:
                    value = vdef.default_value

                res[id] = value
        # Always provide the state variable.
        state_var = self.state_var
        res[state_var] = status.get(state_var, self.initial_state)
        return res
Exemplo n.º 5
0
  def notifyBefore(self, ob, transition_list, args=None, kw=None):
    '''
    Notifies this workflow of an action before it happens,
    allowing veto by exception.  Unless an exception is thrown, either
    a notifySuccess() or notifyException() can be expected later on.
    The action usually corresponds to a method name.
    '''
    if isinstance(transition_list, basestring):
      return

    # Wrap args into kw since this is the only way to be compatible with
    # DCWorkflow. A better approach consists in extending DCWorkflow
    if kw is None:
      kw = {'workflow_method_args' : args}
    else:
      kw = kw.copy()
      kw['workflow_method_args'] = args
    filtered_transition_list = []
    append = filtered_transition_list.append
    for t_id in transition_list:
      tdef = self.getTransitionValueByReference(t_id)
      assert tdef.getTriggerType() == TRIGGER_WORKFLOW_METHOD
      append(tdef.getId())
      former_status = self._getStatusOf(ob)
      # Pass lots of info to the script in a single parameter.
      sci = StateChangeInfo(ob, self, former_status, tdef, None, None, kwargs=kw)
      for script in tdef.getBeforeScriptValueList():
        script(sci)  # May throw an exception.
    return filtered_transition_list
Exemplo n.º 6
0
    def checkGuard(self, security_manager, workflow, current_object, **kw):
        """
    Checks conditions in this guard. Original source code from DCWorkflow
    (Nexedi patch for proxy_roles)
    """
        user_roles = None

        def getRoles():
            stack = security_manager._context.stack
            if stack:
                proxy_roles = getattr(stack[-1], '_proxy_roles', None)
                if proxy_roles:
                    return proxy_roles
            return security_manager.getUser().getRolesInContext(current_object)

        if workflow.isManagerBypass():
            # Possibly bypass.
            user_roles = getRoles()
            if 'Manager' in user_roles:
                return True
        guard_permission_list = self.getGuardPermissionList()
        if guard_permission_list:
            for permission in guard_permission_list:
                if _checkPermission(permission, current_object):
                    break
            else:
                return False
        guard_role_list = self.getGuardRoleList()
        if guard_role_list:
            # Require at least one of the given roles.
            if user_roles is None:
                user_roles = getRoles()
            for role in guard_role_list:
                if role in user_roles:
                    break
            else:
                return False
        guard_group_list = self.getGuardGroupList()
        if guard_group_list:
            # Require at least one of the specified groups.
            user = security_manager.getUser()
            base = aq_base(user)
            if hasattr(base, 'getGroupsInContext'):
                user_groups = user.getGroupsInContext(current_object)
            elif hasattr(base, 'getGroups'):
                user_groups = user.getGroups()
            else:
                user_groups = ()
            for group in guard_group_list:
                if group in user_groups:
                    break
            else:
                return False
        guard_expression = self.getGuardExpressionInstance()
        if guard_expression is not None:
            return guard_expression(
                createExpressionContext(
                    StateChangeInfo(current_object, workflow, kwargs=kw)))
        return True
Exemplo n.º 7
0
 def callInterationScript(self, script_name, ob, status, tdef_id):
   self._getOb(script_name)(
     StateChangeInfo(
       ob, self, status,
       self.getTransitionValueByReference(tdef_id),
       None, None, None,
     ),
   )
Exemplo n.º 8
0
 def callInterationScript(self, script_name, ob, status, tdef_id):
     self.scripts[script_name](StateChangeInfo(
         ob,
         self,
         status,
         self.interactions.get(tdef_id),
         None,
         None,
         None,
     ), )
def execute(self, document, form_kw=None):
    """
  Execute transition.
  """
    workflow = self.getParentValue()
    # Call the before script
    _executeBeforeScript(self, document)

    # Modify the state
    _changeState(self, document)

    # Get variable values
    status_dict = workflow.getCurrentStatusDict(document)
    status_dict['undo'] = 0

    # Modify workflow history
    state_bc_id = workflow.getStateBaseCategory()
    state_object = document.unrestrictedTraverse(
        document.getCategoryMembershipList(state_bc_id)[0])
    status_dict[state_bc_id] = state_object.getReference()
    object_ = workflow.getStateChangeInformation(document,
                                                 state_object,
                                                 transition=self)

    # Update all variables
    expression_context = None
    for variable in workflow.getVariableValueList():
        if variable.getAutomaticUpdate():
            # if we have it in form get it from there
            # otherwise use default
            variable_title = variable.getTitle()
            if variable_title in form_kw:
                status_dict[variable_title] = form_kw[variable_title]
            else:
                expression = variable.getVariableDefaultExpressionInstance()
                if expression is not None:
                    if expression_context is None:
                        from Products.ERP5Type.Core.Workflow import createExpressionContext
                        from Products.DCWorkflow.Expression import StateChangeInfo
                        expression_context = createExpressionContext(
                            StateChangeInfo(document, self, status_dict))
                    status_dict[variable_title] = expression(
                        expression_context)

    # Update all transition variables
    if form_kw is not None:
        object_.REQUEST.other.update(form_kw)
    for variable in self.getTransitionVariableValueList():
        status_dict[variable.getCausalityTitle()] = variable.getInitialValue(
            object=object_)

    _updateWorkflowHistory(workflow, document, status_dict)

    # Call the after script
    _executeAfterScript(self, document, form_kw=form_kw)
Exemplo n.º 10
0
    def has_permission(self, transition):
        guard = transition.guard
        if guard is None:
            return True

        for permission in guard.permissions or []:
            # need to manually check permissions here because
            # we don't have an object to check against
            check_parent = True
            if permission in self.initial_state.permissions:
                # check if acquire set for initial_state.
                # if acquire, you can check against parent
                pinfo = self.initial_state.getPermissionInfo(permission)
                if pinfo.get('acquired'):
                    check_parent = True
                else:
                    check_parent = False
                    if len(set(self.folder_roles) & set(pinfo['roles'])) > 0:
                        break
            if check_parent:
                if self.sm.checkPermission(permission, self.folder):
                    break
        else:
            # no perms valid...
            return False

        if guard.roles:
            for role in guard.roles:
                if role in self.folder_roles:
                    break
            else:
                return False

        if guard.groups:
            for group in guard.groups:
                if group in self.u_groups:
                    break
            else:
                return False

        if guard.expr is not None:
            econtext = createExprContext(
                StateChangeInfo(self.folder,
                                aq_parent(aq_parent(self.initial_state))))
            res = guard.expr(econtext)
            if not res:
                return False

        return True
Exemplo n.º 11
0
 def _checkTransitionGuard(self, guard, sm, wf_def, ob):
     """
       This method is similar to DCWorkflow.Guard.check, but allows to
       retrieve the truth value as a appy.gen.No instance, not simply "1"
       or "0".
     """
     u_roles = None
     if wf_def.manager_bypass:
         # Possibly bypass.
         u_roles = sm.getRolesInContext(ob)
         if 'Manager' in u_roles:
             return 1
     if guard.permissions:
         for p in guard.permissions:
             if _checkPermission(p, ob):
                 break
         else:
             return 0
     if guard.roles:
         # Require at least one of the given roles.
         if u_roles is None:
             u_roles = sm.getRolesInContext(ob)
         for role in guard.roles:
             if role in u_roles:
                 break
         else:
             return 0
     if guard.groups:
         # Require at least one of the specified groups.
         u = sm.getUser()
         b = aq_base(u)
         if hasattr(b, 'getGroupsInContext'):
             u_groups = u.getGroupsInContext(ob)
         elif hasattr(b, 'getGroups'):
             u_groups = u.getGroups()
         else:
             u_groups = ()
         for group in guard.groups:
             if group in u_groups:
                 break
         else:
             return 0
     expr = guard.expr
     if expr is not None:
         econtext = createExprContext(StateChangeInfo(ob, wf_def))
         res = expr(econtext)
         return res
     return 1
Exemplo n.º 12
0
 def check(self, sm, wf_def, ob, **kw):
     """Checks conditions in this guard.
     """
     u_roles = None
     if wf_def.manager_bypass:
         # Possibly bypass.
         u_roles = sm.getUser().getRolesInContext(ob)
         if 'Manager' in u_roles:
             return 1
     if self.permissions:
         for p in self.permissions:
             if _checkPermission(p, ob):
                 break
         else:
             return 0
     if self.roles:
         # Require at least one of the given roles.
         if u_roles is None:
             u_roles = sm.getUser().getRolesInContext(ob)
         for role in self.roles:
             if role in u_roles:
                 break
         else:
             return 0
     if self.groups:
         # Require at least one of the specified groups.
         u = sm.getUser()
         b = aq_base(u)
         if hasattr(b, 'getGroupsInContext'):
             u_groups = u.getGroupsInContext(ob)
         elif hasattr(b, 'getGroups'):
             u_groups = u.getGroups()
         else:
             u_groups = ()
         for group in self.groups:
             if group in u_groups:
                 break
         else:
             return 0
     expr = self.expr
     if expr is not None:
         econtext = createExprContext(
             StateChangeInfo(ob, wf_def, kwargs=kw))
         res = expr(econtext)
         if not res:
             return 0
     return 1
Exemplo n.º 13
0
    def _executeTransition(self, ob, tdef=None, kwargs=None):
        '''
        Private method.
        Puts object in a new state.
        '''
        sci = None
        econtext = None
        moved_exc = None

        # Figure out the old and new states.
        old_sdef = self._getWorkflowStateOf(ob)
        old_state = old_sdef.getId()
        if tdef is None:
            new_state = self.initial_state
            former_status = {}
        else:
            new_state = tdef.new_state_id
            if not new_state:
                # Stay in same state.
                new_state = old_state
            former_status = self._getStatusOf(ob)
        new_sdef = self.states.get(new_state, None)
        if new_sdef is None:
            msg = _(u'Destination state undefined: ${state_id}',
                    mapping={'state_id': new_state})
            raise WorkflowException(msg)

        # Fire "before" event
        notify(
            BeforeTransitionEvent(ob, self, old_sdef, new_sdef, tdef,
                                  former_status, kwargs))

        # Execute the "before" script.
        if tdef is not None and tdef.script_name:
            script = self.scripts[tdef.script_name]
            # Pass lots of info to the script in a single parameter.
            sci = StateChangeInfo(ob, self, former_status, tdef, old_sdef,
                                  new_sdef, kwargs)
            try:
                script(sci)  # May throw an exception.
            except ObjectMoved, moved_exc:
                ob = moved_exc.getNewObject()
Exemplo n.º 14
0
    def notifyBefore(self, ob, transition_list, args=None, kw=None):
        '''
    Notifies this workflow of an action before it happens,
    allowing veto by exception.  Unless an exception is thrown, either
    a notifySuccess() or notifyException() can be expected later on.
    The action usually corresponds to a method name.
    '''
        if type(transition_list) in StringTypes:
            return

        # Wrap args into kw since this is the only way
        # to be compatible with DCWorkflow
        # A better approach consists in extending DCWorkflow
        if kw is None:
            kw = {'workflow_method_args': args}
        else:
            kw = kw.copy()
            kw['workflow_method_args'] = args
        filtered_transition_list = []

        for t_id in transition_list:
            tdef = self.interactions[t_id]
            assert tdef.trigger_type == TRIGGER_WORKFLOW_METHOD
            filtered_transition_list.append(tdef.id)
            former_status = self._getStatusOf(ob)
            # Execute the "before" script.
            for script_name in tdef.script_name:
                script = self.scripts[script_name]
                # Pass lots of info to the script in a single parameter.
                sci = StateChangeInfo(ob,
                                      self,
                                      former_status,
                                      tdef,
                                      None,
                                      None,
                                      kwargs=kw)
                script(sci)  # May throw an exception

        return filtered_transition_list
Exemplo n.º 15
0
    def getInfoFor(self, ob, name, default):
        '''
    Allows the user to request information provided by the
    workflow.  This method must perform its own security checks.
    '''
        vdef = self.variables.get(name, _MARKER)
        if vdef is _MARKER:
            return default
        if vdef.info_guard is not None and not vdef.info_guard.check(
                getSecurityManager(), self, ob):
            return default
        status = self._getStatusOf(ob)
        if status is not None and status.has_key(name):
            value = status[name]
        # Not set yet.  Use a default.
        elif vdef.default_expr is not None:
            ec = createExprContext(StateChangeInfo(ob, self, status))
            value = vdef.default_expr(ec)
        else:
            value = vdef.default_value

        return value
Exemplo n.º 16
0
                expr = tdef_exprs[id]
            elif not vdef.update_always and former_status.has_key(id):
                # Preserve former value
                value = former_status[id]
            else:
                if vdef.default_expr is not None:
                    expr = vdef.default_expr
                else:
                    value = vdef.default_value
            if expr is not None:
                # Evaluate an expression.
                if econtext is None:
                    # Lazily create the expression context.
                    if sci is None:
                        sci = StateChangeInfo(
                            ob, self, former_status, tdef,
                            old_sdef, new_sdef, kwargs)
                    econtext = createExprContext(sci)
                value = expr(econtext)
            status[id] = value

        # Update state.
        status[self.state_var] = new_state
        tool = aq_parent(aq_inner(self))
        tool.setStatusOf(self.id, ob, status)

        # Update role to permission assignments.
        self.updateRoleMappingsFor(ob)

        # Execute the "after" script.
        if tdef is not None and tdef.after_script_name:
Exemplo n.º 17
0
    def _executeTransition(self, ob, tdef=None, kwargs=None):
        '''
        Private method.
        Puts object in a new state.
        '''
        sci = None
        econtext = None
        moved_exc = None

        # Figure out the old and new states.
        old_sdef = self._getWorkflowStateOf(ob)
        old_state = old_sdef.getId()
        if tdef is None:
            new_state = self.initial_state
            former_status = {}
        else:
            new_state = tdef.new_state_id
            if not new_state:
                # Stay in same state.
                new_state = old_state
            former_status = self._getStatusOf(ob)
        new_sdef = self.states.get(new_state, None)
        if new_sdef is None:
            msg = _(u'Destination state undefined: ${state_id}',
                    mapping={'state_id': new_state})
            raise WorkflowException(msg)

        # Fire "before" event
        notify(BeforeTransitionEvent(ob, self, old_sdef, new_sdef, tdef,
                                     former_status, kwargs))

        # Execute the "before" script.
        if tdef is not None and tdef.script_name:
            script = self.scripts[tdef.script_name]
            # Pass lots of info to the script in a single parameter.
            sci = StateChangeInfo(
                ob, self, former_status, tdef, old_sdef, new_sdef, kwargs)
            try:
                script(sci)  # May throw an exception.
            except ObjectMoved as moved_exc:
                ob = moved_exc.getNewObject()
                # Re-raise after transition

        # Update variables.
        state_values = new_sdef.var_values
        if state_values is None:
            state_values = {}
        tdef_exprs = None
        if tdef is not None:
            tdef_exprs = tdef.var_exprs
        if tdef_exprs is None:
            tdef_exprs = {}
        status = {}
        for id, vdef in self.variables.items():
            if not vdef.for_status:
                continue
            expr = None
            if id in state_values:
                value = state_values[id]
            elif id in tdef_exprs:
                expr = tdef_exprs[id]
            elif not vdef.update_always and id in former_status:
                # Preserve former value
                value = former_status[id]
            else:
                if vdef.default_expr is not None:
                    expr = vdef.default_expr
                else:
                    value = vdef.default_value
            if expr is not None:
                # Evaluate an expression.
                if econtext is None:
                    # Lazily create the expression context.
                    if sci is None:
                        sci = StateChangeInfo(
                            ob, self, former_status, tdef,
                            old_sdef, new_sdef, kwargs)
                    econtext = createExprContext(sci)
                value = expr(econtext)
            status[id] = value

        # Update state.
        status[self.state_var] = new_state
        tool = aq_parent(aq_inner(self))
        tool.setStatusOf(self.id, ob, status)

        # Update role to permission assignments.
        self.updateRoleMappingsFor(ob)

        # Execute the "after" script.
        if tdef is not None and tdef.after_script_name:
            script = self.scripts[tdef.after_script_name]
            # Pass lots of info to the script in a single parameter.
            sci = StateChangeInfo(
                ob, self, status, tdef, old_sdef, new_sdef, kwargs)
            script(sci)  # May throw an exception.

        # Fire "after" event
        notify(AfterTransitionEvent(ob, self, old_sdef, new_sdef, tdef, status,
                                    kwargs))

        # Return the new state object.
        if moved_exc is not None:
            # Propagate the notification that the object has moved.
            raise moved_exc
        else:
            return new_sdef
Exemplo n.º 18
0
  def notifySuccess(self, ob, transition_list, result, args=None, kw=None):
    """
    Notifies this workflow that an action has taken place.
    """
    if isinstance(transition_list, basestring):
      return

    if kw is None:
      kw = {}
    else:
      kw = kw.copy()
    kw['workflow_method_args'] = args
    kw['workflow_method_result'] = result

    workflow_variable_list = self.getVariableValueList()
    for t_id in transition_list:
      tdef = self.getTransitionValueByReference(t_id)
      assert tdef.getTriggerType() == TRIGGER_WORKFLOW_METHOD

      # Initialize variables
      former_status = self._getStatusOf(ob)
      econtext = None
      sci = None

      # Update variables.
      status = {}
      for vdef in workflow_variable_list:
        id_ = vdef.getId()
        if not vdef.getStatusIncluded():
          continue
        expression = None
        value = ''
        if not vdef.getAutomaticUpdate() and id_ in former_status:
          # Preserve former value
          value = former_status[id_]
        else:
          variable_default_expression = vdef.getVariableDefaultExpression()
          if variable_default_expression is not None:
            expression = variable_default_expression
            if expression is not None:
              # Evaluate an expression.
              if econtext is None:
                # Lazily create the expression context.
                if sci is None:
                  sci = StateChangeInfo(
                      ob, self, former_status, tdef,
                      None, None, None)
                econtext = createExpressionContext(sci)
              value = expression(econtext)
        status[id_] = value

      sci = StateChangeInfo(
            ob, self, former_status, tdef, None, None, kwargs=kw)

      # Execute the "after" script.
      for script in tdef.getAfterScriptValueList():
        script(sci) # May throw an exception.

      # Queue the "Before Commit" scripts
      sm = getSecurityManager()
      for script in tdef.getBeforeCommitScriptValueList():
        transaction.get().addBeforeCommitHook(self._before_commit,
                                              (sci, script.getId(), sm))

      # Execute "activity" scripts
      for script in tdef.getActivateScriptValueList():
        ob.activate(activity='SQLQueue').activeInteractionScript(
          interaction_workflow_path=self.getPhysicalPath(),
          script_name=script.getId(),
          status=status,
          tdef_id=tdef.getId(),
        )
Exemplo n.º 19
0
 def activeScript(self, script_name, ob_url, status, tdef_id):
     ob = self.unrestrictedTraverse(ob_url)
     tdef = self.getTransitionValueByReference(tdef_id)
     sci = StateChangeInfo(ob, self, status, tdef, None, None, None)
     self._getOb(script_name)(sci)
Exemplo n.º 20
0
    def notifySuccess(self, ob, transition_list, result, args=None, kw=None):
        '''
    Notifies this workflow that an action has taken place.
    '''
        if type(transition_list) in StringTypes:
            return

        kw = kw.copy()
        kw['workflow_method_args'] = args
        kw['workflow_method_result'] = result

        for t_id in transition_list:
            tdef = self.interactions[t_id]
            assert tdef.trigger_type == TRIGGER_WORKFLOW_METHOD

            # Initialize variables
            former_status = self._getStatusOf(ob)
            econtext = None
            sci = None

            # Update variables.
            tdef_exprs = tdef.var_exprs
            if tdef_exprs is None: tdef_exprs = {}
            status = {}
            for id, vdef in self.variables.items():
                if not vdef.for_status:
                    continue
                expr = None
                if tdef_exprs.has_key(id):
                    expr = tdef_exprs[id]
                elif not vdef.update_always and former_status.has_key(id):
                    # Preserve former value
                    value = former_status[id]
                else:
                    if vdef.default_expr is not None:
                        expr = vdef.default_expr
                    else:
                        value = vdef.default_value
                if expr is not None:
                    # Evaluate an expression.
                    if econtext is None:
                        # Lazily create the expression context.
                        if sci is None:
                            sci = StateChangeInfo(ob, self, former_status,
                                                  tdef, None, None, None)
                        econtext = createExprContext(sci)
                    value = expr(econtext)
                status[id] = value

            sci = StateChangeInfo(ob,
                                  self,
                                  former_status,
                                  tdef,
                                  None,
                                  None,
                                  kwargs=kw)
            # Execute the "after" script.
            for script_name in tdef.after_script_name:
                script = self.scripts[script_name]
                # Pass lots of info to the script in a single parameter.
                script(sci)  # May throw an exception

            # Queue the "Before Commit" scripts
            sm = getSecurityManager()
            for script_name in tdef.before_commit_script_name:
                transaction.get().addBeforeCommitHook(self._before_commit,
                                                      (sci, script_name, sm))

            # Execute "activity" scripts
            for script_name in tdef.activate_script_name:
                self.activate(activity='SQLQueue')\
                    .activeScript(script_name, ob.getRelativeUrl(),
                                  status, tdef.id)