[Zope3-checkins] CVS: Zope3/src/zope/products/securitypolicy - __init__.py:1.2 browser.zcml:1.2 configure.zcml:1.2 interfaces.py:1.2 meta.zcml:1.2 metaconfigure.py:1.2 metadirectives.py:1.2 permissionroles.py:1.2 principalpermission.py:1.2 principalrole.py:1.2 role.py:1.2 rolepermission.py:1.2 roleregistry.py:1.2 securitymap.py:1.2 zopepolicy.py:1.2

Chris McDonough chrism at plope.com
Wed Jan 14 17:56:03 EST 2004


Update of /cvs-repository/Zope3/src/zope/products/securitypolicy
In directory cvs.zope.org:/tmp/cvs-serv5558/src/zope/products/securitypolicy

Added Files:
	__init__.py browser.zcml configure.zcml interfaces.py 
	meta.zcml metaconfigure.py metadirectives.py 
	permissionroles.py principalpermission.py principalrole.py 
	role.py rolepermission.py roleregistry.py securitymap.py 
	zopepolicy.py 
Log Message:
Merge security policy refactoring:

 - Moved all role- and grant-related functionality into
   zope.products.securitypolicy (and out of zope.app.security.grant).
   The zope.products.securitypolicy implementation is exactly
   the same as the old implementation; no changes were made
   to the actual mechanics of role-permission or principal-permission
   grants.  The only real difference is that all functionality
   that is the purview of what we want a security policy to have
   control of is now in that one place.

 - Created new modulealias directive which can be used to provide
   aliases to older modules (to not break existing ZODBs when
   module locations change).

 - Added minor feature: "make debug" launches a debug session in the
   spirit of Zope 2's "zopectl debug".
   


=== Zope3/src/zope/products/securitypolicy/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/__init__.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.


=== Zope3/src/zope/products/securitypolicy/browser.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/browser.zcml	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,40 @@
+<zope:configure 
+   xmlns:zope="http://namespaces.zope.org/zope"
+   xmlns="http://namespaces.zope.org/browser">
+
+<!-- Role Service -->
+
+  <menuItem
+     menu="add_service"
+     for="zope.app.interfaces.container.IAdding"
+     action="RoleService"
+     title="Role Service" />
+
+  <icon
+      name="zmi_icon" 
+      for=".role.ILocalRoleService"
+      file="role_service.gif" />
+
+  <pages 
+     permission="zope.ManageServices" 
+     for=".role.IRoleService"
+     class=".browser.Contents">
+
+     <page name="index.html" attribute="contents"
+           menu="zmi_views" title="Contents" />
+     <page name="removeObjects.html" attribute="removeObjects" />
+
+  </pages>
+
+  <pages 
+     permission="zope.ManageServices" 
+     for=".role.IRoleService"
+     class=".browser.Add">
+
+    <page name="+" template="addrole.pt" 
+          menu="zmi_actions" title="Add" />
+    <page name="action.html" attribute="action" />
+
+  </pages>
+
+</zope:configure>


=== Zope3/src/zope/products/securitypolicy/configure.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/configure.zcml	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,88 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+  <include file="meta.zcml"/>
+
+  <content class=".permissionroles.PermissionRoles">
+    <require
+        permission="zope.Security"
+        attributes="roles rolesInfo"
+        interface=".interfaces.IRegisteredObject" />
+  </content>
+
+  <content class=".rolepermission.RolePermissions">
+    <require
+        permission="zope.Security"
+        attributes="permissions permissionsInfo"
+        interface=".interfaces.IRegisteredObject" />
+    </content>
+
+  <adapter 
+      factory=".rolepermission.AnnotationRolePermissionManager"
+      provides=".interfaces.IRolePermissionManager"
+      for="zope.app.interfaces.annotation.IAnnotatable" />
+
+  <adapter 
+      factory=".principalrole.AnnotationPrincipalRoleManager"
+      provides=".interfaces.IPrincipalRoleManager"
+      for="zope.app.interfaces.annotation.IAnnotatable" />
+
+  <adapter 
+      factory=".principalpermission.AnnotationPrincipalPermissionManager"
+      provides=".interfaces.IPrincipalPermissionManager"
+      for="zope.app.interfaces.annotation.IAnnotatable" />
+
+  <serviceType
+      id="Roles" 
+      interface=".interfaces.IRoleService" />
+
+  <service
+      serviceType="Roles" 
+      component=".roleregistry.roleRegistry" />
+
+  <!-- protect Roles and Permissions -->
+  <content class=".roleregistry.Role">
+    <allow interface=".interfaces.IRegisteredObject" />
+  </content>
+
+<!-- XXX (this came out of services/configure.zcml) Role Templates -->
+
+<content class=".role.RoleService">
+  <factory
+      id="RoleService"
+      permission="zope.ManageServices"
+      />
+  <require
+      permission="zope.Security"
+      interface=".interfaces.IRoleService"
+      />
+  <require
+      permission="zope.ManageServices"
+      interface="zope.app.interfaces.container.IContainer"
+      />
+</content>
+
+<content class=".role.Role">
+  <factory />
+  <require
+      permission="zope.Security"
+      interface=".interfaces.IRole"
+      />
+</content>
+
+<!-- create module aliases for users of persistent objects moved
+     during the course of refactoring  -->
+
+<modulealias module=".securitymap"
+             alias="zope.app.security.grants.securitymap"/>
+
+<modulealias module=".role"
+             alias="zope.app.services.role" />
+
+<securityPolicy
+    component=".zopepolicy.zopeSecurityPolicy" 
+    />
+
+<include package=".browser"/>
+
+</configure>
+


