[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Security - IUser.py:1.1.2.1 SecurityContext.py:1.1.2.1 SecurityManagement.py:1.1.2.1 SecurityManager.py:1.1.2.1 User.py:1.1.2.1
Tres Seaver
tseaver@zope.com
Fri, 30 Nov 2001 16:06:40 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/App/Security
In directory cvs.zope.org:/tmp/cvs-serv10298/Zope/App/Security
Added Files:
Tag: Zope-3x-branch
IUser.py SecurityContext.py SecurityManagement.py
SecurityManager.py User.py
Log Message:
- Stub in more of the security framework.
=== Added File Zope3/lib/python/Zope/App/Security/IUser.py ===
# Copyright (c) 2001 Zope Coporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
""" Stock user interface """
from Interface import Interface
class IUser( Interface ):
"""
"""
def getUserName():
"""
"""
=== Added File Zope3/lib/python/Zope/App/Security/SecurityContext.py ===
# Copyright (c) 2001 Zope Coporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
""" Default ISecurityContext impl """
from ISecurityContext import ISecurityContext
class SecurityContext:
"""
Capture transient request-specific security information.
Attribute( 'stack'
, 'A stack of elements, each either be an ExecutableObject'
'or a tuple consisting of an ExecutableObject and a'
'custom SecurityPolicy.'
)
Attribute( 'user'
, 'The AUTHENTICATED_USER for the request.'
)
"""
def __init__( self, user ):
self.stack = []
self.user = user
self.objectCache = {}
=== Added File Zope3/lib/python/Zope/App/Security/SecurityManagement.py ===
# Copyright (c) 2001 Zope Coporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
""" Default ISecurityManagement implementation """
from ISecurityManagement import ISecurityManagement, ISecurityManagementSetup
from SecurityManager import SecurityManager
from SecurityContext import SecurityContext
__implements__ = ( ISecurityManagement, ISecurityManagementSetup )
try:
import thread
except:
get_ident=lambda: 0
else:
get_ident=thread.get_ident
_managers={}
#
# ISecurityManagementSetup implementation
#
def newSecurityManager( user ):
"""
Install a new SecurityManager, using user. Return the
old SecurityManager, if any, or None.
"""
thread_id = get_ident()
old = _managers.get( thread_id, None )
_managers[ thread_id ] = SecurityManager( thread_id
, SecurityContext( user )
)
return old
def replaceSecurityManager( old_manager ):
"""
Replace the SecurityManager with 'old_manager', which
must implement ISecurityManager.
"""
thread_id = get_ident()
_managers[ thread_id ] = old_manager
def noSecurityManager():
"""
Clear any existing SecurityManager.
"""
try:
del _managers[ get_ident() ]
except KeyError:
pass
#
# ISecurityManagement implementation
#
def getSecurityManager():
"""
Get a SecurityManager (create if needed).
"""
thread_id = get_ident()
manager=_managers.get( thread_id, None )
if manager is None:
import User
manager = newSecurityManager( User.UserWithName( 'Anonymous User' ) )
return manager
def setSecurityPolicy( aSecurityPolicy ):
"""
Set the system default security policy.
This method should only be caused by system startup code.
It should never, for example, be called during a web request.
"""
SecurityManager.setSecurityPolicy( aSecurityPolicy )
=== Added File Zope3/lib/python/Zope/App/Security/SecurityManager.py ===
# Copyright (c) 2001 Zope Coporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
""" Default ISecurityManager implementation """
import ZopeSecurityPolicy, os, string
max_stack_size = 100
_defaultPolicy = ZopeSecurityPolicy.ZopeSecurityPolicy()
def setSecurityPolicy(aSecurityPolicy):
"""Set the system default security policy.
This method should only be caused by system startup code. It should
never, for example, be called during a web request.
"""
global _defaultPolicy
last=_defaultPolicy
_defaultPolicy=aSecurityPolicy
return last
from ISecurityManager import ISecurityManager
class SecurityManager:
"""
A security manager provides methods for checking access and managing
executable context and policies.
"""
__implements__ = ISecurityManager
def __init__( self, thread_id, context ):
self._thread_id = thread_id
self._context = context
self._policy = None
def validate( self, accessed, container, name, value, roles ):
"""
Validate access.
Arguments:
accessed -- the object that was being accessed
container -- the object the value was found in
name -- The attribute name used to access the value
value -- The value retrieved though the access.
roles -- an (optional) list of roles to use when authorizing
access
The arguments may be provided as keyword arguments. Some of
these arguments may be ommitted, however, the policy may
reject access in some cases when arguments are ommitted.
It is best to provide all the values possible.
A boolean value is returned indicating whether the value is
accessible. An Unauthorized exception may be raised in some
cases.
"""
policy = self._policy
if policy is None: policy = _defaultPolicy
return policy.validate( accessed, container, name, value,
self._context, roles )
def validateValue( self, value, roles ):
"""
Validate access. This is a shortcut for the common case of
validating a value without providing access information.
A boolean value is returned indicating whether the value is
accessible. An Unauthorized exception may be raised in some
cases.
"""
policy = self._policy
if policy is None:
policy = _defaultPolicy
return policy.validate( None, None, None, value, self._context, roles )
def checkPermission( self, permission, object ):
"""
Check whether the security context allows the given
permission on the given object. Return a boolean value.
Arguments:
permission -- A permission name
object -- The object being accessed according to the permission
"""
policy = self._policy
if policy is None:
policy = _defaultPolicy
return policy.checkPermission( permission, object, self._context )
def addContext( self, anExecutableObject ):
"""
Add an ExecutableObject to the current security
context.
There is no return.
"""
stack=self._context.stack
if len( stack ) > max_stack_size:
raise SystemError, 'Excessive recursion'
stack.append( anExecutableObject )
p=getattr( anExecutableObject, '_customSecurityPolicy', None )
if p is not None: p=p()
self._policy=p
def removeContext( self, anExecutableObject ):
"""
Remove an ExecutableObject.
There is no return.
"""
stack=self._context.stack
if not stack: return
top=stack[-1]
if top is anExecutableObject:
del stack[-1]
else:
indexes=range(len(stack))
indexes.reverse()
for i in indexes:
top=stack[i]
if top is anExecutableObject:
del stack[i:]
break
else:
return
if stack:
top=stack[-1]
p=getattr(top, '_customSecurityPolicy', None)
if p is not None: p=p()
self._policy=p
else:
self._policy=None
def getUser( self ):
"""
Return the authenticated user.
This is equivalent to something like::
REQUEST['AUTHENTICATED_USER']
but is a bit cleaner, especially if 'REQUEST' isn't handy.
"""
return self._context.user
def calledByExecutable( self ):
"""
Determine if called through an ExecutableObject.
A true value is returned if any ExecutableObjects
have (directly or indirectly) called the current method and
a true value otherwise.
This can be used to determine if an object was called
(more or less) directly from a URL, or if it was called by
through-the-web provided code.
(The value returned by the initial implementation
is actually size of the context stack, which is the depth
of the through-the-web call stack. Is this information
valuable enough to promise in the interface?)
"""
return len( self._context.stack )
=== Added File Zope3/lib/python/Zope/App/Security/User.py ===
# Copyright (c) 2001 Zope Coporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
""" Default IUser implementations """
from IUser import IUser
class UserWithName:
__implements__ = IUser
def __init__( self, user_name ):
self._user_name = user_name
def getUserName( self ):
return self._user_name
'''
class UnrestrictedUser( UserWithName ):
__implements__( IUser )
unrestricted = UnrestrictedUser( 'System' )
class AnonymousUser( UserWithName ):
__implements__( IUser )
nobody = AnonymousUser( 'Anonymous' )
'''