[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