Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
 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)
Example #6
0
        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
Example #7
0
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
Example #8
0
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
Example #9
0
 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)
Example #10
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

    # 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)
        if validation_exc :
            # reraise validation failed exception