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

Steve Alexander steve at cat-box.net
Tue Jan 13 18:34:24 EST 2004


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

Added Files:
      Tag: steveachrismcd-securitypolicy-branch
	__init__.py configure.zcml interfaces.py meta.zcml 
	metaconfigure.py metadirectives.py permissionroles.py 
	principalpermission.py principalrole.py rolepermission.py 
	securitymap.py zopepolicy.py 
Log Message:
Initial move of things related to the security policy.


=== Added File Zope3/src/zope/products/securitypolicy/__init__.py ===
#
# This file is necessary to make this directory a package.


=== Added File Zope3/src/zope/products/securitypolicy/configure.zcml ===
<configure xmlns="http://namespaces.zope.org/zope">

  <content class=".permissionroles.PermissionRoles">
    <require
        permission="zope.Security"
        attributes="roles rolesInfo"
        interface="zope.app.interfaces.security.IRegisteredObject" />
  </content>

  <content class="zope.products.securitypolicy.rolepermission.RolePermissions">
    <require
        permission="zope.Security"
        attributes="permissions permissionsInfo"
        interface="zope.app.interfaces.security.IRegisteredObject" />
    </content>

  <adapter 
      factory=".rolepermission.AnnotationRolePermissionManager"
      provides="zope.app.interfaces.security.IRolePermissionManager"
      for="zope.app.interfaces.annotation.IAnnotatable" />

  <adapter 
      factory=".principalrole.AnnotationPrincipalRoleManager"
      provides="zope.app.interfaces.security.IPrincipalRoleManager"
      for="zope.app.interfaces.annotation.IAnnotatable" />

  <adapter 
      factory=".principalpermission.AnnotationPrincipalPermissionManager"
      provides="zope.app.interfaces.security.IPrincipalPermissionManager"
      for="zope.app.interfaces.annotation.IAnnotatable" />

</configure>



=== Added File Zope3/src/zope/products/securitypolicy/interfaces.py ===
##############################################################################
#
# 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


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) "


=== Added File Zope3/src/zope/products/securitypolicy/meta.zcml ===
<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" />

</configure>


=== Added File Zope3/src/zope/products/securitypolicy/metaconfigure.py ===
##############################################################################
#
# 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: metaconfigure.py,v 1.1.2.1 2004/01/13 23:34:20 stevea Exp $
"""
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


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) )


=== Added File Zope3/src/zope/products/securitypolicy/metadirectives.py ===
##############################################################################
#
# 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: metadirectives.py,v 1.1.2.1 2004/01/13 23:34:20 stevea Exp $
"""
from zope.interface import Interface
from zope.schema import Id 

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)


=== Added File Zope3/src/zope/products/securitypolicy/permissionroles.py ===
##############################################################################
#
# 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: permissionroles.py,v 1.1.2.1 2004/01/13 23:34:20 stevea Exp $
"""

from zope.component import getAdapter
from zope.app.interfaces.security 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]


=== Added File Zope3/src/zope/products/securitypolicy/principalpermission.py ===
##############################################################################
#
# 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.app.interfaces.security 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


=== Added File Zope3/src/zope/products/securitypolicy/principalrole.py ===
##############################################################################
#
# 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.app.interfaces.security import IPrincipalRoleManager
from zope.app.interfaces.security 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.app.security.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


=== Added File Zope3/src/zope/products/securitypolicy/rolepermission.py ===
##############################################################################
#
# 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: rolepermission.py,v 1.1.2.1 2004/01/13 23:34:20 stevea Exp $
"""
from zope.component import getAdapter
from zope.interface import implements

from zope.app.interfaces.annotation import IAnnotations
from zope.app.interfaces.security import IRolePermissionMap
from zope.app.interfaces.security import IRolePermissionManager
from zope.app.interfaces.security import IRole

from zope.app.security.settings import Allow, Deny, Unset
from zope.app.security.role import checkRole
from zope.app.security.permission import checkPermission
from zope.products.securitypolicy.securitymap import PersistentSecurityMap
from zope.products.securitypolicy.securitymap import SecurityMap

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


=== Added File Zope3/src/zope/products/securitypolicy/securitymap.py ===
##############################################################################
#
# 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()


=== Added File Zope3/src/zope/products/securitypolicy/zopepolicy.py ===
##############################################################################
#
# 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: zopepolicy.py,v 1.1.2.1 2004/01/13 23:34:20 stevea Exp $
"""
__version__='$Revision: 1.1.2.1 $'[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.app.interfaces.security 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