[Zope-dev] Zope 2.3.0 AccessControl/SecurityInfo.py
Randall F. Kern
randy@spoke.net
Thu, 1 Mar 2001 15:25:23 -0800
Sorry if these have already been fixed in 2.3.1, I haven't had time to
upgrade yet.
I fixed a small bug in SecurityInfo that made
SecurityInfo.setPermissionDefault() impossible to use:
191c191
> self.roles[permission_name] =3D rdict.keys()
---
< self.roles[permission_name] =3D rdict
def setPermissionDefault(self, permission_name, roles):
"""Declare default roles for a permission"""
rdict =3D {}
for role in roles:
rdict[role] =3D 1
if self.roles.get(permission_name, rdict) !=3D rdict:
LOG('SecurityInfo', WARNING, 'Conflicting default role'
'declarations for permission "%s"' % permission_name)
self._warnings =3D 1
self.roles[permission_name] =3D rdict.keys()
My other problem was that I wanted to setup some default permissions
that are used programatically in my product (i.e. they aren't used to
protect any specific methods, but the methods themselves check for the
permission.) A small change to ClassSecurityInfo.apply() allows you to
call SecurityInfo.setPermissionDefault() to create new permissions, even
if they aren't attached to any methods:
239a240,242
> for permission_name in self.roles.keys():
> if not ac_permissions.has_key(permission_name):
> ac_permissions[permission_name] =3D ()
def apply(self, classobj):
"""Apply security information to the given class object."""
dict =3D classobj.__dict__
# Check the class for an existing __ac_permissions__ and
# incorporate that if present to support older classes or
# classes that haven't fully switched to using SecurityInfo.
if dict.has_key('__ac_permissions__'):
for item in dict['__ac_permissions__']:
permission_name =3D item[0]
self._setaccess(item[1], permission_name)
if len(item) > 2:
self.setDefaultRoles(permission_name, item[2])
# Set __roles__ for attributes declared public or private.
# Collect protected attribute names in ac_permissions.
ac_permissions =3D {}
for name, access in self.names.items():
if access in (ACCESS_PRIVATE, ACCESS_PUBLIC, ACCESS_NONE):
dict['%s__roles__' % name] =3D access
else:
if not ac_permissions.has_key(access):
ac_permissions[access] =3D []
ac_permissions[access].append(name)
# Now transform our nested dict structure into the nested tuple
# structure expected of __ac_permissions__ attributes and set
# it on the class object.
getRoles =3D self.roles.get
__ac_permissions__ =3D []
for permission_name in self.roles.keys():
if not ac_permissions.has_key(permission_name):
ac_permissions[permission_name] =3D ()
permissions =3D ac_permissions.items()
permissions.sort()
for permission_name, names in permissions:
roles =3D getRoles(permission_name, ())
if len(roles):
entry =3D (permission_name, tuple(names), tuple(roles))
else:
entry =3D (permission_name, tuple(names))
__ac_permissions__.append(entry)
dict['__ac_permissions__'] =3D tuple(__ac_permissions__)
# Take care of default attribute access policy
access =3D getattr(self, 'access', _marker)
if access is not _marker:
dict['__allow_access_to_unprotected_subobjects__'] =3D =
access
if getattr(self, '_warnings', None):
LOG('SecurityInfo', WARNING, 'Class "%s" had conflicting '
'security declarations' % classobj.__name__)
-Randy