[Erp5-report] r17429 - in /erp5/trunk/products/CMFCategory: ./ tests/
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Nov 6 21:54:56 CET 2007
Author: yo
Date: Tue Nov 6 21:54:56 2007
New Revision: 17429
URL: http://svn.erp5.org?rev=17429&view=rev
Log:
Rewrite resolveCategory so that it does not acquire objects mistakenly.
Modified:
erp5/trunk/products/CMFCategory/CategoryTool.py
erp5/trunk/products/CMFCategory/tests/testCMFCategory.py
Modified: erp5/trunk/products/CMFCategory/CategoryTool.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFCategory/CategoryTool.py?rev=17429&r1=17428&r2=17429&view=diff
==============================================================================
--- erp5/trunk/products/CMFCategory/CategoryTool.py (original)
+++ erp5/trunk/products/CMFCategory/CategoryTool.py Tue Nov 6 21:54:56 2007
@@ -34,6 +34,7 @@
from Products.CMFCore.utils import UniqueObject
from Globals import InitializeClass, DTMLFile
from AccessControl import ClassSecurityInfo
+from AccessControl import Unauthorized, getSecurityManager
from Acquisition import aq_base
from Products.ERP5Type import Permissions
from Products.ERP5Type.Base import Base
@@ -45,7 +46,7 @@
import re
-from zLOG import LOG, PROBLEM
+from zLOG import LOG, PROBLEM, WARNING
_marker = object()
@@ -1511,23 +1512,76 @@
except KeyError:
pass
- try:
- obj = self.restrictedTraverse(relative_url)
- if obj is None:
- REQUEST = self.REQUEST
- url = '%s/%s' % ('/'.join(self.getPhysicalPath()), relative_url)
- #LOG("CMFCategory:",0,"Trying url %s" % url )
- obj = self.portal_catalog.resolve_url(url, REQUEST)
- #LOG('Obj type', 0, str(obj.getUid()))
- value = obj
- except (KeyError, AttributeError) :
- LOG("CMFCategory WARNING",0,"Could not access object relative_url %s" % relative_url )
- value = None
+ # This below is complicated, because we want to avoid acquisitions
+ # in most cases, but we still need to restrict the access.
+ # For instance, if the relative url is source/person_module/yo,
+ # only person_module should be acquired. This becomes very critical,
+ # for example, with source/sale_order_module/1/1/1, because
+ # we do not want to acquire a Sale Order when a Line or a Cell is
+ # not present.
+ #
+ # In addition, the behavior of resolveCategory is weird, in that
+ # the relative url might not start with a base category. It can
+ # be without a base category, and this means that the first
+ # part must be acquired. This notation makes things quite
+ # unpredictable. Therefore, we will have to redesign this method
+ # in the future.
+ if isinstance(relative_url, basestring):
+ stack = relative_url.split('/')
+ else:
+ stack = list(relative_url)
+ stack.reverse()
+
+ validate = getSecurityManager().validate
+ key = stack.pop()
+ obj = self._getOb(key, None)
+ if obj is not None:
+ # The first one is a base category.
+ if not validate(self, self, key, obj):
+ raise Unauthorized('unauthorized access to element %s' % key)
+ base_category = obj
+
+ # Next, an object must be retrieved from a base category or
+ # a portal.
+ if stack:
+ key = stack.pop()
+ obj = base_category._getOb(key, None)
+ if obj is None:
+ portal = self.getPortalObject()
+ obj = portal._getOb(key, None)
+ if obj is not None:
+ if not validate(portal, base_category, key, obj):
+ raise Unauthorized('unauthorized access to element %s' % key)
+ obj = obj.__of__(base_category)
+ else:
+ if not validate(base_category, base_category, key, obj):
+ raise Unauthorized('unauthorized access to element %s' % key)
+ else:
+ # The first one is a module.
+ portal = self.getPortalObject()
+ obj = portal._getOb(key, None)
+ if obj is not None:
+ if not validate(portal, portal, key, obj):
+ raise Unauthorized('unauthorized access to element %s' % key)
+
+ if obj is not None:
+ while stack:
+ container = obj
+ key = stack.pop()
+ obj = container._getOb(key, None)
+ if obj is None:
+ break
+ if not validate(container, container, key, obj):
+ raise Unauthorized('unauthorized access to element %s' % key)
+
+ if obj is None:
+ LOG('CMFCategory', WARNING,
+ 'Could not access object %s' % relative_url)
if cache is not None:
- cache[key] = value
-
- return value
+ cache[key] = obj
+
+ return obj
InitializeClass( CategoryTool )
Modified: erp5/trunk/products/CMFCategory/tests/testCMFCategory.py
URL: http://svn.erp5.org/erp5/trunk/products/CMFCategory/tests/testCMFCategory.py?rev=17429&r1=17428&r2=17429&view=diff
==============================================================================
--- erp5/trunk/products/CMFCategory/tests/testCMFCategory.py (original)
+++ erp5/trunk/products/CMFCategory/tests/testCMFCategory.py Tue Nov 6 21:54:56 2007
@@ -1016,7 +1016,7 @@
bc.getCategoryChildTitleItemList(checked_permission=checked_permission,
cache=0))
- def test_renameBaseCategory(self):
+ def test_29_renameBaseCategory(self):
bc = self.portal.portal_categories.newContent(
portal_type='Base Category',
id='first_id')
@@ -1025,6 +1025,36 @@
bc.setId('new_id')
self.assertEquals('new_id', bc.getId())
+ def test_30_resolveCategory(self):
+ portal = self.getPortal()
+ category_tool = portal.portal_categories
+ module = portal.sale_order_module
+ order = module.newContent(id='foo', portal_type='Sale Order')
+ self.assertNotEquals(order, None)
+ line = order.newContent(id='bar', portal_type='Sale Order Line')
+ self.assertNotEquals(line, None)
+ cell = line.newContent(id='baz', portal_type='Sale Order Cell')
+ self.assertNotEquals(cell, None)
+ get_transaction().commit()
+ self.tic()
+
+ for relative_url, value in (
+ ('sale_order_module', module),
+ ('sale_order_module/foo', order),
+ ('sale_order_module/bar', None),
+ ('sale_order_module/sale_order_module', None),
+ ('sale_order_module/foo/bar', line),
+ ('sale_order_module/foo/foo', None),
+ ('sale_order_module/foo/sale_order_module', None),
+ ('sale_order_module/foo/bar/baz', cell),
+ ('sale_order_module/foo/bar/bar', None),
+ ('sale_order_module/foo/bar/foo', None),
+ ('sale_order_module/foo/bar/sale_order_module', None),
+ ):
+ obj = category_tool.resolveCategory(relative_url)
+ self.assertEquals(obj, value)
+ obj = category_tool.resolveCategory('order/' + relative_url)
+ self.assertEquals(obj, value)
def test_suite():
suite = unittest.TestSuite()
More information about the Erp5-report
mailing list