Source code for zope.security.decorator
##############################################################################
#
# Copyright (c) 2003 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Decorator support
Decorators are proxies that are mostly transparent but that may provide
additional features.
"""
__docformat__ = "reStructuredText"
from zope.interface.declarations import ObjectSpecification
from zope.proxy import getProxiedObject, ProxyBase
from zope.proxy.decorator import SpecificationDecoratorBase
from zope.security.checker import selectChecker, CombinedChecker
from zope.security.proxy import Proxy
from zope.security.proxy import getChecker
[docs]class DecoratedSecurityCheckerDescriptor(object):
"""Descriptor for a Decorator that provides a decorated security checker.
"""
def __get__(self, inst, cls=None):
if inst is None:
return self
else:
proxied_object = getProxiedObject(inst)
if type(proxied_object) is Proxy:
checker = getChecker(proxied_object)
else:
checker = getattr(proxied_object, '__Security_checker__', None)
if checker is None:
checker = selectChecker(proxied_object)
wrapper_checker = selectChecker(inst)
if wrapper_checker is None and checker is None:
raise AttributeError("%r has no attribute %r" %
(proxied_object.__class__.__name__,
'__Security_checker__'))
elif wrapper_checker is None:
return checker
elif checker is None:
return wrapper_checker
else:
return CombinedChecker(wrapper_checker, checker)
def __set__(self, inst, value):
raise TypeError("Can't set __Security_checker__ on a decorated object")
[docs]class SecurityCheckerDecoratorBase(ProxyBase):
"""Base class for a proxy that provides additional security declarations."""
__Security_checker__ = DecoratedSecurityCheckerDescriptor()
[docs]class DecoratorBase(SpecificationDecoratorBase, SecurityCheckerDecoratorBase):
"""Base class for a proxy that provides both additional interfaces and
security declarations."""
# zope.location was made independent of security. To work together with
# security, we re-inject the DecoratedSecurityCheckerDescriptor onto the
# location proxy from here.
# This is the only sane place we found for doing it: it kicks in as soon
# as someone starts using security proxies.
import zope.location.location
zope.location.location.LocationProxy.__Security_checker__ = (
DecoratedSecurityCheckerDescriptor())