diff --git a/product/ERP5Type/dtml/editGuardForm.dtml b/product/ERP5Type/dtml/editGuardForm.dtml new file mode 100644 index 0000000000000000000000000000000000000000..5318e4789b2bf89df37826269844ad49def818e2 --- /dev/null +++ b/product/ERP5Type/dtml/editGuardForm.dtml @@ -0,0 +1,28 @@ +<dtml-var manage_page_header> +<dtml-var manage_tabs> + +<form action="manage_setGuard" method="POST"> +<table> + +<tr> +<th align="left" valign="top">Guard</th> +<td> +<dtml-with getGuard> +<table> +<tr> +<th align="left">Permission(s)</th> +<td><input type="text" name="guard_permissions" value="&dtml-getPermissionsText;" /></td> +<th align="left">Role(s)</th> +<td><input type="text" name="guard_roles" value="&dtml-getRolesText;" /></td> +<th align="left">Group(s)</th> +<td><input type="text" name="guard_groups" value="&dtml-getGroupsText;" /></td> +</tr> +</table> +</dtml-with> +</td> +</tr> + +</table> +<input type="submit" name="submit" value="Save changes" /> +</form> +<dtml-var manage_page_footer> diff --git a/product/ERP5Type/patches/PythonScript.py b/product/ERP5Type/patches/PythonScript.py index 75588a1d0192566561b4b08dfc1180629a0c7433..45fd969211f4a0353c23b2982baf211d1aa44ce3 100644 --- a/product/ERP5Type/patches/PythonScript.py +++ b/product/ERP5Type/patches/PythonScript.py @@ -10,11 +10,16 @@ # FOR A PARTICULAR PURPOSE # ############################################################################## +from Products.CMFCore.utils import _checkPermission +from Products.DCWorkflow.Guard import Guard from Products.PythonScripts.PythonScript import PythonScript from App.special_dtml import DTMLFile from Products.ERP5Type import _dtmldir +from AccessControl import ModuleSecurityInfo, getSecurityManager from OFS.misc_ import p_ from App.ImageFile import ImageFile +from Acquisition import aq_base, aq_parent +from zExceptions import Forbidden def haveProxyRole(self): """if a script has proxy role, return True""" @@ -50,3 +55,95 @@ PythonScript.manage = manage_editForm PythonScript.manage_main = manage_editForm PythonScript.manage_editDocument = manage_editForm PythonScript.manage_editForm = manage_editForm + +security = ModuleSecurityInfo('Products.PythonScripts.PythonScript.PythonScript') + +PythonScript.manage_options += ( + { + 'label':'Guard', + 'action':'manage_guardForm', + }, +) +PythonScript._guard_form = DTMLFile( + 'editGuardForm', _dtmldir) + +def manage_guardForm(self, REQUEST, manage_tabs_message=None): + ''' + ''' + return self._guard_form(REQUEST, + management_view='Guard', + manage_tabs_message=manage_tabs_message, + ) +PythonScript.manage_guardForm = manage_guardForm +security.declareProtected('View management screens', 'manage_guardForm') + +def manage_setGuard(self, props=None, REQUEST=None): + ''' + ''' + g = Guard() + if g.changeFromProperties(props or REQUEST): + self.guard = g + else: + self.guard = None + if REQUEST is not None: + return self.manage_guardForm(REQUEST, 'Properties changed.') +PythonScript.manage_setGuard = manage_setGuard +security.declareProtected('Change Python Scripts', 'manage_setGuard') + +def getGuard(self): + guard = getattr(self, 'guard', None) + if guard is not None: + return guard + else: + return Guard().__of__(self) # Create a temporary guard. +PythonScript.getGuard = getGuard + +def checkGuard(guard, ob): + # returns 1 if guard passes against ob, else 0. + # TODO : implement TALES evaluation by defining an appropriate + # context. + u = None + if guard.permissions: + for p in guard.permissions: + if _checkPermission(p, ob): + break + else: + return 0 + if guard.roles: + if u is None: + u = getSecurityManager().getUser() + # Require at least one of the given roles. + u_roles = u.getRolesInContext(ob) + for role in guard.roles: + if role in u_roles: + break + else: + return 0 + if guard.groups: + # Require at least one of the specified groups. + if u is None: + u = getSecurityManager().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 guard.groups: + if group in u_groups: + break + else: + return 0 + return 1 + +PythonScript_exec = PythonScript._exec +def _exec(self, *args): + # PATCH BEGIN : check guard against context, if guard exists. + guard = getattr(self, 'guard', None) + if guard is not None: + if not checkGuard(guard, aq_parent(self)): + raise Forbidden, 'Calling %s %s is denied by Guard.' % (self.meta_type, self.id) + # PATCH END + return PythonScript_exec(self, *args) +PythonScript._exec = _exec