1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
##############################################################################
#
# 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.security.checker import ProxyFactory
from zope.security.proxy import removeSecurityProxy
from zope.location import ILocation, LocationProxy
def assertLocation(adapter, parent):
"""Assert locatable adapters.
This function asserts that the adapter get location-proxied if
it doesn't provide ILocation itself. Further more 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
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 ILocation and it's __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
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 ILocation and it's __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)
class LocatingUntrustedAdapterFactory(object):
"""Adapt an adapter factory to provide locatable untrusted adapters
Untrusted adapters always adapt proxied objects. If any permission
other than zope.Public is required, untrusted adapters need a location
in order that the local authentication mechanism can be inovked
correctly.
If the adapter does not provide ILocation, we location proxy it and
set the parent. If the adapter does provide ILocation and
it's __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])
|