From d2e2d15d958d246b10f7dd3cdde5e1ffb810b8ea Mon Sep 17 00:00:00 2001 From: Tatuya Kamada <tatuya@nexedi.com> Date: Mon, 5 Jul 2010 07:04:59 +0000 Subject: [PATCH] Fix a issue that BusinessTemplate unexpectedly removes the skins of another skin folder when upgrading. To fix the issue, (un)restrectedTraverse calling are replaced with the new method, (un)restrictedResolveValue. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@36841 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5/Document/BusinessTemplate.py | 77 +++++++++++++++++++++-- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py index 876b9a8faf..ab90069a71 100644 --- a/product/ERP5/Document/BusinessTemplate.py +++ b/product/ERP5/Document/BusinessTemplate.py @@ -32,7 +32,7 @@ from Shared.DC.ZRDB.Connection import Connection as RDBConnection from Products.ERP5Type.DiffUtils import DiffFile from Products.ERP5Type.Globals import Persistent, PersistentMapping from Acquisition import Implicit, aq_base, aq_inner, aq_parent -from AccessControl import ClassSecurityInfo +from AccessControl import ClassSecurityInfo, Unauthorized, getSecurityManager from Products.CMFCore.utils import getToolByName from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter from Products.ERP5Type.Base import WorkflowMethod, _aq_reset @@ -613,6 +613,71 @@ class BaseTemplateItem(Implicit, Persistent): """ return self.__class__.__name__[:-12] + def restrictedResolveValue(self, context=None, relative_url=None, default=None): + """ + Get the value with checking the security. + This method does not acquire the parent. + """ + def restrictedGetOb(container, key, default): + validate = getSecurityManager().validate + obj = container._getOb(key, None) + if obj is not None: + try: + if not validate(container, container, key, obj): + raise Unauthorized('unauthorized access to element %s' % key) + except Unauthorized: + # if user can't access object try to return default passed + if default is not None: + return default + else: + raise + return obj + return self._resolveValue(context, relative_url, default, getOb=restrictedGetOb) + + def unrestrictedResolveValue(self, context=None, relative_url=None, default=None): + """ + Get the value without checking the security. + This method does not acquire the parent. + """ + def unrestrictedGetOb(container, key, default): + return container._getOb(key, None) + return self._resolveValue(context, relative_url, default, getOb=unrestrictedGetOb) + + def _resolveValue(self, context, relative_url, default, getOb=None): + """ + Resolve the value without acquire the parent. + """ + if isinstance(relative_url, basestring): + stack = relative_url.split('/') + else: + stack = list(relative_url) + stack.reverse() + value = None + if stack: + portal = aq_inner(self.getPortalObject()) + # It can be passed with the context, so at first, searching from the context. + if context is None: + container = portal + else: + container = context + key = stack.pop() + value = getOb(container, key, default) + + # resolve the value from top to down + while value is not None and stack: + key = stack.pop() + value = value._getOb(key, default) + else: + # When relative_url is empty, returns the context + return context + + if value is None: + LOG('BusinessTemplate', WARNING, + 'Could not access object %s' % relative_url) + + return value + + class ObjectTemplateItem(BaseTemplateItem): """ This class is used for generic objects and as a subclass. @@ -933,7 +998,7 @@ class ObjectTemplateItem(BaseTemplateItem): container_path = path_list[:-1] object_id = path_list[-1] try: - container = portal.unrestrictedTraverse(container_path) + container = self.unrestrictedResolveValue(portal, container_path) except KeyError: # parent object can be set to nothing, in this case just go on container_url = '/'.join(container_path) @@ -1162,7 +1227,7 @@ class ObjectTemplateItem(BaseTemplateItem): if recursive_path in update_dict: action = update_dict[recursive_path] if action in ('remove', 'save_and_remove'): - document = portal.restrictedTraverse(recursive_path, None) + document = self.restrictedResolveValue(portal, recursive_path, None) if document is None: # It happens if the parent of target path is removed before continue @@ -1212,7 +1277,7 @@ class ObjectTemplateItem(BaseTemplateItem): container_path = relative_url.split('/')[0:-1] object_id = relative_url.split('/')[-1] try: - container = portal.unrestrictedTraverse(container_path) + container = self.unrestrictedResolveValue(portal, container_path) object = container._getOb(object_id) # We force access to the object to be sure # that appropriate exception is thrown # in case object is already backup and/or removed @@ -1270,7 +1335,7 @@ class PathTemplateItem(ObjectTemplateItem): try: container_path = relative_url.split('/')[0:-1] object_id = relative_url.split('/')[-1] - container = portal.unrestrictedTraverse(container_path) + container = self.unrestrictedResolveValue(portal, container_path) if trash and trashbin is not None: self.portal_trash.backupObject(trashbin, container_path, object_id, save=1, @@ -1757,7 +1822,7 @@ class WorkflowTemplateItem(ObjectTemplateItem): container_path = path.split('/')[:-1] object_id = path.split('/')[-1] try: - container = portal.unrestrictedTraverse(container_path) + container = self.unrestrictedResolveValue(portal, container_path) except KeyError: # parent object can be set to nothing, in this case just go on container_url = '/'.join(container_path) -- 2.30.9