[Zope-dev] Checkins not appearing

Florent Guillaume fg at nuxeo.com
Fri Mar 25 08:43:25 EST 2005


I made yesterday some checkins on the Zope-2.7 branch, which didn't 
appear on the zope-checkins list.

FYI they're below. I'm porting them to trunk right now.

Florent

Index: doc/CHANGES.txt
===================================================================
RCS file: /cvs-repository/Zope/doc/Attic/CHANGES.txt,v
retrieving revision 1.625.2.309
diff -u -r1.625.2.309 CHANGES.txt
--- doc/CHANGES.txt     18 Mar 2005 15:31:01 -0000      1.625.2.309
+++ doc/CHANGES.txt     24 Mar 2005 18:32:34 -0000
@@ -11,6 +11,10 @@
        - DateIndex/DateRangeIndexes did not reset their __len__ attribute
          properly when cleared

+      - Fixed brain.getObject() to correctly traverse to an object even
+        if one of its parents is not accessible, to be close to what the
+        Publisher does.
+
    Zope 2.7.5 final (2005/03/20)

      Bugs fixed
Index: lib/python/Products/ZCatalog/CatalogBrains.py
===================================================================
RCS file: /cvs-repository/Products/ZCatalog/Attic/CatalogBrains.py,v
retrieving revision 1.8.44.1
diff -u -r1.8.44.1 CatalogBrains.py
--- lib/python/Products/ZCatalog/CatalogBrains.py       23 Mar 2004 
20:27:23 -0000      1.8.44.1
+++ lib/python/Products/ZCatalog/CatalogBrains.py       24 Mar 2005 
18:32:35 -0000
@@ -42,12 +42,24 @@

      def getObject(self, REQUEST=None):
          """Return the object for this record
-
+
          Will return None if the object cannot be found via its 
cataloged path
          (i.e., it was deleted or moved without recataloging), or if 
the user is
-        not authorized to access an object along the path.
+        not authorized to access the object.
+
+        This method mimicks a subset of what publisher's traversal does,
+        so it allows access if the final object can be accessed even
+        if intermediate objects cannot.
          """
-        return self.aq_parent.restrictedTraverse(self.getPath(), None)
+        path = self.getPath().split('/')
+        if not path:
+            return None
+        parent = self.aq_parent
+        if len(path) > 1:
+            parent = parent.unrestrictedTraverse('/'.join(path[:-1]), None)
+            if parent is None:
+                return None
+        return parent.restrictedTraverse(path[-1], None)

      def getRID(self):
          """Return the record ID for this object."""
Index: lib/python/Products/ZCatalog/tests/testBrains.py
===================================================================
RCS file: /cvs-repository/Products/ZCatalog/tests/Attic/testBrains.py,v
retrieving revision 1.1.4.1
diff -u -r1.1.4.1 testBrains.py
--- lib/python/Products/ZCatalog/tests/testBrains.py    23 Mar 2004 
20:27:23 -0000      1.1.4.1
+++ lib/python/Products/ZCatalog/tests/testBrains.py    24 Mar 2005 
18:32:35 -0000
@@ -23,15 +23,17 @@
      """Happy content"""
      def __init__(self, id):
          self.id = id
+    def check(self):
+        pass

  class Secret(Happy):
      """Object that raises Unauthorized when accessed"""
-    def __of__(self, parent):
+    def check(self):
          raise Unauthorized

  class Conflicter(Happy):
      """Object that raises ConflictError when accessed"""
-    def __of__(self, parent):
+    def check(self):
          raise ConflictError

  class DummyRequest(Acquisition.Implicit):
@@ -50,10 +52,20 @@
               '/conflicter':Conflicter('conflicter')}
      _paths = _objs.keys() + ['/zonked']
      _paths.sort()
-
+
+    # This is sooooo ugly
+
+    def unrestrictedTraverse(self, path, default=None):
+        assert path == '' # for these tests...
+        return self
+
      def restrictedTraverse(self, path, default=_marker):
+        if not path.startswith('/'):
+            path = '/'+path
          try:
-            return self._objs[path].__of__(self)
+            ob = self._objs[path].__of__(self)
+            ob.check()
+            return ob
          except (KeyError, Unauthorized):
              if default is not _marker:
                  return default
Index: lib/python/Products/ZCatalog/tests/testCatalog.py
===================================================================
RCS file: /cvs-repository/Products/ZCatalog/tests/Attic/testCatalog.py,v
retrieving revision 1.22.12.6
diff -u -r1.22.12.6 testCatalog.py
--- lib/python/Products/ZCatalog/tests/testCatalog.py   18 May 2004 
14:48:49 -0000      1.22.12.6
+++ lib/python/Products/ZCatalog/tests/testCatalog.py   24 Mar 2005 
18:32:35 -0000
@@ -26,6 +26,10 @@
  from Products.ZCatalog import ZCatalog,Vocabulary
  from Products.ZCatalog.Catalog import Catalog, CatalogError
  import ExtensionClass
