[Zope3-checkins] CVS: Zope3/src/zope/security - checker.py:1.25
Steve Alexander
steve@cat-box.net
Thu, 29 May 2003 11:51:50 -0400
Update of /cvs-repository/Zope3/src/zope/security
In directory cvs.zope.org:/tmp/cvs-serv6524/src/zope/security
Modified Files:
checker.py
Log Message:
Added a DecoratedChecker.
=== Zope3/src/zope/security/checker.py 1.24 => 1.25 ===
--- Zope3/src/zope/security/checker.py:1.24 Wed May 28 08:55:28 2003
+++ Zope3/src/zope/security/checker.py Thu May 29 11:51:19 2003
@@ -170,6 +170,111 @@
return Proxy(value, checker)
+
+class DecoratedChecker(TrustedCheckerBase):
+ """A checker using further permissions relative to an original checker.
+ """
+
+ implements(IChecker)
+
+ def __init__(self, original_checker, permission_func,
+ setattr_permission_func=lambda name: None
+ ):
+ """Create a checker
+
+ A dictionary or a callable must be provided for computing permissions
+ for names. The callable will be called with attribute names and must
+ return a permission id, None, or the special marker, CheckerPublic. If
+ None is returned, then access to the name is decided by
+ original_checker. If CheckerPublic is returned, then access will be
+ granted without checking a permission.
+
+ An optional setattr permission function or dictionary may be
+ provided for checking set attribute access.
+ """
+ self._original_checker = original_checker
+
+ if type(permission_func) is dict:
+ permission_func = permission_func.get
+ self._permission_func = permission_func
+
+ if type(setattr_permission_func) is dict:
+ setattr_permission_func = setattr_permission_func.get
+ self._setattr_permission_func = setattr_permission_func
+
+ def permission_id(self, name):
+ permission = self._permission_func(name)
+ if permission is None:
+ permission = self._original_checker.permission_id(name)
+ return permission
+
+ def setattr_permission_id(self, name):
+ permission = self._setattr_permission_func(name)
+ if permission is None:
+ permission = self._original_checker.setattr_permission_id(name)
+ return permission
+
+ def check(self, object, name):
+ permission = self._permission_func(name)
+ if permission is not None:
+ if permission is CheckerPublic:
+ return # Public
+ manager = getSecurityManager()
+ if manager.checkPermission(permission, object):
+ return
+ else:
+ __traceback_supplement__ = (TracebackSupplement, object)
+ raise Unauthorized(name=name)
+ else:
+ # let the original checker decide
+ self._original_checker.check(object, name)
+ return
+
+ def check_getattr(self, object, name):
+ permission = self._permission_func(name)
+ if permission is not None:
+ if permission is CheckerPublic:
+ return # Public
+ manager = getSecurityManager()
+ if manager.checkPermission(permission, object):
+ return
+ else:
+ __traceback_supplement__ = (TracebackSupplement, object)
+ raise Unauthorized(name=name)
+ else:
+ # let the original checker decide
+ self._original_checker.check_getattr(object, name)
+ return
+
+ def check_setattr(self, object, name):
+ permission = self._setattr_permission_func(name)
+ if permission is not None:
+ if permission is CheckerPublic:
+ return # Public
+ manager = getSecurityManager()
+ if manager.checkPermission(permission, object):
+ return
+ else:
+ __traceback_supplement__ = (TracebackSupplement, object)
+ raise Unauthorized(name=name)
+ else:
+ # let the original checker decide
+ self._original_checker.check_setattr(object, name)
+ return
+
+ def proxy(self, value):
+ 'See IChecker'
+ # Now we need to create a proxy
+
+ checker = getattr(value, '__Security_checker__', None)
+ if checker is None:
+ checker = selectChecker(value)
+ if checker is None:
+ return value
+
+ return Proxy(value, checker)
+
+
class CheckerLoggingMixin:
"""Debugging mixin for Checker.
@@ -232,7 +337,8 @@
if WATCH_CHECKERS:
class Checker(CheckerLoggingMixin, Checker):
pass
-
+ class DecoratedChecker(CheckerLoggingMixin, DecoratedChecker):
+ pass
# Helper class for __traceback_supplement__
class TracebackSupplement: