[Zope3-checkins] SVN: Zope3/trunk/src/zope/security/ Make changes
as discussed in http://www.zope.org/Collectors/Zope3-dev/506:
canWrite now does not raise Forbidden if canAccess does not,
effectively.
Gary Poster
gary at zope.com
Mon Dec 19 12:47:36 EST 2005
Log message for revision 40886:
Make changes as discussed in http://www.zope.org/Collectors/Zope3-dev/506: canWrite now does not raise Forbidden if canAccess does not, effectively.
Changed:
U Zope3/trunk/src/zope/security/checker.py
U Zope3/trunk/src/zope/security/tests/test_checker.py
-=-
Modified: Zope3/trunk/src/zope/security/checker.py
===================================================================
--- Zope3/trunk/src/zope/security/checker.py 2005-12-19 13:14:52 UTC (rev 40885)
+++ Zope3/trunk/src/zope/security/checker.py 2005-12-19 17:47:35 UTC (rev 40886)
@@ -97,8 +97,26 @@
checker.check_setattr(obj, name)
except Unauthorized:
return False
- # if it is Forbidden (or anything else), let it be raised: it probably
- # indicates a programming or configuration error
+ except ForbiddenAttribute:
+ # we are going to be a bit DWIM-y here: see
+ # http://www.zope.org/Collectors/Zope3-dev/506
+
+ # generally, if the check is ForbiddenAttribute we want it to be
+ # raised: it probably indicates a programming or configuration error.
+ # However, we special case a write ForbiddenAttribute when one can
+ # actually read the attribute: this represents a reasonable
+ # configuration of a readonly attribute, and returning False (meaning
+ # "no, you can't write it") is arguably more useful than raising the
+ # exception.
+ try:
+ checker.check_getattr(obj, name)
+ # we'll let *this* ForbiddenAttribute fall through, if any. It
+ # means that both read and write are forbidden.
+ except Unauthorized:
+ pass
+ return False
+ # all other exceptions, other than Unauthorized and ForbiddenAttribute,
+ # should be passed through uncaught, as they indicate programmer error
return True
def canAccess(obj, name):
Modified: Zope3/trunk/src/zope/security/tests/test_checker.py
===================================================================
--- Zope3/trunk/src/zope/security/tests/test_checker.py 2005-12-19 13:14:52 UTC (rev 40885)
+++ Zope3/trunk/src/zope/security/tests/test_checker.py 2005-12-19 17:47:35 UTC (rev 40886)
@@ -435,11 +435,12 @@
# write is not merely unauthorized but forbidden--including write access
# for baz.
checker = Checker(
- {'foo':'test_allowed',
+ {'foo':'test_allowed', # these are the read settings
'bar':'test_allowed',
'baz':'you_will_not_have_this_permission'},
- {'foo':'test_allowed',
- 'bar':'you_will_not_have_this_permission'})
+ {'foo':'test_allowed', # these are the write settings
+ 'bar':'you_will_not_have_this_permission',
+ 'bing':'you_will_not_have_this_permission'})
defineChecker(SomeClass, checker)
# so, our hapless interaction may write and access foo...
@@ -453,13 +454,28 @@
# ...and may access baz.
self.assert_(not canAccess(obj, 'baz'))
- # there are no security assertions for writing baz or accessing
- # anything else, so these actually raise Forbidden. The rationale
- # behind exposing the Forbidden exception is primarily that it is
- # usually indicative of programming or configuration errors.
- self.assertRaises(Forbidden, canWrite, obj, 'baz')
+ # there are no security assertions for writing or reading shazam, so
+ # checking these actually raises Forbidden. The rationale behind
+ # exposing the Forbidden exception is primarily that it is usually
+ # indicative of programming or configuration errors.
self.assertRaises(Forbidden, canAccess, obj, 'shazam')
+ self.assertRaises(Forbidden, canWrite, obj, 'shazam')
+ # However, we special-case canWrite when an attribute has a Read
+ # setting but no Write setting. Consider the 'baz' attribute from the
+ # checker above: it is readonly. All users are forbidden to write
+ # it. This is a very reasonable configuration. Therefore, canWrite
+ # will hide the Forbidden exception if and only if there is a
+ # setting for accessing the attribute.
+ self.assert_(not canWrite(obj, 'baz'))
+
+ # The reverse is not true at the moment: an unusal case like the
+ # write-only 'bing' attribute will return a boolean for canWrite,
+ # but canRead will simply raise a Forbidden exception, without checking
+ # write settings.
+ self.assert_(not canWrite(obj, 'bing'))
+ self.assertRaises(Forbidden, canAccess, obj, 'bing')
+
class TestCheckerPublic(TestCase):
def test_that_pickling_CheckerPublic_retains_identity(self):
More information about the Zope3-Checkins
mailing list