The Security Policy
-------------------

The provided security policy is generic, in the sense that it provides
a flexible way to check for permissions on objects, but doesn't
define the application logic which defines how object permissions
are set.

The following example implements a very simple permission checker which
might be used with the security policy to check for roles. Notice that
this is just an example. There's a better base for role-related security
checking.

  >>> from canonical.security.interfaces import (
  ...     IPermissionChecker, IRoleRegistry)
  >>> from canonical.security.role import RoleRegistry, Role
  >>> from zope.interface.verify import verifyObject
  >>> from zope import component, interface

  >>> registry = RoleRegistry()
  >>> role1 = Role("name1")
  >>> role2 = Role("name2")
  >>> registry.add(role1)
  >>> registry.add(role2)
  >>> registry.grant(role1, "perm1")
  >>> registry.grant(role2, "perm2")
  >>> sm = component.getSiteManager()
  >>> sm.registerUtility(registry, IRoleRegistry)


  >>> @interface.implementer(IPermissionChecker)
  ... class PermissionChecker(object):
  ...
  ...     def __init__(self, context, principal):
  ...         self.context = context
  ...         self.principal = principal
  ...
  ...     def __call__(self, perm):
  ...         roles = getattr(self.context, "_roles", ())
  ...         return component.getUtility(IRoleRegistry).may(roles, perm)


  >>> verifyObject(IPermissionChecker, PermissionChecker(None, None))
  True


  >>> class IStub(interface.Interface): pass

  >>> @interface.implementer(IStub)
  ... class Stub(object):
  ...
  ...     def __init__(self, *roles):
  ...         self._roles = roles

  >>> sm.registerAdapter(PermissionChecker, [IStub, interface.Interface])

  >>> obj1 = Stub(role1)
  >>> obj2 = Stub(role2)


That's all that is needed to put the security infrastructure to work. We
can now instantiate the policy, and request authorization.

  >>> from zope.security.testing import Participation, Principal
  >>> from canonical.security.policy import SecurityPolicy

  >>> participation = Participation(Principal("someone"))
  >>> policy = SecurityPolicy(participation)
  >>> policy.checkPermission("perm1", obj1)
  True
  >>> policy.checkPermission("perm2", obj1)
  False
  >>> policy.checkPermission("perm1", obj2)
  False
  >>> policy.checkPermission("perm2", obj2)
  True


The security policy can handle default roles, if nothing else
makes a decision before.

  >>> role3 = Role("name3")
  >>> registry.add(role3, default=True)
  >>> registry.grant(role3, "perm3")

  >>> policy.checkPermission("perm3", obj1)
  True
  >>> policy.checkPermission("perm3", obj2)
  True


As aforementioned, there's a good base to implement role-based
permission checking. It's named RolePermissionChecker.

  >>> from canonical.security.policy import RolePermissionChecker

  >>> class RoleChecker(RolePermissionChecker):
  ...     registry_name = "named_registry"
  ...     def get_roles(self):
  ...         return getattr(self.context, "_roles", ())


  >>> registry = RoleRegistry()
  >>> role3 = Role("name3")
  >>> registry.add(role1)
  >>> registry.add(role2)
  >>> registry.add(role3)
  >>> registry.grant(role1, "perm1")
  >>> registry.grant(role3, "perm3")
  >>> sm.registerUtility(registry, IRoleRegistry, "named_registry")

  >>> obj3 = Stub(role1, role3)

  >>> sm.registerAdapter(RoleChecker, [IStub, interface.Interface])

  >>> policy.checkPermission("perm1", obj3)
  True
  >>> policy.checkPermission("perm2", obj3)
  False
  >>> policy.checkPermission("perm3", obj3)
  True


The RolePermissionChecker also handles default roles.

  >>> role4 = Role("name4")
  >>> registry.add(role4, default=True)
  >>> registry.grant(role4, "perm4")

  >>> policy.checkPermission("perm4", obj3)
  True


vim:ts=4:sw=4:et:ft=doctest
