vendor/Five/1.2b-r20590

view security.py @ 0:3673ed425f80

Vendor import of Five 1.2b+ (r20590)
author fguillaume
date Fri, 02 Dec 2005 20:25:42 +0000
parents
children
line source
1 ##############################################################################
2 #
3 # Copyright (c) 2004, 2005 Zope Corporation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Five security handling
16 $Id: security.py 18859 2005-10-24 12:13:39Z philikon $
17 """
18 from zope.interface import implements, classProvides
19 from zope.component import queryUtility, getUtility
20 from zope.security.management import thread_local
21 from zope.security.interfaces import IInteraction, ISecurityPolicy
22 from zope.security.simplepolicies import ParanoidSecurityPolicy
23 from zope.app.security.interfaces import IPermission
24 from zope.app import zapi
26 from AccessControl import ClassSecurityInfo, getSecurityManager
27 from Globals import InitializeClass as initializeClass
28 from types import StringTypes
30 CheckerPublicId = 'zope.Public'
31 CheckerPrivateId = 'zope2.Private'
32 from zope.security.checker import CheckerPublic
34 def getSecurityInfo(klass):
35 sec = {}
36 info = vars(klass)
37 if info.has_key('__ac_permissions__'):
38 sec['__ac_permissions__'] = info['__ac_permissions__']
39 for k, v in info.items():
40 if k.endswith('__roles__'):
41 sec[k] = v
42 return sec
44 def clearSecurityInfo(klass):
45 sec = {}
46 info = vars(klass)
47 if info.has_key('__ac_permissions__'):
48 delattr(klass, '__ac_permissions__')
49 for k, v in info.items():
50 if k.endswith('__roles__'):
51 delattr(klass, k)
53 def checkPermission(permission, object, interaction=None):
54 """Return whether security policy allows permission on object.
56 Arguments:
57 permission -- A permission name
58 object -- The object being accessed according to the permission
59 interaction -- This Zope 3 concept has no equivalent in Zope 2,
60 and is ignored.
62 checkPermission is guaranteed to return True if permission is
63 CheckerPublic or None.
64 """
65 if (permission in ('zope.Public', 'zope2.Public') or
66 permission is None or permission is CheckerPublic):
67 return True
69 if isinstance(permission, StringTypes):
70 permission = zapi.queryUtility(IPermission, unicode(permission))
71 if permission is None:
72 return False
74 if getSecurityManager().checkPermission(permission.title, object):
75 return True
77 return False
79 class FiveSecurityPolicy(ParanoidSecurityPolicy):
80 """Security policy that bridges between Zope 3 security mechanisms and
81 Zope 2's security policy.
83 Don't let the name of the base class fool you... This really just
84 delegates to Zope 2's security manager."""
85 classProvides(ISecurityPolicy)
86 implements(IInteraction)
88 def checkPermission(self, permission, object):
89 return checkPermission(permission, object)
91 def newInteraction():
92 """Con Zope 3 to use Zope 2's checkPermission.
94 Zope 3 when it does a checkPermission will turn around and
95 ask the thread local interaction for the checkPermission method.
96 By making the interaction *be* Zope 2's security manager, we can
97 con Zope 3 into using Zope 2's checker...
98 """
99 if getattr(thread_local, 'interaction', None) is None:
100 thread_local.interaction = FiveSecurityPolicy()
102 def _getSecurity(klass):
103 # a Zope 2 class can contain some attribute that is an instance
104 # of ClassSecurityInfo. Zope 2 scans through things looking for
105 # an attribute that has the name __security_info__ first
106 info = vars(klass)
107 for k, v in info.items():
108 if hasattr(v, '__security_info__'):
109 return v
110 # we stuff the name ourselves as __security__, not security, as this
111 # could theoretically lead to name clashes, and doesn't matter for
112 # zope 2 anyway.
113 security = ClassSecurityInfo()
114 setattr(klass, '__security__', security)
115 return security
117 def protectName(klass, name, permission_id):
118 """Protect the attribute 'name' on 'klass' using the given
119 permission"""
120 security = _getSecurity(klass)
121 # XXX: Sometimes, the object CheckerPublic is used instead of the
122 # string zope.Public. I haven't ben able to figure out why, or if
123 # it is correct, or a bug. So this is a workaround.
124 if permission_id is CheckerPublic:
125 security.declarePublic(name)
126 return
127 # Zope 2 uses string, not unicode yet
128 name = str(name)
129 if permission_id == CheckerPublicId:
130 security.declarePublic(name)
131 elif permission_id == CheckerPrivateId:
132 security.declarePrivate(name)
133 else:
134 permission = getUtility(IPermission, name=permission_id)
135 # Zope 2 uses string, not unicode yet
136 perm = str(permission.title)
137 security.declareProtected(perm, name)
139 def protectClass(klass, permission_id):
140 """Protect the whole class with the given permission"""
141 security = _getSecurity(klass)
142 if permission_id == CheckerPublicId:
143 security.declareObjectPublic()
144 elif permission_id == CheckerPrivateId:
145 security.declareObjectPrivate()
146 else:
147 permission = getUtility(IPermission, name=permission_id)
148 # Zope 2 uses string, not unicode yet
149 perm = str(permission.title)
150 security.declareObjectProtected(perm)