+from OFS.Folder import Folder as OFS_Folder
+from AccessControl.SecurityManagement import setSecurityManager
+from AccessControl.SecurityManagement import noSecurityManager
+from AccessControl import Unauthorized

  from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex
  from Products.PluginIndexes.TextIndex.TextIndex import TextIndex
@@ -60,18 +64,6 @@
  # XXX What's this mean?  What does this comment apply to?
 
################################################################################

-# XXX These imports and class don't appear to be needed?
-## from AccessControl.SecurityManagement import newSecurityManager
-## from AccessControl.SecurityManagement import noSecurityManager
-
-## class DummyUser:
-
-##     def __init__( self, name ):
-##         self._name = name
-
-##     def getUserName( self ):
-##         return self._name
-
  def sort(iterable):
      L = list(iterable)
      L.sort()
@@ -584,7 +576,82 @@
          expected.sort()
          expected = [rid for sortkey, rid, getitem in expected]
          self.assertEqual(merged_rids, expected)
-
+
+
+class PickySecurityManager:
+    def __init__(self, badnames=[]):
+        self.badnames = badnames
+    def validateValue(self, value):
+        return 1
+    def validate(self, accessed, container, name, value):
+        if name not in self.badnames:
+            return 1
+        raise Unauthorized(name)
+
+class Folder(OFS_Folder):
+    def __init__(self, id):
+        self._setId(id)
+        OFS_Folder.__init__(self)
+
+class TestZCatalogGetObject(unittest.TestCase):
+    # Test what objects are returned by brain.getObject()
+
+    def setUp(self):
+        catalog = ZCatalog.ZCatalog('catalog')
+        catalog.addIndex('id', 'FieldIndex')
+        root = Folder('')
+        root.getPhysicalRoot = lambda: root
+        self.root = root
+        self.root.catalog = catalog
+
+    def tearDown(self):
+        noSecurityManager()
+
+    def test_getObject_found(self):
+        # Check normal traversal
+        root = self.root
+        catalog = root.catalog
+        root.ob = Folder('ob')
+        catalog.catalog_object(root.ob)
+        brain = catalog.searchResults()[0]
+        self.assertEqual(brain.getPath(), '/ob')
+        self.assertEqual(brain.getObject().getId(), 'ob')
+
+    def test_getObject_missing(self):
+        # Check that if the object is missing None is returned
+        root = self.root
+        catalog = root.catalog
+        root.ob = Folder('ob')
+        catalog.catalog_object(root.ob)
+        brain = catalog.searchResults()[0]
+        del root.ob
+        self.assertEqual(brain.getObject(), None)
+
+    def test_getObject_restricted(self):
+        # Check that if the object's security does not allow traversal,
+        # None is returned
+        root = self.root
+        catalog = root.catalog
+        root.fold = Folder('fold')
+        root.fold.ob = Folder('ob')
+        catalog.catalog_object(root.fold.ob)
+        brain = catalog.searchResults()[0]
+        # allow all accesses
+        pickySecurityManager = PickySecurityManager()
+        setSecurityManager(pickySecurityManager)
+        self.assertEqual(brain.getObject().getId(), 'ob')
+        # disallow just 'ob' access
+        pickySecurityManager = PickySecurityManager(['ob'])
+        setSecurityManager(pickySecurityManager)
+        self.assertEqual(brain.getObject(), None)
+        # disallow just 'fold' access
+        pickySecurityManager = PickySecurityManager(['fold'])
+        setSecurityManager(pickySecurityManager)
+        ob = brain.getObject()
+        self.failIf(ob is None)
+        self.assertEqual(ob.getId(), 'ob')
+
+
  def test_suite():
      suite = unittest.TestSuite()
      suite.addTest( unittest.makeSuite( TestAddDelColumn ) )
@@ -593,6 +660,7 @@
      suite.addTest( unittest.makeSuite( TestCatalogObject ) )
      suite.addTest( unittest.makeSuite( TestRS ) )
      suite.addTest( unittest.makeSuite( TestMerge ) )
+    suite.addTest( unittest.makeSuite( TestZCatalogGetObject ) )
      return suite

  if __name__ == '__main__':


-- 
Florent Guillaume, Nuxeo (Paris, France)   CTO, Director of R&D
+33 1 40 33 71 59   http://nuxeo.com   fg at nuxeo.com


More information about the Zope-Dev mailing list