Пример #1
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
Пример #2
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)
    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 id in status:
                    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
Пример #4
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
Пример #5
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
Пример #6
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
Пример #7
0
def checkTransitionGuard(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".'''
    from Products.DCWorkflow.Expression import StateChangeInfo,createExprContext
    u_roles = None
    if wf_def.manager_bypass:
        # Possibly bypass.
        u_roles = sm.getUser().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.getUser().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
Пример #8
0
 def stateTransationNotify(self, stateChangeInfo):
     econtext = createExprContext(stateChangeInfo)
     
     mFROM = self._resolveMailFromAddress(econtext)
     mTO = self._resolveMailTOAddreses(econtext, stateChangeInfo)
     mCC = self._resolveMailCCAddreses(econtext, stateChangeInfo)
     mCCN = self._resolveMailCCNAddreses(econtext, stateChangeInfo)
     
     options = {}
     if self.message_id_expression:
         options["Message-Id"] = self.message_id_expression(econtext)
     if self.in_replay_to_expression:
         options["In-Reply-To"] = self.in_replay_to_expression(econtext)
     
     self.mail_header_dtml.__dict__.update(econtext.__dict__)
     mHeader = self.mail_header_dtml(client=stateChangeInfo.object)
     
     #TODO fix this patch
     mHeader = unicode(mHeader,"latin-1").encode("latin-1","replace")
     mHeadCss = self.mail_head_css_dtml(client=stateChangeInfo.object)
     mBody = self.mail_body_dtml(client=stateChangeInfo.object)
     if mHeadCss:
         mBodyFull = "<html> " + mHeadCss + mBody + " </html>"
     else:
         mBodyFull = "<html> " + mBody + " </html>"
     try:
         if mTO or mCC or mCCN:
             log("mTo: " + str(mTO))
             log("mFROM: " + str(mFROM))
             log("mCC: " + str(mCC))
             log("mCCN: " + str(mCCN))
             log("mHeader: " + str(mHeader))
             log("mBody: " + str(mBody))
             #~ self.MailHost.secureSend(  mBodyFull, mTO,
                                                         #~ mFROM, mHeader,
                                                         #~ mCC, mCCN, "html",charset="utf-8", **options)
             lThread = SenderThread(self.MailHost, mTO, mFROM, mCC, mCCN, mHeader, mBodyFull, options)
             lThread.start()
             log("Sender Thread started succesfully by " + str(lThread))
     except:
         type, val, tb = sys.exc_info()
         traceback.print_exc(file=sys.stdout)
         warn("Mail cannot be sent : \nException type: %s \nException value: %s \nException tb: %s" % (type, val, tb) )
         return self.plone_utils.addPortalMessage( u"the notification mail can't be sent! the server network services are not correctly configured or a firewall is blocking the nameserver lookups \n error: %s " % type)
Пример #9
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
Пример #10
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
Пример #11
0
                # 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.
Пример #12
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
Пример #13
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)
Пример #14
0
                # 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.
Пример #15
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)