[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Security - _protections.py:1.1.4.1 ZopeSecurityPolicy.py:1.1.2.25 __init__.py:1.1.2.5 metaConfigure.py:1.1.2.26 protectClass.py:1.1.2.13 publicClass.py:1.1.2.9 security-meta.zcml:1.1.2.3 security.zcml:1.1.2.5 ISecurityContext.py:NONE ISecurityManagement.py:NONE ISecurityManager.py:NONE ISecurityPolicy.py:NONE SecurityContext.py:NONE SecurityManagement.py:NONE SecurityManager.py:NONE SimpleSecurityPolicies.py:NONE

Jim Fulton jim@zope.com
Sun, 28 Apr 2002 13:17:11 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/Security
In directory cvs.zope.org:/tmp/cvs-serv17050/lib/python/Zope/App/Security

Modified Files:
      Tag: Zope-3x-branch
	ZopeSecurityPolicy.py __init__.py metaConfigure.py 
	protectClass.py publicClass.py security-meta.zcml 
	security.zcml 
Added Files:
      Tag: Zope-3x-branch
	_protections.py 
Removed Files:
      Tag: Zope-3x-branch
	ISecurityContext.py ISecurityManagement.py ISecurityManager.py 
	ISecurityPolicy.py SecurityContext.py SecurityManagement.py 
	SecurityManager.py SimpleSecurityPolicies.py 
Log Message:
HOTYB: Merged SecurityProxy-branch into main branch.  

All tests pass and folders can be listed and added through the web.
It is likely that most other things don't work and will need to be
fixed. The reason is that many accesses that should have been checked
before are now being checked and additional checks and thinking about
permissions and security settings are needed.

I'm in the process of drafting a paper for the wiki that describes the
changes in more detail.


=== Added File Zope3/lib/python/Zope/App/Security/_protections.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 protection information for some standard low-level types

Revision information:
$Id: _protections.py,v 1.1.4.1 2002/04/28 17:16:40 jim Exp $
"""

def protect():
    from Zope.Security.Checker import \
         defineChecker, getCheckerForInstancesOf, NamesChecker
    import Persistence.BTrees


    def _protect(which):
        __import__('Persistence.BTrees.%sBTree' % which)
        module = getattr(Persistence.BTrees, "%sBTree" % which)
        
        defineChecker(getattr(module, '%sBTree' % which),
                      getCheckerForInstancesOf(dict))
        defineChecker(getattr(module, '%sBucket' % which),
                      getCheckerForInstancesOf(dict))
        defineChecker(getattr(module, '%sSet' % which),
                      NamesChecker(['__getitem__', '__len__', 'has_key',
                                    '__repr__', '__str__',
                                    'keys', 'maxKey', 'minKey']
                                   )
                      )
        defineChecker(getattr(module, '%sTreeSet' % which),
                      NamesChecker(['__len__', 'has_key',
                                   '__repr__', '__str__',
                                   'keys', 'maxKey', 'minKey']
                                   )
                      )
        items = getattr(module, '%sBTree' % which)().keys()
        defineChecker(type(items),
                      getCheckerForInstancesOf(tuple))
        
        
    for which in 'OO', 'II', 'OI', 'IO':
        _protect(which)

    
                      


=== Zope3/lib/python/Zope/App/Security/ZopeSecurityPolicy.py 1.1.2.24 => 1.1.2.25 ===
 
 from Zope.ComponentArchitecture import getAdapter
-from Zope.ContextWrapper.ContainmentIterator import ContainmentIterator
-
+from Zope.Proxy.ContextWrapper import ContainmentIterator
 from Zope.Exceptions import Unauthorized, Forbidden
-
 from Zope.App.Security.IRolePermissionManager import IRolePermissionManager
 from Zope.App.Security.IPrincipalPermissionManager \
     import IPrincipalPermissionManager
@@ -39,9 +37,6 @@
 
 from types import StringType, StringTypes, TupleType, ListType, IntType, MethodType, NoneType
 
-# XXX: hack alert
-from Zope.ContextWrapper import getbaseobject
-
 getPermissionsForPrincipal = \
                 principalPermissionManager.getPermissionsForPrincipal
 getPermissionsForRole      = rolePermissionManager.getPermissionsForRole
@@ -75,48 +70,6 @@
         self._ownerous=ownerous
         self._authenticated=authenticated
 
-    #
-    #   ISecurityPolicy implementation.
-    #
-    def validate( self
-                , name
-                , value
-                , context
-                ):
-
-        try: permission=value.__permission__
-        except AttributeError:
-            # XXX: allow some simple types to get ZMI working
-            #      is this the right thing to do?
-            #      Also, respect the attribute
-            #      __allow_access_to_unprotected_subobjects__
-            #      as used in TALES iterators and other places
-            #      Also, respect __aatus__ for accessing methods of objects
-            #      (un)protected by it.
-            #      This is still a hack, and still incomplete, and just here
-            #      to get the ZMI working.
-            
-            
-            unwrapped_value = getbaseobject(value)
-            if (isinstance(unwrapped_value, (ListType, TupleType, StringTypes, IntType, NoneType))
-                or 
-                getattr(value,'__allow_access_to_unprotected_subobjects__',0)):
-                permission = 'Zope.Public'
-            elif (isinstance(unwrapped_value, MethodType) and 
-                  getattr(value.im_self,
-                          '__allow_access_to_unprotected_subobjects__',
-                          0)):
-                permission = 'Zope.Public'
-            else:
-                raise Forbidden(name, value, 'No permission set')
-
-        if permission == 'Zope.Public': # XXX need unit test for this
-            return
-
-        if self.checkPermission(permission, value, context):
-            return
-        raise Unauthorized(permission, name, value)
-
     def checkPermission( self, permission, object, context ):
         # XXX We aren't really handling multiple principals yet
 
@@ -191,51 +144,6 @@
                 return 1 # Allow on global role
 
         return 0 # Deny by default
-
-#        for p in principals.keys():
-#            if permission in getPermissionsForPrincipal(p):
-#                del principals[p]
-#            else:
-#                for r in getRolesForPrincipal(p):
-#                    if permission in getPermissionsForRole(r):
-#                        del principals[p]
-#                    if r in roles:
-#                        return 1
-#        return not principals
-
-    #
-    #   Helper methods
-    #
-    def _allowName( self, name ):
-        """
-            Is 'name' ever allowed to be retrieved under this policy?
-        """
-        return name and isinstance(name, StringType) and name.strip()
-
-    def _findPermission( self, value ):
-        """
-            Find the permission which guards the accessed object.
-        """
-        return getattr( value, '__permission__', None )
-    
-    def _listRolesFor( self, permission, object ):
-        """
-            Crawl the context of 'object' and return an accumulated
-            list of all roles which have 'permission'.
-
-            Note that we don't (yet) use 'object' to search for
-            placeful permission-role bindings.
-        """
-        role_set = {}
-
-        # Add "global" roles for permission here
-        for role in getRolesForPermission( permission ):
-            role_set[ role ] = 1
-
-        roles = role_set.keys()
-        roles.sort()
-
-        return tuple( roles )
 
 zopeSecurityPolicy=ZopeSecurityPolicy()
 


=== Zope3/lib/python/Zope/App/Security/__init__.py 1.1.2.4 => 1.1.2.5 ===
 ##############################################################################
 """ Zope Security Architecture """
+
+# Register some standard types
+import _protections
+_protections.protect()
+del _protections


=== Zope3/lib/python/Zope/App/Security/metaConfigure.py 1.1.2.25 => 1.1.2.26 ===
 from PermissionRegistry import permissionRegistry as perm_reg
 from RoleRegistry import roleRegistry as role_reg
-from SecurityManager import setSecurityPolicy
+from Zope.Security.SecurityManager import setSecurityPolicy
 from PrincipalRegistry import principalRegistry
 from RolePermissionManager import rolePermissionManager as role_perm_mgr
 from PrincipalPermissionManager import principalPermissionManager \


=== Zope3/lib/python/Zope/App/Security/protectClass.py 1.1.2.12 => 1.1.2.13 ===
 # 
 ##############################################################################
-"""Create the protection declarations object.
-
-Protection declarations are assert as part of the configuration process to map
-permissions to objects, ie to specific classes, class instances, and methods.
-\(Method permissions apply to both the class and class instance manifestations
-of the methods.)
-
-When the declarations are expressed as a simple (ie, empty) tag, they are
-applied to both the class and the instances of the class.  When the tags have
-subtags, then the instances are not inherently affected - the subtag directive
-"instances" can then be used.  [XXX this needs to be fleshed out.]
-
-Invalid protection declarations raise ProtectionDeclarationException
-instances."""
+"""Make assertions about permissions needed to access class instances attributes
+"""
 
 from Interface.Method import Method
 from Exceptions import UndefinedPermissionError
@@ -32,26 +20,29 @@
 
 from Zope.Configuration.ConfigurationDirectiveInterfaces \
      import INonEmptyDirective
+from Zope.Configuration.Action import Action
+
+from Zope.Security.Checker import defineChecker, getCheckerForInstancesOf
+from Zope.Security.Checker import Checker, CheckerPublic
 
 class ProtectionDeclarationException(Exception):
     """Security-protection-specific exceptions."""
     pass
 
 
-
 class protectClass:
 
     __class_implements__ = INonEmptyDirective    
     
     def __init__(self, _context, name, permission_id=None, interface=None,
-                 methods=None):
+                 names=None, like_unto=None):
         self.__class = _context.resolve(name)
         self.__name = name
         self.__permission_id = permission_id
+        self.__like_unto = like_unto
         self.__context = _context
-        self.__r = self.protect(_context, permission_id, interface, methods)
-        # So subsequent simple-declaration-style self() calls process instances
-        self.__empty = 1
+        self.__r = self.protect(_context, permission_id, interface, names,
+                                like_unto)
 
     # ._getPermission() is handy for subclassing with different permission
     # policy, eg publicClass.
@@ -68,65 +59,57 @@
             return permission_id
 
     def protect(self, _context, permission_id=None, interface=None,
-                methods=None):
+                names=None, like_unto=None):
         "Protect a specific aspect"
 
-        self.__empty = 0
+        r = []
+
+        if like_unto:
+            self.__protectLikeUnto(like_unto, r)
 
-        if not (interface or methods):
-            return []
+        if not (interface or names):
+            return r
+        
         permission_id = self._getPermission(permission_id)
 
-        r = []
 
         if interface:
             self.__protectByInterface(interface, permission_id, r)
-        if methods:
-            self.__protectMethods(methods, permission_id, r)
+        if names:
+            self.__protectNames(names, permission_id, r)
 
         return r
 
-    def instances(self, _context, permission_id=None):
-        "Protect instances of the class, as opposed to methods"
-        self.__empty = 0
-
-        permission_id = self._getPermission(permission_id)
-        r=[]
-        self.__instances(permission_id, r)
-        return r
-
-    def __instances(self, permission_id, r):
-        "Protect instances of the class, as opposed to methods"
-        permission_id = self._getPermission(permission_id)
-        r.append((
-            ('protectInstances', self.__class),
-            protectInstancesOfClass, (self.__class, permission_id,)))
-
-    def __protectMethod(self, method, permission_id, r):
-        "Set a permission on a particular method."
+    def __protectName(self, name, permission_id, r):
+        "Set a permission on a particular name."
         r.append((
-            ('protectMethod', self.__class, method),
-            protectMethod, (self.__class, method, permission_id)))
-
-    def __protectMethods(self, methods, permission_id, r):
-        "Set a permission on a bunch of methods."
-        for method in methods.split(","):
-            self.__protectMethod(method.strip(), permission_id, r)
+            ('protectName', self.__class, name),
+            protectName, (self.__class, name, permission_id)))
 
+    def __protectNames(self, names, permission_id, r):
+        "Set a permission on a bunch of names."
+        for name in names.split(","):
+            self.__protectName(name.strip(), permission_id, r)
 
     def __protectByInterface(self, interface, permission_id, r):
-        "Set a permission on methods in an interface."
+        "Set a permission on names in an interface."
         interface = self.__context.resolve(interface)
         for n, d in interface.namesAndDescriptions(1):
-            if isinstance(d, Method):
-                self.__protectMethod(n, permission_id, r)
+            self.__protectName(n, permission_id, r)
+
+    def __protectLikeUnto(self, like_unto, r):
+        "Set a permission on names in an interface."
+        like_unto = self.__context.resolve(like_unto)
+        r.append(
+            Action(discriminator=('protectLikeUnto', self.__class, object()),
+                   callable=protectLikeUnto,
+                   args=(self.__class, like_unto),
+                   )
+            )
 
     def __call__(self):
         "Handle empty/simple declaration."
-        r = self.__r
-        if self.__empty:
-            self.__instances(self.__permission_id, r)
-        return r
+        return self.__r
 
 def _checkPermission(permission_id):
     """Check to make sure that the permission is valid.
@@ -135,58 +118,38 @@
     if not permissionRegistry.definedPermission(permission_id):
         raise UndefinedPermissionError(permission_id)
 
+def protectName(class_, name, permission_id):
+    "Set a permission on a particular name."
+    checker = getCheckerForInstancesOf(class_)
+    if checker is None:
+        checker = Checker({}.get)
+        defineChecker(class_, checker)
+
+    if permission_id == 'Zope.Public':
+        # Translate public permission to CheckerPublic
+        permission_id = CheckerPublic
+
+    # OK, so it's a hack.
+    protections = checker.getPermission_func().__self__    
+    protections[name] = permission_id
 
-def protectInstancesOfClass(class_, permission_id):
-    _checkPermission(permission_id)
-    class_.__permission__ = permission_id
-
-def protectMethod(class_, method, permission_id):
-    "Set a permission on a particular method."
-    _checkPermission(permission_id)
-
-    m = getattr(class_, method)
-
-    d = class_.__dict__
-    if not d.has_key(method):
-        # Hm, we inherit the method. Dang, we need to insert a stub
-
-        # Make sure we have new style class:
-        if not issubclass(class_, object):
-            raise TypeError(
-                "Can only protected inherited methods of new "
-                "style classes", class_)
-
-        f = Protected(class_, method, permission_id)
-        setattr(class_, method, f)
+def protectLikeUnto(class_, like_unto):
+    """Use the protections from like_unto for class_
+    """
+    
+    unto_checker = getCheckerForInstancesOf(like_unto)
+    if unto_checker is None:
         return
-        
-    try:
-        setattr(m, "__permission__", permission_id)
-    except (AttributeError, TypeError):
-        if hasattr(m, "im_func"):
-            setattr(m.im_func, "__permission__", permission_id)
-        else:
-            raise ProtectionDeclarationException(
-                "Couldn't assign permission to method %s of class %s"
-                % (m, class_.__name__))
-
-# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Hack!!!!!!!!!!
-
-class Protected(object):
-
-    def __init__(self, *args):
-        self.__args = args # class_, method, permission_id
-
-    def __get__(self, instance, type=None):
-        return ProtectedMethod(self.__args, instance)
 
+    # OK, so it's a hack.
+    unto_protections = unto_checker.getPermission_func().__self__
     
-class ProtectedMethod(object):
-
-    def __init__(self, args, instance):
-        class_, method, self.__permission__ = args
-        m = getattr(super(class_, instance), method)
-        self.__m = self.__call__ = m
-
-    def __call__(self, *args, **kw):
-        return self.__m(*args, **kw)
+    checker = getCheckerForInstancesOf(class_)
+    if checker is None:
+        checker = Checker({}.get)
+        defineChecker(class_, checker)
+
+    # OK, so it's a hack.
+    protections = checker.getPermission_func().__self__
+    for name in unto_protections:
+        protections[name] = unto_protections[name]


=== Zope3/lib/python/Zope/App/Security/publicClass.py 1.1.2.8 => 1.1.2.9 ===
 
     def __init__(self, _context, name, permission_id=None, interface=None,
-                 methods=None):
+                 names=None):
         self._getPermission(permission_id) # Prohibit explicit permission!
         protectClass.__init__(self, _context, name,
                               permission_id=PublicPermission,
-                              interface=interface, methods=methods)
+                              interface=interface, names=names)
 
     def _getPermission(self, permission_id=None):
         if permission_id not in [None, PublicPermission]:


