Source code for zope.security.adapter
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Support for taking security into account in adaptation
"""
from zope.location import ILocation
from zope.location import LocationProxy
from zope.security.checker import ProxyFactory
from zope.security.proxy import removeSecurityProxy
[docs]def assertLocation(adapter, parent):
"""
Assert locatable adapters.
This function asserts that the adapter get location-proxied if it
doesn't provide :class:`zope.location.interfaces.ILocation`
itself. Furthermore, the returned locatable adapter get its parent
set if its ``__parent__`` attribute is currently None.
"""
# handle none-locatable adapters (A)
if not ILocation.providedBy(adapter):
locatable = LocationProxy(adapter)
locatable.__parent__ = parent
return locatable
# handle locatable, parentless adapters (B)
if adapter.__parent__ is None:
adapter.__parent__ = parent
return adapter
# handle locatable, parentful adapters (C)
return adapter
[docs]class LocatingTrustedAdapterFactory(object):
"""
Adapt an adapter factory to provide trusted and (locatable) adapters.
Trusted adapters always adapt unproxied objects. If asked to
adapt any proxied objects, it will unproxy them and then
security-proxy the resulting adapter (S) unless the objects where not
security-proxied before (N).
Further locating trusted adapters provide a location for protected
adapters only (S). If such a protected adapter itself does not
provide ILocation it is wrapped within a location proxy and it
parent will be set. If the adapter does provide
:class:`zope.location.interfaces.ILocation` and its
``__parent__`` is None, we set the ``__parent__`` to the adapter's
context.
"""
def __init__(self, factory):
self.factory = factory
self.__name__ = factory.__name__
self.__module__ = factory.__module__
# protected methods
def _customizeProtected(self, adapter, context):
return assertLocation(adapter, context)
def _customizeUnprotected(self, adapter, context):
if ILocation.providedBy(adapter) and adapter.__parent__ is None:
adapter.__parent__ = context
return adapter
def __call__(self, *args):
for arg in args:
if removeSecurityProxy(arg) is not arg:
args = [removeSecurityProxy(x) for x in args]
adapter = self.factory(*args)
adapter = self._customizeProtected(adapter, args[0])
return ProxyFactory(adapter)
adapter = self.factory(*args)
adapter = self._customizeUnprotected(adapter, args[0])
return adapter
[docs]class TrustedAdapterFactory(LocatingTrustedAdapterFactory):
"""
Adapt an adapter factory to provide trusted adapters.
Trusted adapters always adapt unproxied objects. If asked to
adapt any proxied objects, it will unproxy them and then
security-proxy the resulting adapter unless the objects where not
security-proxied before.
If the adapter does provide
:class:`zope.location.interfaces.ILocation` and its ``__parent__``
is None, we set the ``__parent__`` to the adapter's context.
"""
# do not location-proxy the adapter
def _customizeProtected(self, adapter, context):
return self._customizeUnprotected(adapter, context)
[docs]class LocatingUntrustedAdapterFactory(object):
"""
Adapt an adapter factory to provide locatable untrusted adapters
Untrusted adapters always adapt proxied objects. If any permission
other than :const:`zope.Public
<zope.security.interfaces.PUBLIC_PERMISSION_NAME>` is required,
untrusted adapters need a location in order that the local
authentication mechanism can be invoked correctly.
If the adapter does not provide
:class:`zope.location.interfaces.ILocation`, we location proxy it
and set the parent. If the adapter does provide ``ILocation`` and
its ``__parent__`` is None, we set the ``__parent__`` to the
adapter's context only.
"""
def __init__(self, factory):
self.factory = factory
self.__name__ = factory.__name__
self.__module__ = factory.__module__
def __call__(self, *args):
adapter = self.factory(*args)
return assertLocation(adapter, args[0])