[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