[Checkins] SVN: z3ext.security/tags/1.2.0/ egg 1.2.0
Nikolay Kim
fafhrd at datacom.kz
Fri Mar 21 02:11:54 EDT 2008
Log message for revision 84813:
egg 1.2.0
Changed:
A z3ext.security/tags/1.2.0/
D z3ext.security/tags/1.2.0/src/
A z3ext.security/tags/1.2.0/src/
A z3ext.security/tags/1.2.0/src/z3ext/security/README.txt
A z3ext.security/tags/1.2.0/src/z3ext/security/__init__.py
A z3ext.security/tags/1.2.0/src/z3ext/security/configure.zcml
A z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.py
A z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.txt
A z3ext.security/tags/1.2.0/src/z3ext/security/groups.py
A z3ext.security/tags/1.2.0/src/z3ext/security/interfaces.py
A z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.py
A z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.txt
A z3ext.security/tags/1.2.0/src/z3ext/security/tests.py
A z3ext.security/tags/1.2.0/src/z3ext/security/utils.py
-=-
Copied: z3ext.security/tags/1.2.0 (from rev 84812, z3ext.security/trunk)
Copied: z3ext.security/tags/1.2.0/src (from rev 84811, z3ext.security/trunk/src)
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/README.txt (from rev 84812, z3ext.security/trunk/src/z3ext/security/README.txt)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/README.txt (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/README.txt 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,11 @@
+==============
+z3ext.security
+==============
+
+This package provides security related features
+
+ - Extended Security Policy: securitypolicy.txt
+
+ - Extended Grant Information: grantinfo.txt
+
+ - Principal Groups infomration: groups.txt
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/__init__.py (from rev 84812, z3ext.security/trunk/src/z3ext/security/__init__.py)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/__init__.py (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/__init__.py 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/configure.zcml (from rev 84812, z3ext.security/trunk/src/z3ext/security/configure.zcml)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/configure.zcml (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/configure.zcml 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,35 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <!-- IPrincipalGroups adapter -->
+ <adapter
+ for="zope.security.interfaces.IPrincipal"
+ provides=".interfaces.IPrincipalGroups"
+ factory=".groups.PrincipalGroups" />
+
+ <!-- extended grant info -->
+ <adapter factory="z3ext.security.grantinfo.ExtendedGrantInfo" />
+
+ <class class=".grantinfo.ExtendedGrantInfo">
+ <allow interface=".interfaces.IExtendedGrantInfo" />
+ </class>
+
+ <!-- add security declaration for anonymous -->
+ <class class="zope.app.security.principalregistry.UnauthenticatedPrincipal">
+ <require
+ permission="zope.Public"
+ interface="zope.security.interfaces.IPrincipal" />
+ </class>
+
+ <!-- Registering documentation with API doc -->
+ <configure
+ xmlns:apidoc="http://namespaces.zope.org/apidoc"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
+ zcml:condition="have apidoc">
+
+ <apidoc:bookchapter
+ id="z3ext"
+ title="z3ext packages" />
+
+ </configure>
+
+</configure>
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.py (from rev 84812, z3ext.security/trunk/src/z3ext/security/grantinfo.py)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.py (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.py 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,104 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+""" IExtendedGrantInfo implmentation, extended version of IGrantInfo
+
+$Id$
+"""
+
+from zope import interface, component
+from zope.component import getAdapters
+from zope.security.proxy import removeSecurityProxy
+
+from zope.securitypolicy.interfaces import IPrincipalRoleMap
+from zope.securitypolicy.interfaces import IRolePermissionMap
+
+from zope.securitypolicy.principalrole import principalRoleManager
+globalPrincipalsForRole = principalRoleManager.getPrincipalsForRole
+
+from interfaces import IExtendedGrantInfo
+from securitypolicy import globalRolesForPrincipal, globalRolesForPermission
+
+
+class ExtendedGrantInfo(object):
+ component.adapts(interface.Interface)
+ interface.implements(IExtendedGrantInfo)
+
+ def __init__(self, context):
+ self.context = context
+
+ def getRolesForPermission(self, permission):
+ context = removeSecurityProxy(self.context)
+
+ roles = {}
+ for name, roleperm in getAdapters((context,), IRolePermissionMap):
+ for role, setting in roleperm.getRolesForPermission(permission):
+ if role not in roles:
+ roles[role] = setting
+
+ parent = getattr(context, '__parent__', None)
+ if parent is None:
+ for name, setting in globalRolesForPermission(permission):
+ if name not in roles:
+ roles[name] = setting
+ else:
+ info = IExtendedGrantInfo(parent)
+ for role, setting in info.getRolesForPermission(permission):
+ if role not in roles:
+ roles[role] = setting
+
+ return roles.items()
+
+ def getRolesForPrincipal(self, principal):
+ context = removeSecurityProxy(self.context)
+
+ roles = {}
+ for name, prinrole in getAdapters((context,), IPrincipalRoleMap):
+ for role, setting in prinrole.getRolesForPrincipal(principal):
+ if role not in roles:
+ roles[role] = setting
+
+ parent = getattr(context, '__parent__', None)
+ if parent is None:
+ for role, setting in globalRolesForPrincipal(principal):
+ if role not in roles:
+ roles[role] = setting
+ else:
+ info = IExtendedGrantInfo(parent)
+ for role, setting in info.getRolesForPrincipal(principal):
+ if role not in roles:
+ roles[role] = setting
+
+ return roles.items()
+
+ def getPrincipalsForRole(self, role):
+ context = removeSecurityProxy(self.context)
+
+ principals = {}
+ for name, prinrole in getAdapters((context,), IPrincipalRoleMap):
+ for principal, setting in prinrole.getPrincipalsForRole(role):
+ if principal not in principals:
+ principals[principal] = setting
+
+ parent = getattr(context, '__parent__', None)
+ if parent is None:
+ for principal, setting in globalPrincipalsForRole(role):
+ if principal not in principals:
+ principal[role] = setting
+ else:
+ info = IExtendedGrantInfo(parent)
+ for principal, setting in info.getPrincipalsForRole(role):
+ if principal not in principals:
+ principals[principal] = setting
+
+ return principals.items()
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.txt (from rev 84812, z3ext.security/trunk/src/z3ext/security/grantinfo.txt)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.txt (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/grantinfo.txt 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,141 @@
+==================
+IExtendedGrantInfo
+==================
+
+IExtendedGrantInfo interface is extended version of IGrantInfo
+from zope/securitypolicy but it runs for each parent and
+uses all available IRolePermissionMap and IPrincipalRoleMap adapters
+for object.
+
+initialization:
+
+ >>> from zope import interface
+ >>> from zope.component import provideAdapter
+ >>> from zope.securitypolicy import interfaces
+ >>> from z3ext.security.grantinfo import ExtendedGrantInfo
+ >>> from z3ext.security.interfaces import IExtendedGrantInfo
+
+ >>> provideAdapter(ExtendedGrantInfo, (interface.Interface,), IExtendedGrantInfo)
+
+ >>> import zope.interface
+ >>> from zope.annotation.interfaces import IAttributeAnnotatable
+
+ >>> class IMyObject(zope.interface.Interface):
+ ... pass
+
+ >>> class Ob:
+ ... __parent__ = None
+ ... zope.interface.implements(IAttributeAnnotatable, IMyObject)
+
+ >>> ob1 = Ob()
+ >>> ob2 = Ob()
+ >>> ob3 = Ob()
+ >>> ob4 = Ob()
+
+Let's build parents dependencies: ob1->ob2->ob3, ob1->ob4
+
+ >>> ob2.__parent__ = ob1
+ >>> ob3.__parent__ = ob2
+ >>> ob4.__parent__ = ob1
+
+ >>> grantinfo = IExtendedGrantInfo(ob3)
+ >>> IExtendedGrantInfo.providedBy(grantinfo)
+ True
+
+ >>> grantinfo.getRolesForPermission('P1')
+ []
+
+This is standard behaviour:
+
+ >>> roleper = interfaces.IRolePermissionManager(ob3)
+ >>> roleper.grantPermissionToRole('P1', 'role1')
+
+ >>> grantinfo.getRolesForPermission('P1')
+ [('role1', PermissionSetting: Allow)]
+
+Now let's set permission in parent:
+
+ >>> roleper = interfaces.IRolePermissionManager(ob2)
+ >>> roleper.grantPermissionToRole('P1', 'role2')
+
+ >>> grantinfo.getRolesForPermission('P1')
+ [('role1', PermissionSetting: Allow), ('role2', PermissionSetting: Allow)]
+
+ >>> roleper = interfaces.IRolePermissionManager(ob1)
+ >>> roleper.grantPermissionToRole('P1', 'role3')
+
+ >>> grantinfo.getRolesForPermission('P1')
+ [('role1', PermissionSetting: Allow), ('role3', PermissionSetting: Allow), ('role2', PermissionSetting: Allow)]
+
+ >>> roleper.denyPermissionToRole('P1', 'role3')
+
+ >>> grantinfo.getRolesForPermission('P1')
+ [('role1', PermissionSetting: Allow), ('role3', PermissionSetting: Deny), ('role2', PermissionSetting: Allow)]
+
+But lower object permissions/role has more weight, now we
+have role3 denied for P1 permission on ob1, we can allow permission
+on ob2 so ob3 should have allow for P1 permission on role role3
+
+ >>> roleper = interfaces.IRolePermissionManager(ob2)
+ >>> roleper.grantPermissionToRole('P1', 'role3')
+
+ >>> grantinfo.getRolesForPermission('P1')
+ [('role1', PermissionSetting: Allow), ('role3', PermissionSetting: Allow), ('role2', PermissionSetting: Allow)]
+
+ >>> grantinfo = IExtendedGrantInfo(ob4)
+ >>> grantinfo.getRolesForPermission('P1')
+ [('role3', PermissionSetting: Deny)]
+
+
+getRolesForPrincipal
+--------------------
+
+ >>> grantinfo = IExtendedGrantInfo(ob3)
+ >>> grantinfo.getRolesForPrincipal('bob')
+ []
+
+ >>> prinrole = interfaces.IPrincipalRoleManager(ob3)
+ >>> prinrole.assignRoleToPrincipal('role1', 'bob')
+
+ >>> grantinfo.getRolesForPrincipal('bob')
+ [('role1', PermissionSetting: Allow)]
+
+ >>> prinrole = interfaces.IPrincipalRoleManager(ob2)
+ >>> prinrole.assignRoleToPrincipal('role2', 'bob')
+
+ >>> grantinfo.getRolesForPrincipal('bob')
+ [('role1', PermissionSetting: Allow), ('role2', PermissionSetting: Allow)]
+
+ >>> prinrole = interfaces.IPrincipalRoleManager(ob1)
+ >>> prinrole.assignRoleToPrincipal('role3', 'bob')
+
+ >>> grantinfo.getRolesForPrincipal('bob')
+ [('role1', PermissionSetting: Allow), ('role3', PermissionSetting: Allow), ('role2', PermissionSetting: Allow)]
+
+role3 role allowed for principal 'bob' on ob1, we can deny this role on object ob2
+and on ob3 role3 should be denied
+
+ >>> prinrole = interfaces.IPrincipalRoleManager(ob2)
+ >>> prinrole.removeRoleFromPrincipal('role3', 'bob')
+
+ >>> grantinfo.getRolesForPrincipal('bob')
+ [('role1', PermissionSetting: Allow), ('role3', PermissionSetting: Deny), ('role2', PermissionSetting: Allow)]
+
+
+getPrincipalsForRole
+--------------------
+
+This is new method in extended version, it usefull when we need get all
+principals that have role, for example for cataloging.
+
+ >>> grantinfo = IExtendedGrantInfo(ob3)
+ >>> grantinfo.getPrincipalsForRole('role1')
+ [('bob', PermissionSetting: Allow)]
+
+We can get info about other principals with same role
+
+ >>> prinrole = interfaces.IPrincipalRoleManager(ob1)
+ >>> prinrole.assignRoleToPrincipal('role1', 'bob1')
+
+ >>> grantinfo.getPrincipalsForRole('role1')
+ [('bob', PermissionSetting: Allow), ('bob1', PermissionSetting: Allow)]
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/groups.py (from rev 84812, z3ext.security/trunk/src/z3ext/security/groups.py)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/groups.py (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/groups.py 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+from zope import interface
+from zope.component import getUtility
+from zope.security.proxy import removeSecurityProxy
+from zope.security.interfaces import IPrincipal, IGroup, IGroupAwarePrincipal
+from zope.app.security.interfaces import IAuthentication
+
+from interfaces import IPrincipalGroups
+
+
+class PrincipalGroups(object):
+ interface.implements(IPrincipalGroups)
+
+ _cached = None
+
+ def __init__(self, principal):
+ self.principal = removeSecurityProxy(principal)
+
+ def getGroups(self, type=None):
+ if type is None:
+ type = IPrincipal
+
+ principal = self.principal
+
+ if IGroupAwarePrincipal.providedBy(principal):
+ if principal.groups:
+ seen = set()
+ principals = getUtility(IAuthentication)
+
+ stack = [iter(principal.groups)]
+
+ if IGroup.providedBy(principal):
+ stack.append(iter([principal.id]))
+
+ while stack:
+ try:
+ group_id = stack[-1].next()
+ except StopIteration:
+ stack.pop()
+ else:
+ if group_id not in seen:
+ group = principals.getPrincipal(group_id)
+
+ seen.add(group_id)
+ stack.append(iter(group.groups))
+
+ if type.providedBy(group):
+ yield group
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/interfaces.py (from rev 84812, z3ext.security/trunk/src/z3ext/security/interfaces.py)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/interfaces.py (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/interfaces.py 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+""" z3ext.security interfaces
+
+$Id$
+"""
+from zope import interface
+
+
+class IPrincipalGroups(interface.Interface):
+ """ principal groups """
+
+ principal = interface.Attribute('Principal')
+
+ def getGroups(type=None):
+ """ get principal groups """
+
+
+class IExtendedGrantInfo(interface.Interface):
+ """ similar to IGrantInfo but recursive """
+
+ def getRolesForPermission(permission):
+ """ roles with permission """
+
+ def getRolesForPrincipal(principal):
+ """ principal roles """
+
+ def getPrincipalsForRole(role_id):
+ """ Get the principals that have been granted a role. """
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.py (from rev 84812, z3ext.security/trunk/src/z3ext/security/securitypolicy.py)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.py (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.py 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,202 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+from zope.component import getAdapters
+from zope.security.proxy import removeSecurityProxy
+from zope.app.security.settings import Allow
+
+from zope.securitypolicy.interfaces import IPrincipalRoleMap
+from zope.securitypolicy.interfaces import IRolePermissionMap
+from zope.securitypolicy.interfaces import IPrincipalPermissionMap
+
+from zope.securitypolicy.zopepolicy import ZopeSecurityPolicy
+
+from zope.securitypolicy.zopepolicy import SettingAsBoolean
+from zope.securitypolicy.zopepolicy import globalRolesForPrincipal
+from zope.securitypolicy.zopepolicy import globalRolesForPermission
+from zope.securitypolicy.zopepolicy import globalPrincipalPermissionSetting
+
+
+class CacheEntry(object):
+
+ prinper = None
+ roles_adapters = None
+ principal_roles_adapters = None
+
+ def __init__(self):
+ self.prin = {}
+ self.decision = {}
+ self.roles = {}
+ self.principal_roles = {}
+
+
+class SecurityPolicy(ZopeSecurityPolicy):
+
+ def cache(self, parent):
+ cache = self._cache
+
+ if parent in cache:
+ return cache[parent]
+ else:
+ cacheEntry = CacheEntry()
+ cache[parent] = cacheEntry
+ return cacheEntry
+
+ def cached_roles(self, parent, permission, _allow=Allow):
+ cache = self.cache(parent)
+ cache_roles = cache.roles
+ if permission in cache_roles:
+ return cache_roles[permission]
+
+ if parent is None:
+ roles = dict(
+ [(role, 1) for (role, setting) in globalRolesForPermission(permission)
+ if setting is _allow])
+ cache_roles[permission] = roles
+ return roles
+
+ roles = self.cached_roles(
+ removeSecurityProxy(getattr(parent, '__parent__', None)), permission)
+
+ # cache adaters
+ rolepers = cache.roles_adapters
+ if rolepers is None:
+ rolepers = tuple(getAdapters((parent,), IRolePermissionMap))
+ cache.roles_adapters = rolepers
+
+ if rolepers:
+ roles = roles.copy()
+ for name, roleper in rolepers:
+ for role, setting in roleper.getRolesForPermission(permission):
+ if setting is _allow:
+ roles[role] = 1
+ elif role in roles:
+ del roles[role]
+
+ cache_roles[permission] = roles
+ return roles
+
+ def cached_principal_roles(self, parent, principal,
+ SettingAsBoolean=SettingAsBoolean):
+ cache = self.cache(parent)
+ cache_principal_roles = cache.principal_roles
+ if principal in cache_principal_roles:
+ return cache_principal_roles[principal]
+
+ if parent is None:
+ roles = dict(
+ [(role, SettingAsBoolean[setting])
+ for (role, setting) in globalRolesForPrincipal(principal)]
+ )
+ roles['zope.Anonymous'] = True # Everybody has Anonymous
+ cache_principal_roles[principal] = roles
+ return roles
+
+ roles = self.cached_principal_roles(
+ removeSecurityProxy(getattr(parent, '__parent__', None)), principal)
+
+ roles = roles.copy()
+
+ # cache adaters
+ adapters = cache.principal_roles_adapters
+ if adapters is None:
+ adapters = tuple(getAdapters((parent,), IPrincipalRoleMap))
+ cache.principal_roles_adapters = adapters
+
+ for name, prinrole in adapters:
+ for role, setting in prinrole.getRolesForPrincipal(principal):
+ roles[role] = SettingAsBoolean[setting]
+
+ cache_principal_roles[principal] = roles
+ return roles
+
+
+ def cached_prinper(self, parent, principal, groups, permission):
+ # Compute the permission, if any, for the principal.
+ cache = self.cache(parent)
+ cache_prin = cache.prin
+
+ if principal in cache_prin:
+ cache_prin_per = cache_prin[principal]
+ else:
+ cache_prin_per = cache_prin[principal] = {}
+
+ if permission in cache_prin_per:
+ return cache_prin_per[permission]
+
+ if parent is None:
+ prinper = SettingAsBoolean[
+ globalPrincipalPermissionSetting(permission, principal, None)
+ ]
+ cache_prin_per[permission] = prinper
+ return prinper
+
+ prinper = cache.prinper
+ if prinper is None:
+ cache.prinper = prinper = IPrincipalPermissionMap(parent, None)
+
+ if prinper is not None:
+ prinper = SettingAsBoolean[
+ prinper.getSetting(permission, principal, None)
+ ]
+ if prinper is not None:
+ cache_prin_per[permission] = prinper
+ return prinper
+
+ parent = removeSecurityProxy(getattr(parent, '__parent__', None))
+ prinper = self.cached_prinper(parent, principal, groups, permission)
+ cache_prin_per[permission] = prinper
+ return prinper
+
+ def cached_decision(self, parent, principal, groups, permission):
+ # Return the decision for a principal and permission
+ cache = self.cache(parent)
+ cache_decision = cache.decision
+
+ if principal in cache_decision:
+ cache_decision_prin = cache_decision[principal]
+ else:
+ cache_decision_prin = cache_decision[principal] = {}
+
+ if permission in cache_decision_prin:
+ return cache_decision_prin[permission]
+
+ # cache_decision_prin[permission] is the cached decision for a
+ # principal and permission.
+
+ decision = self.cached_prinper(parent, principal, groups, permission)
+ if (decision is None) and groups:
+ decision = self._group_based_cashed_prinper(
+ parent, principal, groups, permission)
+
+ if decision is not None:
+ cache_decision_prin[permission] = decision
+ return decision
+
+ roles = self.cached_roles(parent, permission)
+ if roles:
+ prin_roles = self.cached_principal_roles(parent, principal)
+ if groups:
+ prin_roles = self.cached_principal_roles_w_groups(
+ parent, principal, groups, prin_roles)
+ for role, setting in prin_roles.items():
+ if setting and (role in roles):
+ cache_decision_prin[permission] = decision = True
+ return decision
+
+ cache_decision_prin[permission] = decision = False
+ return decision
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.txt (from rev 84812, z3ext.security/trunk/src/z3ext/security/securitypolicy.txt)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.txt (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/securitypolicy.txt 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,149 @@
+=============================
+Extended Zope Security Policy
+=============================
+
+This package implements a extended version of zope.securitypolicy.
+Main difference:
+
+ - for permissions to roles mapping we use IRolePermissionManager interface
+
+ - for roles to permissions mapping we try find all IPrincipalRoleMap
+ adapters, including named adapters, extended security policy
+ allow dynmiclly calculate roles for principal
+
+Everything else is standard zope3 implementation. For standard security policy
+documentation check zope/securitypolicy/zopepolicy.txt file.
+Most of this code from zopepolicy.txt file because in general this security
+policy only extended version of standard version.
+
+
+ >>> import zope.interface
+ >>> from zope.annotation.interfaces import IAttributeAnnotatable
+
+ >>> class IMyObject(zope.interface.Interface):
+ ... pass
+
+ >>> class Ob:
+ ... __parent__ = None
+ ... zope.interface.implements(IAttributeAnnotatable, IMyObject)
+
+ >>> ob = Ob()
+
+ >>> class Principal:
+ ... def __init__(self, id):
+ ... self.id = id
+ ... self.groups = []
+
+ >>> principal = Principal('bob')
+
+ >>> class Participation:
+ ... interaction = None
+
+ >>> from z3ext.security.securitypolicy import SecurityPolicy
+
+ >>> import zope.security.management
+ >>> oldpolicy = zope.security.management.setSecurityPolicy(SecurityPolicy)
+
+Let's create interaction:
+
+ >>> participation = Participation()
+ >>> participation.principal = principal
+ >>> zope.security.management.endInteraction()
+ >>> zope.security.management.newInteraction(participation)
+ >>> interaction = zope.security.management.getInteraction()
+
+ >>> interaction.checkPermission('P1', ob)
+ False
+
+Let's work with roles
+
+ >>> from zope.securitypolicy import interfaces
+
+ >>> interaction.checkPermission('P1', ob)
+ False
+
+We will use 'content.Owner' role, we need give permission to role:
+
+ >>> roleper = interfaces.IRolePermissionManager(ob)
+ >>> roleper.grantPermissionToRole('P1', 'content.Owner')
+
+Right now 'bob' principal doesn't have 'content.Owner' role on 'ob' object
+with standard policy we should use IPrincipalRoleManager adapter to
+give ''content.Owner' role to principal. With extended version we can define
+named adapter. Here example that implemen owner roles that doesn't
+depends on object annotations:
+
+Let's use 'ob' object attribute to define owner of object:
+
+ >>> ob.owner = 'bob'
+
+Now we need custom IPrincipalRoleMap:
+
+ >>> from zope.app.security.settings import Allow, Deny
+
+ >>> class OwnerRolesMap(object):
+ ... zope.interface.implements(interfaces.IPrincipalRoleMap)
+ ...
+ ... def __init__(self, context):
+ ... self.context = context
+ ...
+ ... def getRolesForPrincipal(self, principal_id):
+ ... if getattr(self.context, 'owner', '') == principal_id:
+ ... return (('content.Owner', Allow),)
+ ... return (('content.Owner', Deny),)
+
+For testing implemented only getRolesForPrincipal method, but in many cases we
+need implement all methods.
+
+Now we need register named adapter
+
+ >>> from zope.component import provideAdapter
+ >>> provideAdapter(OwnerRolesMap, (IMyObject,), \
+ ... interfaces.IPrincipalRoleMap, name='ownership')
+ >>> interaction.invalidate_cache()
+
+So 'bob' principal should get 'content.Owner' role on 'ob'
+
+ >>> interaction.checkPermission('P1', ob)
+ True
+
+For better 'Ownership' implementation check z3ext.ownership package.
+
+For futher testing remove permission from role:
+
+ >>> roleper.unsetPermissionFromRole('P1', 'content.Owner')
+
+ >>> interaction.checkPermission('P1', ob)
+ False
+
+With extended security policy we can supply custom IRolePermissionManager
+implementation for object:
+
+ >>> class RolePermissionMap(object):
+ ... zope.interface.implements(interfaces.IRolePermissionMap)
+ ...
+ ... def __init__(self, context):
+ ... self.context = context
+ ...
+ ... def getRolesForPermission(self, permission_id):
+ ... if permission_id == 'P2':
+ ... return (('content.Owner', Allow), ('content.Owner1', Deny))
+ ... elif permission_id == 'P3':
+ ... return (('content.Owner1', Allow), ('content.Owner', Deny))
+ ... return ()
+
+ >>> provideAdapter(RolePermissionMap, (IMyObject,), \
+ ... interfaces.IRolePermissionMap, name='custom')
+ >>> interaction.invalidate_cache()
+
+ >>> interaction.checkPermission('P2', ob)
+ True
+
+ >>> interaction.checkPermission('P3', ob)
+ False
+
+ >>> prinrole = interfaces.IPrincipalRoleManager(ob)
+ >>> prinrole.assignRoleToPrincipal('content.Owner1', 'bob')
+
+ >>> interaction.checkPermission('P3', ob)
+ True
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/tests.py (from rev 84812, z3ext.security/trunk/src/z3ext/security/tests.py)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/tests.py (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/tests.py 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,43 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+""" z3ext.security tests
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import unittest, doctest
+from zope import interface, schema
+from zope.app.testing import setup, ztapi
+from zope.security.management import endInteraction
+from zope.securitypolicy.tests import test_zopepolicy
+from z3ext.security.grantinfo import ExtendedGrantInfo
+from z3ext.security.interfaces import IExtendedGrantInfo
+
+
+def setUp(test):
+ test_zopepolicy.setUp(test)
+ ztapi.provideAdapter(interface.Interface, IExtendedGrantInfo, ExtendedGrantInfo)
+
+def tearDown(test):
+ setup.placelessTearDown()
+
+
+def test_suite():
+ return unittest.TestSuite((
+ doctest.DocFileSuite(
+ 'grantinfo.txt',setUp=setUp, tearDown=tearDown),
+ doctest.DocFileSuite(
+ 'securitypolicy.txt',setUp=setUp, tearDown=tearDown),
+ ))
Copied: z3ext.security/tags/1.2.0/src/z3ext/security/utils.py (from rev 84812, z3ext.security/trunk/src/z3ext/security/utils.py)
===================================================================
--- z3ext.security/tags/1.2.0/src/z3ext/security/utils.py (rev 0)
+++ z3ext.security/tags/1.2.0/src/z3ext/security/utils.py 2008-03-21 06:11:53 UTC (rev 84813)
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+from zope.component import getUtility
+from zope.security.management import queryInteraction
+from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
+
+
+def getPrincipal(id=None):
+ """ get current interaction principal """
+ if id is None:
+ interaction = queryInteraction()
+
+ if interaction is not None:
+ for participation in interaction.participations:
+ if participation.principal is not None:
+ return participation.principal
+ else:
+ try:
+ return getUtility(IAuthentication).getPrincipal(id)
+ except PrincipalLookupError:
+ return None
More information about the Checkins
mailing list