=== Zope3/src/zope/products/securitypolicy/interfaces.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/interfaces.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,229 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Security map to hold matrix-like relationships."""
+
+from zope.interface import Interface
+from zope.app.interfaces.security import IRegisteredObject
+
+class ISecurityMap(Interface):
+    """Security map to hold matrix-like relationships."""
+
+    def addCell(rowentry, colentry, value):
+        " add a cell "
+
+    def delCell(rowentry, colentry):
+        " delete a cell "
+
+    # XXX queryCell / getCell ?
+    def getCell(rowentry, colentry, default=None):
+        " return the value of a cell by row, entry "
+
+    def getRow(rowentry):
+        " return a list of (colentry, value) tuples from a row "
+
+    def getCol(colentry):
+        " return a list of (rowentry, value) tuples from a col "
+
+    def getAllCells():
+        " return a list of (rowentry, colentry, value) "
+
+class IRole(IRegisteredObject):
+    """A role object."""
+
+class IRoleService(Interface):
+    """Define roles
+
+     'IRoleService' objects are used to implement role-definition
+     services. Because they implement services, they are expected to
+     collaborate with services in other contexts. Client code doesn't
+     sarch a context and call multiple services. Instead, client code
+     will call the most specific service in a place and rely on the
+     service to delegate to other services as necessary.
+
+     The interface doesn't include methods for data
+     management. Services may use external data and not allow
+     management in Zope. Simularly, the data to be managed may vary
+     with different implementations of a service.
+     """
+
+    def getRole(rid):
+        """Return an 'IRole' object for the given role id."""
+
+
+    def getRoles():
+        """Return a sequence of the roles (IRole objects)
+        defined in the place containing the service."""
+
+
+
+
+class IPrincipalRoleMap(Interface):
+    """Mappings between principals and roles."""
+
+    def getPrincipalsForRole(role_id):
+        """Get the principals that have been granted a role.
+
+        Return the list of (principal id, setting) who have been assigned or
+        removed from a role.
+
+        If no principals have been assigned this role,
+        then the empty list is returned.
+        """
+
+    def getRolesForPrincipal(principal_id):
+        """Get the roles granted to a principal.
+
+        Return the list of (role id, setting) assigned or removed from
+        this principal.
+
+        If no roles have been assigned to
+        this principal, then the empty list is returned.
+        """
+
+    def getSetting(role_id, principal_id):
+        """Return the setting for this principal, role combination
+        """
+
+    def getPrincipalsAndRoles():
+        """Get all settings.
+
+        Return all the principal/role combinations along with the
+        setting for each combination as a sequence of tuples with the
+        role id, principal id, and setting, in that order.
+        """
+
+
+class IPrincipalRoleManager(IPrincipalRoleMap):
+    """Management interface for mappings between principals and roles."""
+
+    def assignRoleToPrincipal(role_id, principal_id):
+        """Assign the role to the principal."""
+
+    def removeRoleFromPrincipal(role_id, principal_id):
+        """Remove a role from the principal."""
+
+    def unsetRoleForPrincipal(role_id, principal_id):
+        """Unset the role for the principal."""
+
+
+class IRolePermissionMap(Interface):
+    """Mappings between roles and permissions."""
+
+    def getPermissionsForRole(role_id):
+        """Get the premissions granted to a role.
+
+        Return a sequence of (permission id, setting) tuples for the given
+        role.
+
+        If no permissions have been granted to this
+        role, then the empty list is returned.
+        """
+
+    def getRolesForPermission(permission_id):
+        """Get the roles that have a permission.
+
+        Return a sequence of (role id, setting) tuples for the given
+        permission.
+
+        If no roles have been granted this permission, then the empty list is
+        returned.
+        """
+
+    def getSetting(permission_id, role_id):
+        """Return the setting for the given permission id and role id
+
+        If there is no setting, Unset is returned
+        """
+
+    def getRolesAndPermissions():
+        """Return a sequence of (permission_id, role_id, setting) here.
+
+        The settings are returned as a sequence of permission, role,
+        setting tuples.
+
+        If no principal/role assertions have been made here, then the empty
+        list is returned.
+        """
+
+
+class IRolePermissionManager(IRolePermissionMap):
+    """Management interface for mappings between roles and permissions."""
+
+    def grantPermissionToRole(permission_id, role_id):
+        """Bind the permission to the role.
+        """
+
+    def denyPermissionToRole(permission_id, role_id):
+        """Deny the permission to the role
+        """
+
+    def unsetPermissionFromRole(permission_id, role_id):
+        """Clear the setting of the permission to the role.
+        """
+
+
+class IPrincipalPermissionMap(Interface):
+    """Mappings between principals and permissions."""
+
+    def getPrincipalsForPermission(permission_id):
+        """Get the principas that have a permission.
+
+        Return the list of (principal_id, setting) tuples that describe
+        security assertions for this permission.
+
+        If no principals have been set for this permission, then the empty
+        list is returned.
+        """
+
+    def getPermissionsForPrincipal(principal_id):
+        """Get the permissions granted to a principal.
+
+        Return the list of (permission, setting) tuples that describe
+        security assertions for this principal.
+
+        If no permissions have been set for this principal, then the empty
+        list is returned.
+        """
+
+    def getSetting(permission_id, principal_id):
+        """Get the setting for a permission and principal.
+
+        Get the setting (Allow/Deny/Unset) for a given permission and
+        principal.
+        """
+
+    def getPrincipalsAndPermissions():
+        """Get all principal permission settings.
+
+        Get the principal security assertions here in the form
+        of a list of three tuple containing
+        (permission id, principal id, setting)
+        """
+
+
+class IPrincipalPermissionManager(IPrincipalPermissionMap):
+    """Management interface for mappings between principals and permissions."""
+
+    def grantPermissionToPrincipal(permission_id, principal_id):
+        """Assert that the permission is allowed for the principal.
+        """
+
+    def denyPermissionToPrincipal(permission_id, principal_id):
+        """Assert that the permission is denied to the principal.
+        """
+
+    def unsetPermissionForPrincipal(permission_id, principal_id):
+        """Remove the permission (either denied or allowed) from the
+        principal.
+        """


=== Zope3/src/zope/products/securitypolicy/meta.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/meta.zcml	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,17 @@
+<configure 
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+
+  <meta:directive 
+      namespace="http://namespaces.zope.org/zope"
+      name="grant" 
+      schema=".metadirectives.IGrantDirective"
+      handler=".metaconfigure.grant" />
+
+  <meta:directive 
+      namespace="http://namespaces.zope.org/zope"
+      name="role"
+      schema=".metadirectives.IDefineRoleDirective"
+      handler=".metaconfigure.defineRole" />
+
+</configure>


=== Zope3/src/zope/products/securitypolicy/metaconfigure.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/metaconfigure.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+""" Register security related configuration directives.
+
+$Id$
+"""
+from zope.products.securitypolicy.rolepermission \
+     import rolePermissionManager as role_perm_mgr
+from zope.products.securitypolicy.principalpermission \
+     import principalPermissionManager as principal_perm_mgr
+from zope.products.securitypolicy.principalrole \
+     import principalRoleManager as principal_role_mgr
+from zope.configuration.exceptions import ConfigurationError
+from zope.products.securitypolicy.roleregistry import roleRegistry as role_reg
+
+
+def grant(_context, principal=None, role=None, permission=None):
+    if (  (principal is not None)
+        + (role is not None)
+        + (permission is not None)
+          ) != 2:
+        raise ConfigurationError(
+            "Exactly two of the principal, role, and permission attributes "
+            "must be specified")
+
+    if principal:
+        if role:
+            _context.action(
+                discriminator = ('grantRoleToPrincipal', role, principal),
+                callable = principal_role_mgr.assignRoleToPrincipal,
+                args = (role, principal) )
+
+        if permission:
+            _context.action(
+                discriminator = ('grantPermissionToPrincipal',
+                                 permission,
+                                 principal),
+                callable = principal_perm_mgr.grantPermissionToPrincipal,
+                args = (permission, principal) )
+    else:
+        _context.action(
+            discriminator = ('grantPermissionToRole', permission, role),
+            callable = role_perm_mgr.grantPermissionToRole,
+            args = (permission, role) )
+
+def defineRole(_context, id, title, description=''):
+    _context.action(
+            discriminator = ('defineRole', id),
+            callable = role_reg.defineRole,
+            args = (id, title, description) )
+


=== Zope3/src/zope/products/securitypolicy/metadirectives.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/metadirectives.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Grant Directive Schema
+
+$Id$
+"""
+from zope.interface import Interface
+from zope.schema import Id 
+from zope.app.security.registries.metadirectives import IBaseDefineDirective
+
+class IGrantDirective(Interface):
+    """Grant Permissions to roles and principals and roles to principals."""
+
+    principal = Id(
+        title=u"Principal",
+        description=u"Specifies the Principal to be mapped.",
+        required=False)
+
+    permission = Id(
+        title=u"Permission",
+        description=u"Specifies the Permission to be mapped.",
+        required=False)
+
+    role = Id(
+        title=u"Role",
+        description=u"Specifies the Role to be mapped.",
+        required=False)
+
+class IDefineRoleDirective(IBaseDefineDirective):
+    """Define a new role."""
+


=== Zope3/src/zope/products/securitypolicy/permissionroles.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/permissionroles.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,53 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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 getAdapter
+from zope.products.securitypolicy.interfaces import IRolePermissionManager
+from zope.app.interfaces.security import IPermission
+from zope.app.security.settings import Unset
+from zope.interface import implements
+
+class PermissionRoles:
+
+    implements(IPermission)
+
+    def __init__(self, permission, context, roles):
+        self._permission = permission
+        self._context    = context
+        self._roles      = roles
+
+    def getId(self):
+        return self._permission.getId()
+
+    def getTitle(self):
+        return self._permission.getTitle()
+
+    def getDescription(self):
+        return self._permission.getDescription()
+
+    def roleSettings(self):
+        """
+        Returns the list of setting names of each role for this permission.
+        """
+        prm = getAdapter(self._context, IRolePermissionManager)
+        proles = prm.getRolesForPermission(self._permission.getId())
+        settings = {}
+        for role, setting in proles:
+            settings[role] = setting.getName()
+        nosetting = Unset.getName()
+        return [settings.get(role.getId(), nosetting) for role in self._roles]


=== Zope3/src/zope/products/securitypolicy/principalpermission.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/principalpermission.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,163 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Mappings between principals and permissions, stored in an object locally."""
+
+from zope.component import getAdapter
+
+from zope.interface import implements
+from zope.app.interfaces.annotation import IAnnotations
+from zope.products.securitypolicy.interfaces import IPrincipalPermissionManager
+
+from zope.app.security.settings import Allow, Deny, Unset
+from zope.app.security.principal import checkPrincipal
+from zope.app.security.permission import checkPermission
+
+from zope.products.securitypolicy.securitymap import SecurityMap
+
+annotation_key = 'zopel.app.security.AnnotationPrincipalPermissionManager'
+
+class AnnotationPrincipalPermissionManager:
+    """Mappings between principals and permissions."""
+
+    implements(IPrincipalPermissionManager)
+
+    def __init__(self, context):
+        self._context = context
+
+    def grantPermissionToPrincipal(self, permission_id, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        pp = self._getPrincipalPermissions(create=1)
+        pp.addCell(permission_id, principal_id, Allow)
+        self._context._p_changed = 1
+
+    def denyPermissionToPrincipal(self, permission_id, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        pp = self._getPrincipalPermissions(create=1)
+        pp.addCell(permission_id, principal_id, Deny)
+        self._context._p_changed = 1
+
+    def unsetPermissionForPrincipal(self, permission_id, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        pp = self._getPrincipalPermissions()
+        # Only unset if there is a security map, otherwise, we're done
+        if pp:
+            pp.delCell(permission_id, principal_id)
+            self._context._p_changed = 1
+
+    def getPrincipalsForPermission(self, permission_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        pp = self._getPrincipalPermissions()
+        if pp:
+            return pp.getRow(permission_id)
+        return []
+
+    def getPermissionsForPrincipal(self, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        pp = self._getPrincipalPermissions()
+        if pp:
+            return pp.getCol(principal_id)
+        return []
+
+    def getSetting(self, permission_id, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        pp = self._getPrincipalPermissions()
+        if pp:
+            return pp.getCell(permission_id, principal_id, default=Unset)
+        return []
+
+    def getPrincipalsAndPermissions(self):
+        ''' See the interface IPrincipalPermissionManager '''
+        pp = self._getPrincipalPermissions()
+        if pp:
+            return pp.getAllCells()
+        return []
+
+    # Implementation helpers
+
+    def _getPrincipalPermissions(self, create=0):
+        """ Get the principal permission map stored in the context, optionally
+            creating one if necessary """
+        # need to remove security proxies here, otherwise we enter
+        # an infinite loop, becuase checking security depends on
+        # getting PrincipalPermissions.
+        from zope.proxy import removeAllProxies
+        context = removeAllProxies(self._context)
+        annotations = getAdapter(context, IAnnotations)
+        try:
+            return annotations[annotation_key]
+        except KeyError:
+            if create:
+                rp = annotations[annotation_key] = SecurityMap()
+                return rp
+        return None
+
+
+class PrincipalPermissionManager(SecurityMap):
+    """Mappings between principals and permissions."""
+
+    implements(IPrincipalPermissionManager)
+
+    def grantPermissionToPrincipal(self, permission_id, principal_id,
+                                   check=True):
+        ''' See the interface IPrincipalPermissionManager '''
+
+        if check:
+            checkPermission(None, permission_id)
+            checkPrincipal(None, principal_id)
+
+        self.addCell(permission_id, principal_id, Allow)
+
+    def denyPermissionToPrincipal(self, permission_id, principal_id,
+                                  check=True):
+        ''' See the interface IPrincipalPermissionManager '''
+
+        if check:
+            checkPermission(None, permission_id)
+            checkPrincipal(None, principal_id)
+
+        self.addCell(permission_id, principal_id, Deny)
+
+    def unsetPermissionForPrincipal(self, permission_id, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+
+        # Don't check validity intentionally.
+        # After all, we certianly want to unset invalid ids.
+
+        self.delCell(permission_id, principal_id)
+
+    def getPrincipalsForPermission(self, permission_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        return self.getRow(permission_id)
+
+    def getPermissionsForPrincipal(self, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        return self.getCol(principal_id)
+
+    def getSetting(self, permission_id, principal_id):
+        ''' See the interface IPrincipalPermissionManager '''
+        return self.getCell(permission_id, principal_id, default=Unset)
+
+    def getPrincipalsAndPermissions(self):
+        ''' See the interface IPrincipalPermissionManager '''
+        return self.getAllCells()
+
+
+# Permissions are our rows, and principals are our columns
+principalPermissionManager = PrincipalPermissionManager()
+
+
+# Register our cleanup with Testing.CleanUp to make writing unit tests simpler.
+from zope.testing.cleanup import addCleanUp
+addCleanUp(principalPermissionManager._clear)
+del addCleanUp


=== Zope3/src/zope/products/securitypolicy/principalrole.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/principalrole.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,157 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Mappings between principals and roles, stored in an object locally."""
+
+from zope.component import getAdapter
+from zope.interface import implements
+
+from zope.security.proxy import trustedRemoveSecurityProxy
+
+from zope.app.interfaces.annotation import IAnnotations
+from zope.products.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.products.securitypolicy.interfaces import IPrincipalRoleMap
+
+from zope.app.security.settings import Allow, Deny, Unset
+from zope.products.securitypolicy.securitymap import SecurityMap
+from zope.products.securitypolicy.securitymap import PersistentSecurityMap
+
+from zope.app.security.principal import checkPrincipal
+from zope.products.securitypolicy.role import checkRole
+
+annotation_key = 'zope.app.security.AnnotationPrincipalRoleManager'
+
+class AnnotationPrincipalRoleManager:
+    """Mappings between principals and roles."""
+
+    implements(IPrincipalRoleManager)
+
+    def __init__(self, context):
+        self._context = context
+
+    def assignRoleToPrincipal(self, role_id, principal_id):
+        ''' See the interface IPrincipalRoleManager '''
+        pp = self._getPrincipalRoles(create=1)
+        pp.addCell(role_id, principal_id, Allow)
+
+    def removeRoleFromPrincipal(self, role_id, principal_id):
+        ''' See the interface IPrincipalRoleManager '''
+        pp = self._getPrincipalRoles(create=1)
+        pp.addCell(role_id, principal_id, Deny)
+
+    def unsetRoleForPrincipal(self, role_id, principal_id):
+        ''' See the interface IPrincipalRoleManager '''
+        pp = self._getPrincipalRoles()
+        # Only unset if there is a security map, otherwise, we're done
+        if pp:
+            pp.delCell(role_id, principal_id)
+
+    def getPrincipalsForRole(self, role_id):
+        ''' See the interface IPrincipalRoleManager '''
+        pp = self._getPrincipalRoles()
+        if pp:
+            return pp.getRow(role_id)
+        return []
+
+    def getRolesForPrincipal(self, principal_id):
+        ''' See the interface IPrincipalRoleManager '''
+        pp = self._getPrincipalRoles()
+        if pp:
+            return pp.getCol(principal_id)
+        return []
+
+    def getSetting(self, role_id, principal_id):
+        ''' See the interface IPrincipalRoleManager '''
+        pp = self._getPrincipalRoles()
+        if pp:
+            return pp.getCell(role_id, principal_id, default=Unset)
+        return Unset
+
+    def getPrincipalsAndRoles(self):
+        ''' See the interface IPrincipalRoleManager '''
+        pp = self._getPrincipalRoles()
+        if pp:
+            return pp.getAllCells()
+        return []
+
+    # Implementation helpers
+
+    def _getPrincipalRoles(self, create=0):
+        """ Get the principal role map stored in the context, optionally
+            creating one if necessary """
+        annotations = getAdapter(self._context, IAnnotations)
+        try:
+            # there's a chance that annotations is security proxied -
+            # remove proxy to avoid authentication failure on role lookup
+            return trustedRemoveSecurityProxy(annotations)[annotation_key]
+        except KeyError:
+            if create:
+                rp = annotations[annotation_key] = PersistentSecurityMap()
+                return rp
+        return None
+
+
+class PrincipalRoleManager(SecurityMap):
+    """Mappings between principals and roles."""
+
+    implements(IPrincipalRoleManager, IPrincipalRoleMap)
+
+    def assignRoleToPrincipal(self, role_id, principal_id, check=True):
+        ''' See the interface IPrincipalRoleManager '''
+
+        if check:
+            checkPrincipal(None, principal_id)
+            checkRole(None, role_id)
+
+        self.addCell(role_id, principal_id, Allow)
+
+    def removeRoleFromPrincipal(self, role_id, principal_id, check=True):
+        ''' See the interface IPrincipalRoleManager '''
+
+        if check:
+            checkPrincipal(None, principal_id)
+            checkRole(None, role_id)
+
+        self.addCell(role_id, principal_id, Deny)
+
+    def unsetRoleForPrincipal(self, role_id, principal_id):
+        ''' See the interface IPrincipalRoleManager '''
+
+        # Don't check validity intentionally.
+        # After all, we certianly want to unset invalid ids.
+
+        self.delCell(role_id, principal_id)
+
+    def getPrincipalsForRole(self, role_id):
+        ''' See the interface IPrincipalRoleMap '''
+        return self.getRow(role_id)
+
+    def getRolesForPrincipal(self, principal_id):
+        ''' See the interface IPrincipalRoleMap '''
+        return self.getCol(principal_id)
+
+    def getSetting(self, role_id, principal_id):
+        ''' See the interface IPrincipalRoleMap '''
+        return self.getCell(role_id, principal_id, default=Unset)
+
+    def getPrincipalsAndRoles(self):
+        ''' See the interface IPrincipalRoleMap '''
+        return self.getAllCells()
+
+# Roles are our rows, and principals are our columns
+principalRoleManager = PrincipalRoleManager()
+
+# Register our cleanup with Testing.CleanUp to make writing unit tests simpler.
+from zope.testing.cleanup import addCleanUp
+addCleanUp(principalRoleManager._clear)
+del addCleanUp


=== Zope3/src/zope/products/securitypolicy/role.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/role.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,61 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from persistence import Persistent
+from zope.products.securitypolicy.roleregistry import Role
+from zope.app.container.btree import BTreeContainer
+from zope.products.securitypolicy.interfaces import IRoleService
+from zope.app.interfaces.container import IContainer
+from zope.app.component.nextservice import getNextService
+from zope.app.interfaces.services.service import ISimpleService
+from zope.interface import implements
+from zope.component import getService
+
+class Role(Role, Persistent):
+    "Persistent Role"
+
+class ILocalRoleService(IRoleService, IContainer):
+    """TTW manageable role service"""
+
+class RoleService(BTreeContainer):
+
+    implements(ILocalRoleService, ISimpleService)
+
+    def getRole(wrapped_self, rid):
+        '''See interface IRoleService'''
+        try:
+            return wrapped_self[rid]
+        except KeyError:
+            # We failed locally: delegate to a higher-level service.
+            sv = getNextService(wrapped_self, 'Roles')
+            if sv:
+                return sv.getRole(rid)
+            raise # will be original Key Error
+
+    def getRoles(wrapped_self):
+        '''See interface IRoleService'''
+        roles = list(wrapped_self.values())
+        roleserv = getNextService(wrapped_self, 'Roles')
+        if roleserv:
+            roles.extend(roleserv.getRoles())
+        return roles
+
+def checkRole(context, role_id):
+    if not getService(context, 'Roles').getRole(role_id):
+        raise ValueError("Undefined role id", role_id)


=== Zope3/src/zope/products/securitypolicy/rolepermission.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/rolepermission.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,206 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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 getAdapter
+from zope.interface import implements
+
+from zope.app.interfaces.annotation import IAnnotations
+
+from zope.app.security.settings import Allow, Deny, Unset
+from zope.products.securitypolicy.role import checkRole
+from zope.app.security.permission import checkPermission
+
+from zope.products.securitypolicy.interfaces import IRolePermissionManager
+from zope.products.securitypolicy.interfaces import IRole
+from zope.products.securitypolicy.interfaces import IRolePermissionMap
+from zope.products.securitypolicy.securitymap import PersistentSecurityMap
+from zope.products.securitypolicy.securitymap import SecurityMap
+
+# the annotation_key is a holdover from this module's old location, but cannot
+# change without breaking existing databases
+annotation_key = 'zope.app.security.AnnotationRolePermissionManager'
+
+class AnnotationRolePermissionManager:
+    """
+    provide adapter that manages role permission data in an object attribute
+    """
+
+    implements(IRolePermissionManager, IRolePermissionMap)
+
+    def __init__(self, context):
+        self._context = context
+
+    def grantPermissionToRole(self, permission_id, role_id):
+        ''' See the interface IRolePermissionManager '''
+        rp = self._getRolePermissions(create=1)
+        rp.addCell(permission_id, role_id, Allow)
+        # probably not needed, as annotations should manage
+        # their own persistence
+        #self._context._p_changed = 1
+
+    def denyPermissionToRole(self, permission_id, role_id):
+        ''' See the interface IRolePermissionManager '''
+        rp = self._getRolePermissions(create=1)
+        rp.addCell(permission_id, role_id, Deny)
+        # probably not needed, as annotations should manage
+        # their own persistence
+        #self._context._p_changed = 1
+
+    def unsetPermissionFromRole(self, permission_id, role_id):
+        ''' See the interface IRolePermissionManager '''
+        rp = self._getRolePermissions()
+        # Only unset if there is a security map, otherwise, we're done
+        if rp:
+            rp.delCell(permission_id, role_id)
+            # probably not needed, as annotations should manage
+            # their own persistence
+            #self._context._p_changed = 1
+
+    def getRolesForPermission(self, permission_id):
+        '''See interface IRolePermissionMap'''
+        rp = self._getRolePermissions()
+        if rp:
+            return rp.getRow(permission_id)
+        else:
+            return []
+
+    def getPermissionsForRole(self, role_id):
+        '''See interface IRolePermissionMap'''
+        rp = self._getRolePermissions()
+        if rp:
+            return rp.getCol(role_id)
+        else:
+            return []
+
+    def getRolesAndPermissions(self):
+        '''See interface IRolePermissionMap'''
+        rp = self._getRolePermissions()
+        if rp:
+            return rp.getAllCells()
+        else:
+            return []
+
+    def getSetting(self, permission_id, role_id):
+        '''See interface IRolePermissionMap'''
+        rp = self._getRolePermissions()
+        if rp:
+            return rp.getCell(permission_id, role_id)
+        else:
+            return Unset
+
+    def _getRolePermissions(self, create=0):
+        """Get the role permission map stored in the context, optionally
+           creating one if necessary"""
+        # need to remove security proxies here, otherwise we enter
+        # an infinite loop, becuase checking security depends on
+        # getting RolePermissions.
+        from zope.proxy import removeAllProxies
+        context = removeAllProxies(self._context)
+        annotations = getAdapter(context, IAnnotations)
+        try:
+            return annotations[annotation_key]
+        except KeyError:
+            if create:
+                rp = annotations[annotation_key] = PersistentSecurityMap()
+                return rp
+        return None
+
+class RolePermissions:
+
+    implements(IRole)
+
+    def __init__(self, role, context, permissions):
+        self._role = role
+        self._context = context
+        self._permissions = permissions
+
+    def getId(self):
+        return self._role.getId()
+
+    def getTitle(self):
+        return self._role.getTitle()
+
+    def getDescription(self):
+        return self._role.getDescription()
+
+    def permissionsInfo(self):
+        prm = getAdapter(self._context, IRolePermissionManager)
+        rperms = prm.getPermissionsForRole(self._role.getId())
+        settings = {}
+        for permission, setting in rperms:
+            settings[permission] = setting.getName()
+        nosetting = Unset.getName()
+        return [{'id': permission.getId(),
+                 'title': permission.getTitle(),
+                 'setting': settings.get(permission.getId(), nosetting)}
+                for permission in self._permissions]
+
+
+class RolePermissionManager(SecurityMap):
+    """Mappings between roles and permissions."""
+
+    implements(IRolePermissionManager)
+
+    def grantPermissionToRole(self, permission_id, role_id, check=True):
+        '''See interface IRolePermissionMap'''
+
+        if check:
+            checkRole(None, role_id)
+            checkPermission(None, permission_id)
+
+        self.addCell(permission_id, role_id, Allow)
+
+    def denyPermissionToRole(self, permission_id, role_id, check=True):
+        '''See interface IRolePermissionMap'''
+
+        if check:
+            checkRole(None, role_id)
+            checkPermission(None, permission_id)
+
+        self.addCell(permission_id, role_id, Deny)
+
+    def unsetPermissionFromRole(self, permission_id, role_id):
+        '''See interface IRolePermissionMap'''
+
+        # Don't check validity intentionally.
+        # After all, we certianly want to unset invalid ids.
+
+        self.delCell(permission_id, role_id)
+
+    def getRolesForPermission(self, permission_id):
+        '''See interface IRolePermissionMap'''
+        return self.getRow(permission_id)
+
+    def getPermissionsForRole(self, role_id):
+        '''See interface IRolePermissionMap'''
+        return self.getCol(role_id)
+
+    def getSetting(self, permission_id, role_id):
+        '''See interface IRolePermissionMap'''
+        return self.getCell(permission_id, role_id)
+
+    def getRolesAndPermissions(self):
+        '''See interface IRolePermissionMap'''
+        return self.getAllCells()
+
+# Permissions are our rows, and roles are our columns
+rolePermissionManager = RolePermissionManager()
+
+# Register our cleanup with Testing.CleanUp to make writing unit tests simpler.
+from zope.testing.cleanup import addCleanUp
+addCleanUp(rolePermissionManager._clear)
+del addCleanUp


=== Zope3/src/zope/products/securitypolicy/roleregistry.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/roleregistry.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Global role registry."""
+
+PREFIX = 'Global Role'
+
+from zope.app.security.registries.registeredobject import RegisteredObject
+from zope.app.security.registries.registry import Registry
+from zope.products.securitypolicy.interfaces import IRole
+from zope.products.securitypolicy.interfaces import IRoleService
+from zope.app.interfaces.services.service import ISimpleService
+from zope.interface import implements
+
+class Role(RegisteredObject):
+    implements(IRole)
+
+
+class RoleRegistry(Registry):
+    implements(IRoleService, ISimpleService)
+
+    def __init__(self, prefix=PREFIX):
+        Registry.__init__(self, Role)
+        self._prefix = prefix
+
+    def _make_global_id(self, suffix):
+        return self._prefix + '.' + suffix
+
+    def defineRole(self, role, title, description=None):
+        """Define a new role object, register, and return it.
+
+        role is the role name.
+
+        title is the role title, human readable.
+
+        description (optional) is human readable
+        """
+        if description is None:
+            description = ''
+        id = role
+        return self.register(id, title, description)
+
+    def definedRole(self, id):
+        """Return true if named role is registered, otherwise return false
+        """
+        return self.is_registered(id)
+
+    def getRole(self, id):
+        """Return role object registered as name.
+
+        If no named role is registered KeyError is raised.
+        """
+        return self.getRegisteredObject(id)
+
+    def getRoles(self):
+        """Return all registered role objects.
+        """
+        return self.getRegisteredObjects()
+
+    def _clear(self):
+        # Standard roles
+        Registry._clear(self)
+        self.register("zope.Anonymous", "Everybody",
+                      "All users have this role implicitly")
+
+roleRegistry = RoleRegistry()
+
+
+# Register our cleanup with Testing.CleanUp to make writing unit tests simpler.
+from zope.testing.cleanup import addCleanUp
+addCleanUp(roleRegistry._clear)
+del addCleanUp


=== Zope3/src/zope/products/securitypolicy/securitymap.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/securitymap.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,88 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+""" Generic two-dimensional array type """
+
+from persistence import Persistent
+from persistence.dict import PersistentDict
+from zope.interface import implements
+from zope.products.securitypolicy.interfaces import ISecurityMap
+
+class SecurityMap(object):
+
+    implements(ISecurityMap)
+
+    def __init__(self):
+        self._clear()
+
+    def _clear(self):
+        self._byrow = {}
+        self._bycol = {}
+
+    def _empty_mapping(self):
+        return {}
+
+    def addCell(self, rowentry, colentry, value):
+        # setdefault may get expensive if an empty mapping is
+        # expensive to create, for PersistentDict for instance.
+        row = self._byrow.setdefault(rowentry, self._empty_mapping())
+        row[colentry] = value
+
+        col = self._bycol.setdefault(colentry, self._empty_mapping())
+        col[rowentry] = value
+
+    def delCell(self, rowentry, colentry):
+        row = self._byrow.get(rowentry)
+        if row and (colentry in row):
+            del self._byrow[rowentry][colentry]
+            del self._bycol[colentry][rowentry]
+
+    def getCell(self, rowentry, colentry, default=None):
+        " return the value of a cell by row, entry "
+        row = self._byrow.get(rowentry)
+        if row: return row.get(colentry, default)
+        else: return default
+
+    def getRow(self, rowentry):
+        " return a list of (colentry, value) tuples from a row "
+        row = self._byrow.get(rowentry)
+        if row:
+            return row.items()
+        else: return []
+
+    def getCol(self, colentry):
+        " return a list of (rowentry, value) tuples from a col "
+        col = self._bycol.get(colentry)
+        if col:
+            return col.items()
+        else: return []
+
+    def getAllCells(self):
+        " return a list of (rowentry, colentry, value) "
+        res = []
+        for r in self._byrow.keys():
+            for c in self._byrow[r].items():
+                res.append((r,) + c)
+        return res
+
+
+class PersistentSecurityMap(SecurityMap, Persistent):
+
+    implements(ISecurityMap)
+
+    def _clear(self):
+        self._byrow = PersistentDict()
+        self._bycol = PersistentDict()
+
+    def _empty_mapping(self):
+        return PersistentDict()


=== Zope3/src/zope/products/securitypolicy/zopepolicy.py 1.1 => 1.2 ===
--- /dev/null	Wed Jan 14 17:56:03 2004
+++ Zope3/src/zope/products/securitypolicy/zopepolicy.py	Wed Jan 14 17:55:32 2004
@@ -0,0 +1,291 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+""" Define Zope\'s default security policy
+
+$Id$
+"""
+__version__='$Revision$'[11:-2]
+
+from zope.component import queryAdapter
+from zope.app.location import LocationIterator
+
+from zope.security.interfaces import ISecurityPolicy
+from zope.security.management import system_user
+
+from zope.products.securitypolicy.interfaces import \
+     IRolePermissionMap, IPrincipalPermissionMap, IPrincipalRoleMap
+from zope.products.securitypolicy.principalpermission \
+     import principalPermissionManager
+from zope.products.securitypolicy.rolepermission import rolePermissionManager
+from zope.products.securitypolicy.principalrole import principalRoleManager
+from zope.app.security.settings import Allow, Deny
+from zope.interface import implements
+
+getPermissionsForPrincipal = \
+                principalPermissionManager.getPermissionsForPrincipal
+getPermissionsForRole = rolePermissionManager.getPermissionsForRole
+getRolesForPrincipal = principalRoleManager.getRolesForPrincipal
+
+globalContext = object()
+
+
+class ZopeSecurityPolicy:
+
+    implements(ISecurityPolicy)
+
+    def __init__(self, ownerous=True, authenticated=True):
+        """
+            Two optional keyword arguments may be provided:
+
+            ownerous -- Untrusted users can create code
+                (e.g. Python scripts or templates),
+                so check that code owners can access resources.
+                The argument must have a truth value.
+                The default is true.
+
+            authenticated -- Allow access to resources based on the
+                privileges of the authenticated user.
+                The argument must have a truth value.
+                The default is true.
+
+                This (somewhat experimental) option can be set
+                to false on sites that allow only public
+                (unauthenticated) access. An anticipated
+                scenario is a ZEO configuration in which some
+                clients allow only public access and other
+                clients allow full management.
+        """
+
+        self._ownerous = ownerous
+        self._authenticated = authenticated
+
+    def checkPermission(self, permission, object, context):
+        # XXX We aren't really handling multiple principals yet
+
+        # mapping from principal to set of roles
+        user = context.user
+        if user is system_user:
+            return True
+
+        roledict = {'zope.Anonymous': Allow}
+        principals = {user.getId() : roledict}
+
+        role_permissions = {}
+        remove = {}
+
+        # Look for placeless grants first.
+
+        # get placeless principal permissions
+        for principal in principals:
+            for principal_permission, setting in (
+                getPermissionsForPrincipal(principal)):
+                if principal_permission == permission:
+                    if setting is Deny:
+                        return False
+                    assert setting is Allow
+                    remove[principal] = True
+
+        # Clean out removed principals
+        if remove:
+            for principal in remove:
+                del principals[principal]
+            if principals:
+                # not done yet
+                remove.clear()
+            else:
+                # we've eliminated all the principals
+                return True
+
+        # get placeless principal roles
+        for principal in principals:
+            roles = principals[principal]
+            for role, setting in getRolesForPrincipal(principal):
+                assert setting in (Allow, Deny)
+                if role not in roles:
+                    roles[role] = setting
+
+        for perm, role, setting in (
+            rolePermissionManager.getRolesAndPermissions()):
+            assert setting in (Allow, Deny)
+            if role not in role_permissions:
+                role_permissions[role] = {perm: setting}
+            else:
+                if perm not in role_permissions[role]:
+                    role_permissions[role][perm] = setting
+
+        # Get principal permissions based on roles
+        for principal in principals:
+            roles = principals[principal]
+            for role, role_setting in roles.items():
+                if role_setting is Deny:
+                    return False
+                if role in role_permissions:
+                    if permission in role_permissions[role]:
+                        setting = role_permissions[role][permission]
+                        if setting is Deny:
+                            return False
+                        remove[principal] = True
+
+
+        # Clean out removed principals
+        if remove:
+            for principal in remove:
+                del principals[principal]
+            if principals:
+                # not done yet
+                remove.clear()
+            else:
+                # we've eliminated all the principals
+                return True
+
+        # Look for placeful grants
+        for place in LocationIterator(object):
+
+            # Copy specific principal permissions
+            prinper = queryAdapter(place, IPrincipalPermissionMap)
+            if prinper is not None:
+                for principal in principals:
+                    for principal_permission, setting in (
+                        prinper.getPermissionsForPrincipal(principal)):
+                        if principal_permission == permission:
+                            if setting is Deny:
+                                return False
+
+                            assert setting is Allow
+                            remove[principal] = True
+
+            # Clean out removed principals
+            if remove:
+                for principal in remove:
+                    del principals[principal]
+                if principals:
+                    # not done yet
+                    remove.clear()
+                else:
+                    # we've eliminated all the principals
+                    return True
+
+            # Collect principal roles
+            prinrole = queryAdapter(place, IPrincipalRoleMap)
+            if prinrole is not None:
+                for principal in principals:
+                    roles = principals[principal]
+                    for role, setting in (
+                        prinrole.getRolesForPrincipal(principal)):
+                        assert setting in (Allow, Deny)
+                        if role not in roles:
+                            roles[role] = setting
+
+            # Collect role permissions
+            roleper = queryAdapter(place, IRolePermissionMap)
+            if roleper is not None:
+                for perm, role, setting in roleper.getRolesAndPermissions():
+                    assert setting in (Allow, Deny)
+                    if role not in role_permissions:
+                        role_permissions[role] = {perm: setting}
+                    else:
+                        if perm not in role_permissions[role]:
+                            role_permissions[role][perm] = setting
+
+            # Get principal permissions based on roles
+            for principal in principals:
+                roles = principals[principal]
+                for role, role_setting in roles.items():
+                    if role_setting is Deny:
+                        return False
+                    if role in role_permissions:
+                        if permission in role_permissions[role]:
+                            setting = role_permissions[role][permission]
+                            if setting is Deny:
+                                return False
+                            remove[principal] = True
+
+            # Clean out removed principals
+            if remove:
+                for principal in remove:
+                    del principals[principal]
+                if principals:
+                    # not done yet
+                    remove.clear()
+                else:
+                    # we've eliminated all the principals
+                    return True
+
+        return False # deny by default
+
+
+def permissionsOfPrincipal(principal, object):
+    permissions = {}
+
+    roles = {'zope.Anonymous': Allow}
+    principalid = principal.getId()
+
+    # Make two passes.
+
+    # First, collect what we know about the principal:
+
+
+    # get placeless principal permissions
+    for permission, setting in getPermissionsForPrincipal(principalid):
+        if permission not in permissions:
+            permissions[permission] = setting
+
+    # get placeless principal roles
+    for role, setting in getRolesForPrincipal(principalid):
+        if role not in roles:
+            roles[role] = setting
+
+    # get placeful principal permissions and roles
+    for place in LocationIterator(object):
+
+        # Copy specific principal permissions
+        prinper = queryAdapter(place, IPrincipalPermissionMap)
+        if prinper is not None:
+            for permission, setting in prinper.getPermissionsForPrincipal(
+                principalid):
+                if permission not in permissions:
+                    permissions[permission] = setting
+
+        # Collect principal roles
+        prinrole = queryAdapter(place, IPrincipalRoleMap)
+        if prinrole is not None:
+            for role, setting in prinrole.getRolesForPrincipal(principalid):
+                if role not in roles:
+                    roles[role] = setting
+
+    # Second, update permissions using principal
+
+    for perm, role, setting in (
+        rolePermissionManager.getRolesAndPermissions()):
+        if role in roles and perm not in permissions:
+            permissions[perm] = setting
+
+    for place in LocationIterator(object):
+
+        # Collect role permissions
+        roleper = queryAdapter(place, IRolePermissionMap)
+        if roleper is not None:
+            for perm, role, setting in roleper.getRolesAndPermissions():
+                if role in roles and perm not in permissions:
+                    permissions[perm] = setting
+
+
+
+    result = [permission
+              for permission in permissions
+              if permissions[permission] is Allow]
+
+    return result
+
+zopeSecurityPolicy=ZopeSecurityPolicy()




More information about the Zope3-Checkins mailing list