=== Zope3/lib/python/Zope/App/Security/security-meta.zcml 1.1.2.2 => 1.1.2.3 ===
       <subdirective name="protect"
                     attributes="permission_id, interface, methods" />
-      <subdirective name="instances" attributes="permission_id" />
       </directive>
     <directive name="publicClass" attributes="name, interface, methods"
                handler="Zope.App.Security.publicClass." />


=== Zope3/lib/python/Zope/App/Security/security.zcml 1.1.2.4 => 1.1.2.5 ===
 <security:protectClass name="Zope.App.Security.RolePermissionView."
    permission_id="Zope.Security"
-   methods="index, roles, permissions, permissionRoles, action,
+   names="index, roles, permissions, permissionRoles, action,
    manage_permissionForm, update_permission,
    manage_roleForm, update_role, permissionForID" />
 
 <security:protectClass
    name="Zope.App.Security.RolePermissionView.PermissionRoles."
    permission_id="Zope.Security"
-   methods="roles, rolesInfo"
+   names="roles, rolesInfo"
    interface="Zope.App.Security.IRegisteredObject." />
 
 
@@ -55,7 +55,7 @@
   
 <security:protectClass name="Zope.App.Security.PrincipalPermissionView."
    permission_id="Zope.Security"
-   methods="index, get_principal, unsetPermissions, denyPermissions,
+   names="index, get_principal, unsetPermissions, denyPermissions,
    grantPermissions, getUnsetPermissionsForPrincipal,
    getPermissionsForPrincipal" />
 

=== Removed File Zope3/lib/python/Zope/App/Security/ISecurityContext.py ===

=== Removed File Zope3/lib/python/Zope/App/Security/ISecurityManagement.py ===

=== Removed File Zope3/lib/python/Zope/App/Security/ISecurityManager.py ===

=== Removed File Zope3/lib/python/Zope/App/Security/ISecurityPolicy.py ===

=== Removed File Zope3/lib/python/Zope/App/Security/SecurityContext.py ===

=== Removed File Zope3/lib/python/Zope/App/Security/SecurityManagement.py ===

=== Removed File Zope3/lib/python/Zope/App/Security/SecurityManager.py ===

=== Removed File Zope3/lib/python/Zope/App/Security/SimpleSecurityPolicies.py ===