Commit ae79aa21 authored by Alec Mitchell's avatar Alec Mitchell

Merge fix for #2072 into trunk

parent 26faf842
...@@ -206,8 +206,20 @@ class Traversable: ...@@ -206,8 +206,20 @@ class Traversable:
else: else:
# Can't determine container # Can't determine container
container = _none container = _none
if not securityManager.validate( try:
obj, container, name, next): validated = securityManager.validate(
obj, container, name, next)
except Unauthorized:
# If next is a simple unwrapped property, it's
# parentage is indeterminate, but it may have been
# acquired safely. In this case validate will
# raise an error, and we can explicitly check that
# our value was acquired safely.
validated = 0
if container is _none and \
guarded_getattr(obj, name, marker) is next:
validated = 1
if not validated:
raise Unauthorized, name raise Unauthorized, name
else: else:
if restricted: if restricted:
......
...@@ -22,6 +22,7 @@ import cStringIO ...@@ -22,6 +22,7 @@ import cStringIO
import transaction import transaction
import ZODB, Acquisition, transaction import ZODB, Acquisition, transaction
from AccessControl import SecurityManager, Unauthorized from AccessControl import SecurityManager, Unauthorized
from AccessControl.Permissions import access_contents_information
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import noSecurityManager
from Acquisition import aq_base from Acquisition import aq_base
...@@ -102,6 +103,16 @@ class BoboTraversable(SimpleItem): ...@@ -102,6 +103,16 @@ class BoboTraversable(SimpleItem):
bb_status = 'screechy' bb_status = 'screechy'
class BoboTraversableWithAcquisition(SimpleItem):
"""
A BoboTraversable class which may use acquisition to find objects.
This is similar to how the __bobo_traverse__ added by Five behaves).
"""
def __bobo_traverse__(self, request, name):
return Acquisition.aq_get(self, name)
def makeConnection(): def makeConnection():
import ZODB import ZODB
from ZODB.DemoStorage import DemoStorage from ZODB.DemoStorage import DemoStorage
...@@ -235,6 +246,58 @@ class TestTraverse( unittest.TestCase ): ...@@ -235,6 +246,58 @@ class TestTraverse( unittest.TestCase ):
self.failUnless( self.failUnless(
bb.restrictedTraverse('manufactured') is 42) bb.restrictedTraverse('manufactured') is 42)
def testBoboTraverseToAcquiredObject(self):
# Verify it's possible to use a __bobo_traverse__ which retrieves
# objects by acquisition
noSecurityManager()
SecurityManager.setSecurityPolicy( self.oldPolicy )
bb = BoboTraversableWithAcquisition()
bb = bb.__of__(self.root)
self.assertEqual(
bb.restrictedTraverse('folder1'), bb.folder1)
self.assertEqual(
Acquisition.aq_inner(bb.restrictedTraverse('folder1')),
self.root.folder1)
def testBoboTraverseToAcquiredProtectedObject(self):
# Verify it's possible to use a __bobo_traverse__ which retrieves
# objects by acquisition
noSecurityManager()
SecurityManager.setSecurityPolicy( self.oldPolicy )
folder = self.root.folder1
# restrict the ability to access the retrieved object itself
folder.manage_permission(access_contents_information, [], 0)
bb = BoboTraversableWithAcquisition()
bb = bb.__of__(self.root)
self.failUnlessRaises(Unauthorized,
self.root.folder1.restrictedTraverse, 'folder1')
def testBoboTraverseToAcquiredAttribute(self):
# Verify it's possible to use __bobo_traverse__ to an acquired
# attribute
noSecurityManager()
SecurityManager.setSecurityPolicy( self.oldPolicy )
folder = self.root.folder1
folder.stuff = 'stuff here'
bb = BoboTraversableWithAcquisition()
bb = bb.__of__(folder)
self.assertEqual(
bb.restrictedTraverse('stuff'), 'stuff here')
def testBoboTraverseToAcquiredProtectedAttribute(self):
# Verify that using __bobo_traverse__ to get an acquired but
# protected attribute results in Unauthorized
noSecurityManager()
SecurityManager.setSecurityPolicy( self.oldPolicy )
folder = self.root.folder1
# We protect the the attribute by restricting access to the parent
folder.manage_permission(access_contents_information, [], 0)
folder.stuff = 'stuff here'
bb = BoboTraversableWithAcquisition()
bb = bb.__of__(folder)
self.failUnlessRaises(Unauthorized,
self.root.folder1.restrictedTraverse, 'stuff')
def testAcquiredAttributeDenial(self): def testAcquiredAttributeDenial(self):
# Verify that restrictedTraverse raises the right kind of exception # Verify that restrictedTraverse raises the right kind of exception
# on denial of access to an acquired attribute. If it raises # on denial of access to an acquired attribute. If it raises
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment