Commit e10b7d6e authored by Florent Guillaume's avatar Florent Guillaume

Fixed refactored traversal on bound methods of classes with no default

access.
parent 52073e24
......@@ -237,11 +237,11 @@ class Traversable:
if not validated:
raise Unauthorized, name
else:
if hasattr(aq_base(obj), name):
if getattr(aq_base(obj), name, marker) is not marker:
if restricted:
next = guarded_getattr(obj, name, marker)
next = guarded_getattr(obj, name)
else:
next = _getattr(obj, name, marker)
next = _getattr(obj, name)
else:
try:
next=obj[name]
......@@ -249,6 +249,9 @@ class Traversable:
# Raise NotFound for easier debugging
# instead of AttributeError: __getitem__
raise NotFound, name
if restricted and not securityManager.validate(
obj, obj, _none, next):
raise Unauthorized, name
except (AttributeError, NotFound, KeyError), e:
# Try to look for a view
......@@ -270,13 +273,10 @@ class Traversable:
next = _getattr(obj, name, marker)
except AttributeError:
raise e
if next is marker:
# Nothing found re-raise error
raise e
if restricted and not securityManager.validate(
obj, obj, _none, next):
raise Unauthorized, name
if next is marker:
# Nothing found re-raise error
raise e
obj = next
return obj
......
......@@ -68,6 +68,24 @@ class CruelSecurityPolicy:
return 0
class ProtectedMethodSecurityPolicy:
"""Check security strictly on bound methods.
"""
def validate(self, accessed, container, name, value, *args):
if getattr(aq_base(value), 'im_self', None) is None:
return 1
# Bound method
if name is None:
raise Unauthorized
klass = value.im_self.__class__
roles = getattr(klass, name+'__roles__', object())
if roles is None: # ACCESS_PUBLIC
return 1
raise Unauthorized(name)
class UnitTestUser( Acquisition.Implicit ):
"""
Stubbed out manager for unit testing purposes.
......@@ -103,6 +121,22 @@ class BoboTraversable(SimpleItem):
bb_status = 'screechy'
class Restricted(SimpleItem):
"""Instance we'll check with ProtectedMethodSecurityPolicy
"""
getId__roles__ = None # ACCESS_PUBLIC
def getId(self):
return self.id
private__roles__ = () # ACCESS_PRIVATE
def private(self):
return 'private!'
# not protected
def ohno(self):
return 'ohno!'
class BoboTraversableWithAcquisition(SimpleItem):
"""
A BoboTraversable class which may use acquisition to find objects.
......@@ -210,6 +244,17 @@ class TestTraverse( unittest.TestCase ):
self.failUnlessRaises(
KeyError, self.folder1.unrestrictedTraverse, '/folder1/file2/' )
def testTraverseMethodRestricted(self):
self.root.my = Restricted('my')
my = self.root.my
my.id = 'my'
noSecurityManager()
SecurityManager.setSecurityPolicy(ProtectedMethodSecurityPolicy())
r = my.restrictedTraverse('getId')
self.assertEquals(r(), 'my')
self.assertRaises(Unauthorized, my.restrictedTraverse, 'private')
self.assertRaises(Unauthorized, my.restrictedTraverse, 'ohno')
def testBoboTraverseToWrappedSubObj(self):
# Verify it's possible to use __bobo_traverse__ with the
# Zope security policy.
......
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