############################################################################## # # Copyright (c) 2006 Nexedi SARL and Contributors. All Rights Reserved. # 2015 Wenjie Zheng <wenjie.zheng@tiolive.com> # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contract a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## import transaction from AccessControl import getSecurityManager, ClassSecurityInfo from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.Globals import PersistentMapping from Acquisition import aq_inner, aq_parent from Products.ERP5Type import Globals from Products.ERP5Type.Permissions import ManagePortal from Products.DCWorkflow.Guard import Guard from Products.DCWorkflow.Expression import Expression from Products.ERP5Workflow.Document.Transition import TRIGGER_WORKFLOW_METHOD, TRIGGER_USER_ACTION from zLOG import LOG, INFO, ERROR, WARNING from Products.DCWorkflow.Expression import StateChangeInfo from Products.ERP5Type.id_as_reference import IdAsReferenceMixin class Interaction(IdAsReferenceMixin('_interaction'), XMLObject): """ An ERP5 Interaction. """ meta_type = 'ERP5 Interaction' portal_type = 'Interaction' add_permission = Permissions.AddPortalContent isPortalContent = 1 isRADContent = 1 ### zwj: for security issue managed_permission_list = () managed_role = () erp5_permission_roles = {} # { permission: [role] or (role,) } manager_bypass = 0 method_id = None trigger_type = TRIGGER_WORKFLOW_METHOD script_name = () # Executed before transition after_script_name = () # Executed after transition before_commit_script_name = () #Executed Before Commit Transaction activate_script_name = () # Executed as activity portal_type_filter = () portal_type_group_filter = () once_per_transaction = False temporary_document_disallowed = False var_exprs = None # A mapping. guard = None default_reference = '' # Declarative security security = ClassSecurityInfo() security.declareObjectProtected(Permissions.AccessContentsInformation) # Declarative properties property_sheets = ( PropertySheet.Base, PropertySheet.XMLObject, PropertySheet.CategoryCore, PropertySheet.DublinCore, PropertySheet.Reference, PropertySheet.Interaction, ) def _getObjectByRef(self, ref): for ob in self: if wf.getRef() == ref: return ob return None def getGuardSummary(self): res = None if self.guard is not None: res = self.guard.getSummary() return res def getGuard(self): if self.guard is None: self.generateGuard() return self.guard def getVarExprText(self, id): if not self.var_exprs: return '' else: expr = self.var_exprs.get(id, None) if expr is not None: return expr.text else: return '' def generateGuard(self): if self.trigger_type == TRIGGER_USER_ACTION: if self.guard == None: self.guard = Guard(permissions=self.getPermissionList(), roles=self.getRoleList(), groups=self.getGroupList(), expr=self.getExpression()) if self.guard.roles != self.getRoleList(): self.guard.roles = self.getRoleList() elif self.guard.permissions != self.getPermissionList(): self.guard.permissions = self.getPermissionList() elif self.guard.groups != self.getGroupList(): self.guard.groups = self.getGroupList() elif self.guard.expr != self.getExpression(): self.guard.expr = self.getExpression() def execute(self, ob, form_kw=None): LOG(' Calling interaction %s'%self.getId(), WARNING, ' in Interaction.py')### getRef ### zwj: What will be done this part ### this part shoud be called in Base.py as transition be called. # 1: execute before script; # 2: execute after script; # 3: Queue before commit script; # 4: execute activity script. # Initialize variables former_status = {} econtext = None sci = None # Figure out the old and new states. if form_kw is None: form_kw = {} workflow = self.getParent() assert self.trigger_type == TRIGGER_WORKFLOW_METHOD #status = workflow.getCurrentStatusDict(ob) sci = StateChangeInfo( ob, workflow, former_status, self, None, None, kwargs=form_kw) # Execute before script before_script_list = [] before_script_list.append(self.getBeforeScriptName()) if before_script_list != [] and self.getBeforeScriptName() is not None: for script_name in before_script_list: script = workflow._getOb(script_name) ### _getObjectByRef # Pass lots of info to the script in a single parameter. script.execute(sci) # Update variables. tdef_exprs = self.var_exprs if tdef_exprs is None: tdef_exprs = {} for vdef in workflow.objectValues(portal_type='Variable'): id = vdef.getId() ### getRef if not vdef.for_status: continue expr = None if 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, workflow, former_status, self, None, None, None) econtext = Expression_createExprContext(sci) value = expr(econtext) #status[id] = value # Execute the "after" script. after_script_list = [] after_script_list.append(self.getAfterScriptName()) if after_script_list != [] and self.getAfterScriptName() is not None: for script_name in after_script_list: script = workflow._getOb(script_name) ### getObjectByRef LOG('Accessing afterscript: %s'%script_name, WARNING, 'in Interaction.py') # Pass lots of info to the script in a single parameter. script.execute(sci) # May throw an exception # Queue the "Before Commit" scripts sm = getSecurityManager() before_commit_script_list = [] before_commit_script_list.append(self.getBeforeCommitScriptName()) if before_commit_script_list != [] and self.getBeforeCommitScriptName() is not None: for script_name in before_commit_script_list: transaction.get().addBeforeCommitHook(self._before_commit, (sci, script_name, sm)) # Execute "activity" scripts activity_script_list = [] activity_script_list.append(self.getActivateScriptName()) if activity_script_list != [] and self.getActivateScriptName() is not None: for script_name in activity_script_list: workflow.activate(activity='SQLQueue')\ .activeScript(script_name, ob.getRelativeUrl(), former_status, self.getId()) ### getRef def _before_commit(self, sci, script_name, security_manager): # check the object still exists before calling the script ob = sci.object workflow = self.getParent() while ob.isTempObject(): ob = ob.getParentValue() if aq_base(self.unrestrictedTraverse(ob.getPhysicalPath(), None)) is \ aq_base(ob): current_security_manager = getSecurityManager() try: # Who knows what happened to the authentication context # between here and when the interaction was executed... So we # need to switch to the security manager as it was back then setSecurityManager(security_manager) workflow._getOb(script_name)(sci) ### _getObjectByRef finally: setSecurityManager(current_security_manager) def activeScript(self, script_name, ob_url, former_status): workflow = self.getParent() script = workflow._getOb(script_name) ### _getObjectByRef ob = self.unrestrictedTraverse(ob_url) sci = StateChangeInfo( ob, worfklow, former_status, self, None, None, kwargs=kw) script.execute(sci) def getMethodId(self): if type(self.method_id) is type(''): self.method_id = self.method_id.split() return self.method_id def getVarExprText(self, id): if not self.var_exprs: return '' else: expr = self.var_exprs.get(id, None) if expr is not None: return expr.text else: return '' def getWorkflow(self): return aq_parent(aq_inner(aq_parent(aq_inner(self))))