def Guard_checkWithoutRoles(self, sm, wf_def, ob, **kw): """Checks conditions in this guard. This function is the same as Guard.check, but roles are not taken into account here (but taken into account as local roles). This version is for worklist guards. Note that this patched version is not a monkey patch on the class, because we only want this specific behaviour for worklists (Guards are also used in transitions). """ 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.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 DCWorkflowDefinition_executeTransition(self, ob, tdef=None, kwargs=None): ''' Private method. Puts object in a new state. ''' sci = None econtext = None moved_exc = None validation_exc = None # Figure out the old and new states. old_state = self._getWorkflowStateOf(ob, True) if tdef is None: new_state = self.initial_state if not new_state: # Do nothing if there is no initial state. We may want to create # workflows with no state at all, only for worklists. return former_status = {} else: new_state = tdef.new_state_id or old_state former_status = self._getStatusOf(ob) old_sdef = self.states[old_state] try: new_sdef = self.states[new_state] except KeyError: raise WorkflowException('Destination state undefined: ' + new_state) # Execute the "before" script. before_script_success = 1 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: #LOG('_executeTransition', 0, "script = %s, sci = %s" % (repr(script), repr(sci))) script(sci) # May throw an exception. except ValidationFailed, validation_exc: before_script_success = 0 before_script_error_message = deepcopy(validation_exc.msg) validation_exc_traceback = sys.exc_traceback except ObjectMoved, moved_exc: ob = moved_exc.getNewObject()
def _executeMetaTransition(self, ob, new_state_id): """ Allow jumping from state to another without triggering any hooks. Must be used only under certain conditions. """ sci = None econtext = None tdef = None kwargs = None # Figure out the old and new states. old_sdef = self._getWorkflowStateOf(ob) if old_sdef is None: old_state = self._getWorkflowStateOf(ob, id_only=True) else: old_state = old_sdef.getId() if old_state == new_state_id: # Object is already in expected state return former_status = self._getStatusOf(ob) new_sdef = self.states.get(new_state_id, None) if new_sdef is None: raise WorkflowException, ('Destination state undefined: ' + new_state_id) # Update variables. state_values = new_sdef.var_values if state_values is None: state_values = {} tdef_exprs = {} status = {} for id, vdef in self.variables.items(): if not vdef.for_status: continue expr = None if state_values.has_key(id): value = state_values[id] elif 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, old_sdef, new_sdef, kwargs) econtext = createExprContext(sci) value = expr(econtext) status[id] = value status['comment'] = 'Jump from %r to %r' % ( old_state, new_state_id, ) status[self.state_var] = new_state_id tool = aq_parent(aq_inner(self)) tool.setStatusOf(self.id, ob, status) # Update role to permission assignments. self.updateRoleMappingsFor(ob) return new_sdef
def DCWorkflowDefinition_getWorklistVariableMatchDict(self, info, check_guard=True): """ Return a dict which has an entry per worklist definition (worklist id as key) and which value is a dict composed of variable matches. """ if not self.worklists: return None portal = self.getPortalObject() def getPortalTypeListForWorkflow(workflow_id): workflow_tool = portal.portal_workflow result = [] append = result.append for type_info in workflow_tool._listTypeInfo(): portal_type = type_info.id if workflow_id in workflow_tool.getChainFor(portal_type): append(portal_type) return result _getPortalTypeListForWorkflow = CachingMethod( getPortalTypeListForWorkflow, id='_getPortalTypeListForWorkflow', cache_factory='erp5_ui_long') portal_type_list = _getPortalTypeListForWorkflow(self.id) if not portal_type_list: return None variable_match_dict = {} security_manager = getSecurityManager() workflow_id = self.id workflow_title = self.title for worklist_id, worklist_definition in self.worklists.items(): action_box_name = worklist_definition.actbox_name guard = worklist_definition.guard if action_box_name: variable_match = {} for key in worklist_definition.getVarMatchKeys(): var = worklist_definition.getVarMatch(key) if isinstance(var, Expression): evaluated_value = var( createExprContext( StateChangeInfo(portal, self, kwargs=info.__dict__.copy()))) if isinstance(evaluated_value, (str, int, long)): evaluated_value = [str(evaluated_value)] else: evaluated_value = [x % info for x in var] variable_match[key] = evaluated_value if 'portal_type' in variable_match and len( variable_match['portal_type']): portal_type_intersection = set(variable_match['portal_type'])\ .intersection(portal_type_list) # in case the current workflow is not associated with portal_types # defined on the worklist, don't display the worklist for this # portal_type. variable_match['portal_type'] = list(portal_type_intersection) variable_match.setdefault('portal_type', portal_type_list) if len(variable_match.get('portal_type', [])) == 0: continue is_permitted_worklist = 0 if guard is None: is_permitted_worklist = 1 elif (not check_guard) or \ Guard_checkWithoutRoles(guard, security_manager, self, portal): is_permitted_worklist = 1 variable_match[SECURITY_PARAMETER_ID] = guard.roles if is_permitted_worklist: format_data = TemplateDict() format_data._push(info) variable_match.setdefault(SECURITY_PARAMETER_ID, ()) format_data._push(dict((k, ('&%s:list=' % k).join(v)) for\ k, v in variable_match.iteritems())) variable_match[WORKLIST_METADATA_KEY] = { 'format_data': format_data, 'worklist_title': action_box_name, 'worklist_id': worklist_id, 'workflow_title': workflow_title, 'workflow_id': workflow_id, 'action_box_url': worklist_definition.actbox_url, 'action_box_category': worklist_definition.actbox_category } variable_match_dict[worklist_id] = variable_match if len(variable_match_dict) == 0: return None return variable_match_dict
def _listGlobalActions(user=None, id=None, portal_path=None): portal = self._getPortalRoot() portal_url = portal.portal_url portal_url = portal_url() sm = getSecurityManager() res = [] fmt_data = None # We want to display some actions depending on the current date # So, we can now put this kind of expression : <= "%(now)s" # May be this patch should be moved to listFilteredActions in the future info.now = DateTime() for id, qdef in self.worklists.items(): if qdef.actbox_name: guard = qdef.guard # Patch for ERP5 by JP Smets in order # to take into account the expression of the guard # and nothing else - ERP5Workflow definitely needed some day if guard is None or Guard_checkWithoutRoles( guard, sm, self, portal): dict = {} # Patch for ERP5 by JP Smets in order # to implement worklists and search of local roles searchres_len = 0 var_match_keys = qdef.getVarMatchKeys() if var_match_keys: # Check the catalog for items in the worklist. catalog = portal.portal_catalog for k in var_match_keys: v = qdef.getVarMatch(k) if isinstance(v, Expression): v_fmt = v( createExprContext( StateChangeInfo( portal, self, kwargs=info.__dict__.copy()))) else: v_fmt = map(lambda x, info=info: x % info, v) dict[k] = v_fmt # Patch to automatically filter workflists per portal type # so that the same state can be used for different # worklists and they are not merged if not dict.has_key('portal_type'): dict['portal_type'] = portal_type_list # Patch for ERP5 by JP Smets in order # to implement worklists and search of local roles # we do not take into account the guard here if guard is not None and guard.roles: dict['local_roles'] = guard.roles # Patch to use ZSQLCatalog and get high speed # LOG("PatchedDCWorkflowDefinition", 0, dict) searchres_len = int( apply(catalog.countResults, (), dict)[0][0]) if searchres_len == 0: continue if fmt_data is None: fmt_data = TemplateDict() fmt_data._push(info) fmt_data._push({'count': searchres_len}) # Patch for ERP5 by JP Smets in order to # filter per portal type more easily (ie. without # hardcoding it all) fmt_data._push({ 'portal_type': '&portal_type='.join(dict['portal_type']) }) # Patch for ERP5 by JP Smets in order # to implement worklists and search of local roles if dict.has_key('local_roles'): fmt_data._push({ 'local_roles': '&local_roles='.join(dict['local_roles']) }) else: fmt_data._push({'local_roles': ''}) res.append(( id, { 'name': qdef.actbox_name % fmt_data, 'url': '%s/%s' % (portal_url, qdef.actbox_url % fmt_data), 'worklist_id': id, 'workflow_title': self.title, 'workflow_id': self.id, 'permissions': (), # Predetermined. 'category': qdef.actbox_category })) fmt_data._pop() res.sort() return map((lambda (id, val): val), res)
elif 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, old_sdef, new_sdef, kwargs) econtext = createExprContext(sci) value = expr(econtext) status[id] = value # Do not proceed in case of failure of before script if not before_script_success: status[self.state_var] = old_state # Remain in state tool = aq_parent(aq_inner(self)) tool.setStatusOf(self.id, ob, status) sci = StateChangeInfo(ob, self, status, tdef, old_sdef, new_sdef, kwargs) # put the error message in the workflow history sci.setWorkflowVariable(error_message=before_script_error_message) if validation_exc: # reraise validation failed exception
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 # Do not proceed in case of failure of before script if not before_script_success: status[self.state_var] = old_state # Remain in state tool = aq_parent(aq_inner(self)) tool.setStatusOf(self.id, ob, status) sci = StateChangeInfo( ob, self, status, tdef, old_sdef, new_sdef, kwargs) # put the error message in the workflow history sci.setWorkflowVariable(ob, workflow_id=self.id, error_message = before_script_error_message)
elif 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, old_sdef, new_sdef, kwargs) econtext = createExprContext(sci) value = expr(econtext) status[id] = value # Do not proceed in case of failure of before script if not before_script_success: status[self.state_var] = old_state # Remain in state tool = aq_parent(aq_inner(self)) tool.setStatusOf(self.id, ob, status) sci = StateChangeInfo(ob, self, status, tdef, old_sdef, new_sdef, kwargs) # put the error message in the workflow history sci.setWorkflowVariable(error_message=before_script_error_message) if validation_exc: # reraise validation failed exception raise validation_exc, None, validation_exc_traceback