Commit 2049c8a5 authored by iv's avatar iv

ERP5Workflow: add GuardableMixin class + tests on Worklist

parent b2222b06
...@@ -132,6 +132,7 @@ class TestWorklist(testWorkflowMixin): ...@@ -132,6 +132,7 @@ class TestWorklist(testWorkflowMixin):
if worklist_value is None: if worklist_value is None:
worklist_value = workflow_value.newContent(portal_type='Worklist') worklist_value = workflow_value.newContent(portal_type='Worklist')
guard_roles = [] if not guard_roles else [role.strip() for role in guard_roles.split(';')] guard_roles = [] if not guard_roles else [role.strip() for role in guard_roles.split(';')]
# XXX(WORKFLOW), it would be much nicer to use categories instead of ids like 'state_draft', # XXX(WORKFLOW), it would be much nicer to use categories instead of ids like 'state_draft',
# this way we would be consistent with what is used in transitions # this way we would be consistent with what is used in transitions
validation_state = None if not validation_state else 'state_' + validation_state validation_state = None if not validation_state else 'state_' + validation_state
...@@ -164,8 +165,9 @@ class TestWorklist(testWorkflowMixin): ...@@ -164,8 +165,9 @@ class TestWorklist(testWorkflowMixin):
worklists.addWorklist(worklist_id) worklists.addWorklist(worklist_id)
worklist_value = worklists._getOb(worklist_id) worklist_value = worklists._getOb(worklist_id)
worklist_value.setProperties('', actbox_name=action_name, actbox_url=action, worklist_value.setProperties('', actbox_name=action_name, actbox_url=action,
props={k if k.startswith('guard_') else 'var_match_' + k: v props={k if k.startswith('guard_')
for k, v in kw.iteritems()}) else 'var_match_' + k: v
for k, v in kw.iteritems()})
def removeWorklist(self, workflow_id, worklist_id_list): def removeWorklist(self, workflow_id, worklist_id_list):
# add new workflow compatibility # add new workflow compatibility
...@@ -481,6 +483,33 @@ class TestWorklist(testWorkflowMixin): ...@@ -481,6 +483,33 @@ class TestWorklist(testWorkflowMixin):
self.removeWorklist('validation_workflow', ['region_worklist']) self.removeWorklist('validation_workflow', ['region_worklist'])
self.commit() self.commit()
def test_05_guard_setters(self):
worklist_id = 'guarded_worklist'
workflow_id = 'validation_workflow'
workflow_value = self.getWorkflowTool()[workflow_id]
self.createWorklist(workflow_id, worklist_id,
action_name='guarded_test')
worklist_value = getattr(workflow_value, 'worklist_%s' % worklist_id)
# roles
worklist_value.setGuardRoleList([])
self.assertEqual([], worklist_value.guard.roles)
worklist_value.setGuardRoleList(['Assignor', 'Assignee'])
self.assertEqual(['Assignor', 'Assignee'], worklist_value.guard.roles)
# permissions
worklist_value.setGuardPermissionList([])
self.assertEqual([], worklist_value.guard.permissions)
worklist_value.setGuardPermissionList(['Modify portal content'])
self.assertEqual(['Modify portal content'], worklist_value.guard.permissions)
# groups
worklist_value.setGuardGroupList([])
self.assertEqual([], worklist_value.guard.groups)
worklist_value.setGuardGroupList(['Group1', 'Group2'])
self.assertEqual(['Group1', 'Group2'], worklist_value.guard.groups)
# expression
worklist_value.setGuardExpression('')
self.assertEqual('', worklist_value.guard.expr)
worklist_value.setGuardExpression('python: "Hello, world"')
self.assertEqual(worklist_value.guard.expr, 'python: "Hello, world"')
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
......
...@@ -30,8 +30,6 @@ import transaction ...@@ -30,8 +30,6 @@ import transaction
from AccessControl import getSecurityManager, ClassSecurityInfo from AccessControl import getSecurityManager, ClassSecurityInfo
from Acquisition import aq_inner, aq_parent from Acquisition import aq_inner, aq_parent
from Products.CMFCore.Expression import Expression
from Products.DCWorkflow.Guard import Guard
from Products.ERP5Type import Globals, Permissions, PropertySheet from Products.ERP5Type import Globals, Permissions, PropertySheet
from Products.ERP5Type.Globals import PersistentMapping from Products.ERP5Type.Globals import PersistentMapping
from Products.ERP5Type.id_as_reference import IdAsReferenceMixin from Products.ERP5Type.id_as_reference import IdAsReferenceMixin
...@@ -39,9 +37,11 @@ from Products.ERP5Type.Permissions import ManagePortal ...@@ -39,9 +37,11 @@ from Products.ERP5Type.Permissions import ManagePortal
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Workflow.Document.Transition import TRIGGER_WORKFLOW_METHOD,\ from Products.ERP5Workflow.Document.Transition import TRIGGER_WORKFLOW_METHOD,\
TRIGGER_USER_ACTION TRIGGER_USER_ACTION
from Products.ERP5Workflow.mixin.guardable import GuardableMixin
from zLOG import LOG, INFO, ERROR, WARNING from zLOG import LOG, INFO, ERROR, WARNING
class Interaction(IdAsReferenceMixin('interaction_', "prefix"), XMLObject): class Interaction(IdAsReferenceMixin('interaction_', "prefix"), XMLObject,
GuardableMixin):
""" """
An ERP5 Interaction. An ERP5 Interaction.
...@@ -80,33 +80,4 @@ class Interaction(IdAsReferenceMixin('interaction_', "prefix"), XMLObject): ...@@ -80,33 +80,4 @@ class Interaction(IdAsReferenceMixin('interaction_', "prefix"), XMLObject):
PropertySheet.Reference, PropertySheet.Reference,
PropertySheet.Interaction, PropertySheet.Interaction,
PropertySheet.Guard, PropertySheet.Guard,
) )
\ No newline at end of file
def getGuardSummary(self):
res = None
if self.getGuard() is not None:
res = self.guard.getSummary()
return res
def getGuard(self):
# XXX(WORKFLOW): same code in Worklist, please unify
if self.getGuardRoleList() is None and\
self.getGuardPermissionList() is None and\
self.getGuardGroupList() is None and\
self.getGuardExpression() is None and\
self.guard is None:
return Guard().__of__(self)
elif self.guard is None:
self.generateGuard()
return self.guard
def generateGuard(self):
self.guard = Guard()
if self.getGuardRoleList() is not None:
self.guard.roles = self.getGuardRoleList()
if self.getGuardPermissionList() is not None:
self.guard.permissions = self.getGuardPermissionList()
if self.getGuardGroupList() is not None:
self.guard.groups = self.getGuardGroupList()
if self.getGuardExpression() is not None:
self.guard.expr = Expression(self.getGuardExpression())
...@@ -31,10 +31,8 @@ import sys ...@@ -31,10 +31,8 @@ import sys
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Acquisition import aq_base from Acquisition import aq_base
from copy import deepcopy from copy import deepcopy
from Products.CMFCore.Expression import Expression
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
from Products.DCWorkflow.DCWorkflow import ObjectDeleted, ObjectMoved from Products.DCWorkflow.DCWorkflow import ObjectDeleted, ObjectMoved
from Products.DCWorkflow.Guard import Guard
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Accessor.Base import _evaluateTales from Products.ERP5Type.Accessor.Base import _evaluateTales
from Products.ERP5Type.Globals import PersistentMapping from Products.ERP5Type.Globals import PersistentMapping
...@@ -43,13 +41,15 @@ from Products.ERP5Type.patches.DCWorkflow import ValidationFailed ...@@ -43,13 +41,15 @@ from Products.ERP5Type.patches.DCWorkflow import ValidationFailed
from Products.ERP5Type.patches.WorkflowTool import WorkflowHistoryList from Products.ERP5Type.patches.WorkflowTool import WorkflowHistoryList
from Products.ERP5Type.Utils import convertToUpperCase, convertToMixedCase from Products.ERP5Type.Utils import convertToUpperCase, convertToMixedCase
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Workflow.mixin.guardable import GuardableMixin
from zLOG import LOG, ERROR, DEBUG, WARNING from zLOG import LOG, ERROR, DEBUG, WARNING
TRIGGER_AUTOMATIC = 0 TRIGGER_AUTOMATIC = 0
TRIGGER_USER_ACTION = 1 TRIGGER_USER_ACTION = 1
TRIGGER_WORKFLOW_METHOD = 2 TRIGGER_WORKFLOW_METHOD = 2
class Transition(IdAsReferenceMixin("transition_", "prefix"), XMLObject): class Transition(IdAsReferenceMixin("transition_", "prefix"), XMLObject,
GuardableMixin):
""" """
A ERP5 Transition. A ERP5 Transition.
""" """
...@@ -77,31 +77,4 @@ class Transition(IdAsReferenceMixin("transition_", "prefix"), XMLObject): ...@@ -77,31 +77,4 @@ class Transition(IdAsReferenceMixin("transition_", "prefix"), XMLObject):
PropertySheet.Transition, PropertySheet.Transition,
PropertySheet.Guard, PropertySheet.Guard,
PropertySheet.ActionInformation, PropertySheet.ActionInformation,
) )
\ No newline at end of file
def getGuardSummary(self):
res = None
if self.getGuard() is not None:
res = self.guard.getSummary()
return res
def getGuard(self):
self.generateGuard()
if not self.guard.roles or self.guard.roles == []:
reasonable_roles = self.getParent().getManagedRoleList()
# Make sure we do not give rights to anonymous users when no guard is defined
#reasonable_roles.remove('Anonymous')
self.guard.roles = reasonable_roles
return self.guard
def generateGuard(self):
if self.guard is None:
self.guard = Guard()
if self.getGuardRoleList() is not None:
self.guard.roles = self.getGuardRoleList()
if self.getGuardPermissionList() is not None:
self.guard.permissions = self.getGuardPermissionList()
if self.getGuardGroupList() is not None:
self.guard.groups = self.getGuardGroupList()
if self.getGuardExpression() is not None:
self.guard.expr = Expression(self.getGuardExpression())
...@@ -32,16 +32,16 @@ import re ...@@ -32,16 +32,16 @@ import re
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Persistence import PersistentMapping from Persistence import PersistentMapping
from Products.CMFCore.Expression import Expression from Products.CMFCore.Expression import Expression
from Products.DCWorkflow.Guard import Guard
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.id_as_reference import IdAsReferenceMixin from Products.ERP5Type.id_as_reference import IdAsReferenceMixin
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Workflow.mixin.guardable import GuardableMixin
from zLOG import LOG, WARNING from zLOG import LOG, WARNING
tales_re = re.compile(r'(\w+:)?(.*)') tales_re = re.compile(r'(\w+:)?(.*)')
class Worklist(IdAsReferenceMixin("worklist_", "prefix"), XMLObject): class Worklist(IdAsReferenceMixin("worklist_", "prefix"), XMLObject,
GuardableMixin):
""" """
A ERP5 Worklist. A ERP5 Worklist.
Four Variable: portal_type; simulation_state; validation_state; causality_state Four Variable: portal_type; simulation_state; validation_state; causality_state
...@@ -75,35 +75,6 @@ class Worklist(IdAsReferenceMixin("worklist_", "prefix"), XMLObject): ...@@ -75,35 +75,6 @@ class Worklist(IdAsReferenceMixin("worklist_", "prefix"), XMLObject):
PropertySheet.ActionInformation, PropertySheet.ActionInformation,
) )
def getGuardSummary(self):
res = None
if self.getGuard() is not None:
res = self.guard.getSummary()
return res
def getGuard(self):
# XXX(WORKFLOW), I would remove the complete first if below
if self.getGuardRoleList() is None and\
self.getGuardPermissionList() is None and\
self.getGuardGroupList() is None and\
self.getGuardExpression() is None and\
self.guard is None:
return Guard().__of__(self)
elif self.guard is None:
self.generateGuard()
return self.guard
def generateGuard(self):
self.guard = Guard()
if self.getGuardRoleList() is not None:
self.guard.roles = self.getGuardRoleList()
if self.getGuardPermissionList() is not None:
self.guard.permissions = self.getGuardPermissionList()
if self.getGuardGroupList() is not None:
self.guard.groups = self.getGuardGroupList()
if self.getGuardExpression() is not None:
self.guard.expr = Expression(self.getGuardExpression())
def getAvailableCatalogVars(self): def getAvailableCatalogVars(self):
res = [] res = []
res.append(self.getParentValue().getStateVariable()) res.append(self.getParentValue().getStateVariable())
......
from Products.DCWorkflow.Guard import Guard
from Products.CMFCore.Expression import Expression
class GuardableMixin(object):
def generateGuard(self):
if self.guard is None:
self.guard = Guard()
if self.getGuardRoleList() is not None:
self.guard.roles = self.getGuardRoleList()
if self.getGuardPermissionList() is not None:
self.guard.permissions = self.getGuardPermissionList()
if self.getGuardGroupList() is not None:
self.guard.groups = self.getGuardGroupList()
if self.getGuardExpression() is not None:
self.guard.expr = Expression(self.getGuardExpression())
def getGuard(self):
if self.guard is None:
self.generateGuard()
return self.guard
def getGuardSummary(self):
res = None
if self.getGuard() is not None:
res = self.guard.getSummary()
return res
def _setGuardRoleList(self, value, **kw):
self._baseSetGuardRoleList(value, **kw)
self.generateGuard()
def _setGuardPermissionList(self, value, **kw):
self._baseSetGuardPermissionList(value, **kw)
self.generateGuard()
def _setGuardGroupList(self, value, **kw):
self._baseSetGuardGroupList(value, **kw)
self.generateGuard()
def _setGuardExpression(self, value, **kw):
self._baseSetGuardExpression(value, **kw)
self.generateGuard()
# from transition
# def getGuard(self):
# self.generateGuard()
# if not self.guard.roles or self.guard.roles == []:
# reasonable_roles = self.getParent().getManagedRoleList()
# # Make sure we do not give rights to anonymous users when no guard is defined
# #reasonable_roles.remove('Anonymous')
# self.guard.roles = reasonable_roles
# return self.guard
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment