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
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
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
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
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
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
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)
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
# 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.
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
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)
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)