Commit 81ed9c70 authored by iv's avatar iv

ERP5Workflow: change guardable mixin to add all guards methods

this fixes error when accessing to special views on Transition objects
it also remove duplication of guard properties (they were stored in the
properties of the guarded object *and* in a guard object)
parent 2c11d18d
...@@ -198,15 +198,8 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject): ...@@ -198,15 +198,8 @@ class Workflow(IdAsReferenceMixin("", "prefix"), XMLObject):
return 0 return 0
return 1 return 1
def _checkTransitionGuard(self, tdef, document, **kw): def _checkTransitionGuard(self, transition, document, **kw):
guard = tdef.getGuard() return transition.checkGuard(getSecurityManager(), self, document, **kw)
if guard is None:
# in new workflow transition, guard shouldn't be none any more, this
# condiction is only kept for debugging.
return 1
if guard.check(getSecurityManager(), self, document, **kw):
return 1
return 0
def _findAutomaticTransition(self, document, sdef): def _findAutomaticTransition(self, document, sdef):
tdef = None tdef = None
......
from Products.DCWorkflow.Guard import Guard from cgi import escape
# XXX(WORKFLOW) ^ should not use DCWorkflow Guard class
from AccessControl.SecurityInfo import ClassSecurityInfo
from Acquisition import Explicit
from Acquisition import aq_base
from App.class_init import InitializeClass
from App.special_dtml import DTMLFile
from Persistence import Persistent
from Products.CMFCore.Expression import Expression from Products.CMFCore.Expression import Expression
from Products.CMFCore.utils import _checkPermission
from Products.DCWorkflow.Expression import StateChangeInfo
from Products.DCWorkflow.Expression import createExprContext
from Products.DCWorkflow.permissions import ManagePortal
from Products.DCWorkflow.utils import _dtmldir
# XXX(WORKFLOW) remove dependencies to DCWorkflow ^
class GuardableMixin(object): class GuardableMixin(object):
'''
code of methods and functions taken from
Products.DCWorkflow-2.2.4 > Guard.py
'''
guard_expression = Expression('')
guard_group = ()
guard_permission = ()
guard_role = ()
security = ClassSecurityInfo()
security.declareObjectProtected(ManagePortal)
def checkGuard(self, security_manager, workflow, current_object, **kw):
"""Checks conditions in this guard.
"""
user_roles = None
if workflow.manager_bypass:
# Possibly bypass.
user_roles = security_manager.getUser().getRolesInContext(current_object)
if 'Manager' in user_roles:
return True
if self.guard_permission:
for permission in self.guard_permission:
if _checkPermission(permission, current_object):
break
else:
return False
if self.guard_role:
# Require at least one of the given roles.
if user_roles is None:
user_roles = security_manager.getUser()\
.getRolesInContext(current_object)
for role in self.guard_role:
if role in user_roles:
break
else:
return False
if self.guard_group:
# Require at least one of the specified groups.
user = security_manager.getUser()
base = aq_base(user)
if hasattr(base, 'getGroupsInContext'):
user_groups = user.getGroupsInContext(current_object)
elif hasattr(base, 'getGroups' ):
user_groups = user.getGroups()
else:
user_groups = ()
for group in self.guard_group:
if group in user_groups:
break
else:
return False
if self.guard_expression is not None:
expression_context = createExprContext(StateChangeInfo(current_object,
workflow,
kwargs=kw))
if not self.guard_expression(expression_context):
return False
return True
security.declareProtected(ManagePortal, 'getSummary')
def getSummary(self):
# Perhaps ought to be in DTML.
summary = []
if self.guard_permission:
summary.append('Requires permission:')
summary.append(formatNameUnion(self.guard_permission))
if self.guard_role:
if summary:
summary.append('<br/>')
summary.append('Requires role:')
summary.append(formatNameUnion(self.guard_role))
if self.guard_group:
if summary:
summary.append('<br/>')
summary.append('Requires group:')
summary.append(formatNameUnion(self.guard_group))
if self.guard_expression is not None:
if summary:
summary.append('<br/>')
summary.append('Requires expr:')
summary.append('<code>' + escape(self.guard_expression.text) + '</code>')
return ' '.join(summary)
def changeFromProperties(self, props):
'''
Returns True if changes were specified.
'''
if props is None:
return False
changed = False
given_property = props.get('guard_permission', None)
if given_property:
changed = True
permission_list = [permission.strip() for permission in
given_property.split(';')]
self.guard_permission = tuple(permission_list)
given_property = props.get('guard_role', None)
if given_property:
changed = True
role_list = [role.strip() for role in given_property.split(';')]
self.guard_role = tuple(role_list)
given_property = props.get('guard_group', None)
if given_property:
changed = True
group_list = [ group.strip() for group in given_property.split(';') ]
self.guard_group = tuple(group_list)
given_property = props.get('guard_expression', None)
if given_property:
changed = True
self.guard_expression = Expression(given_property)
return changed
security.declareProtected(ManagePortal, 'setGuardExpression')
def setGuardExpression(self, text):
self.guard_expression = Expression(text)
def generateGuard(self): def formatNameUnion(names):
if self.guard is None: escaped = ['<code>' + escape(name) + '</code>' for name in names]
self.guard = Guard() if len(escaped) == 2:
if self.getGuardRoleList() is not None: return ' or '.join(escaped)
self.guard.roles = self.getGuardRoleList() elif len(escaped) > 2:
if self.getGuardPermissionList() is not None: escaped[-1] = ' or ' + escaped[-1]
self.guard.permissions = self.getGuardPermissionList() return '; '.join(escaped)
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
...@@ -211,29 +211,30 @@ class TestERP5Workflow(ERP5TypeTestCase): ...@@ -211,29 +211,30 @@ class TestERP5Workflow(ERP5TypeTestCase):
transition = workflow.newContent(portal_type=transition_type) transition = workflow.newContent(portal_type=transition_type)
# roles # roles
transition.setGuardRoleList([]) transition.setGuardRoleList([])
self.assertEqual([], transition.guard.roles) self.assertEqual(transition.guard_role, ())
transition.setGuardRoleList(['Assignor', 'Assignee']) transition.setGuardRoleList(['Assignor', 'Assignee'])
self.assertEqual(['Assignor', 'Assignee'], transition.guard.roles) self.assertEqual(('Assignor', 'Assignee'), transition.guard_role)
# permissions # permissions
transition.setGuardPermissionList([]) transition.setGuardPermissionList([])
self.assertEqual([], transition.guard.permissions) self.assertEqual(transition.guard_permission, ())
transition.setGuardPermissionList(['Modify portal content']) transition.setGuardPermissionList(['Modify portal content'])
self.assertEqual(['Modify portal content'], transition.guard.permissions) self.assertEqual(('Modify portal content',), transition.guard_permission)
# groups # groups
transition.setGuardGroupList([]) transition.setGuardGroupList([])
self.assertEqual([], transition.guard.groups) self.assertEqual(transition.guard_group, ())
transition.setGuardGroupList(['Group1', 'Group2']) transition.setGuardGroupList(['Group1', 'Group2'])
self.assertEqual(['Group1', 'Group2'], transition.guard.groups) self.assertEqual(transition.guard_group, ('Group1', 'Group2'))
# expression # expression
transition.setGuardExpression('')
self.assertEqual(None, transition.guard.expr)
transition.setGuardExpression('python: "Hello, world"') transition.setGuardExpression('python: "Hello, world"')
self.assertEqual(transition.guard.expr.text, 'python: "Hello, world"') self.assertEqual(transition.guard_expression.text, 'python: "Hello, world"')
def test_InteractionGuards(self): def test_InteractionGuards(self):
self.test_TransitionGuards(transition_type='Interaction') self.test_TransitionGuards(transition_type='Interaction')
def test_Base_viewDict(self): def test_Base_viewDict(self):
"""
verify that Base_viewDict view can be accessed
"""
workflow = self.workflow_module.newContent(portal_type='Workflow') workflow = self.workflow_module.newContent(portal_type='Workflow')
state = workflow.newContent(portal_type='State', title='Some State') state = workflow.newContent(portal_type='State', title='Some State')
transition = workflow.newContent(portal_type='Transition', transition = workflow.newContent(portal_type='Transition',
...@@ -243,8 +244,6 @@ class TestERP5Workflow(ERP5TypeTestCase): ...@@ -243,8 +244,6 @@ class TestERP5Workflow(ERP5TypeTestCase):
transition.setCategoryList('destination/' + transition.getPath()) transition.setCategoryList('destination/' + transition.getPath())
http_response = self.publish(transition.getPath() + '/Base_viewDict', http_response = self.publish(transition.getPath() + '/Base_viewDict',
basic='ERP5TypeTestCase:',) basic='ERP5TypeTestCase:',)
self.logMessage('path: ' + transition.getPath() + '/Base_viewDict')
self.logMessage(str(http_response.status) + '\n')
self.assertEqual(http_response.status, 200) self.assertEqual(http_response.status, 200)
......
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