[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Security - protectClass.py:1.1.2.8

Jim Fulton jim@zope.com
Mon, 4 Mar 2002 11:58:04 -0500


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

Modified Files:
      Tag: Zope-3x-branch
	protectClass.py 
Log Message:
Added logic to protectClass to make sure that inherited methods were
protected correctly.



=== Zope3/lib/python/Zope/App/Security/protectClass.py 1.1.2.7 => 1.1.2.8 ===
     pass
 
+
+
 class protectClass:
 
     __class_implements__ = INonEmptyDirective    
@@ -63,13 +65,6 @@
         else:
             return permission_id
 
-    def __checkPermission(self, permission_id):
-        """Check to make sure that the permission is valid.
-        """
-
-        if not permissionRegistry.definedPermission(permission_id):
-            raise UndefinedPermissionError(permission_id)
-
     def protect(self, permission_id=None, interface=None,
                 method=None, methods=None):
         "Protect a specific aspect"
@@ -100,36 +95,18 @@
         self.__instances(permission_id, r)
         return r
 
-    def __inst(self, permission_id):
-        self.__checkPermission(permission_id)
-        self.__class.__permission__ = permission_id
-
     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),
-            self.__inst, (permission_id,)))
+            protectInstancesOfClass, (self.__class, permission_id,)))
 
     def __protectMethod(self, method, permission_id, r):
         "Set a permission on a particular method."
         r.append((
             ('protectMethod', self.__class, method),
-            self.__method, (method, permission_id)))
-
-    def __method(self, method, permission_id):
-        "Set a permission on a particular method."
-        self.__checkPermission(permission_id)
-        m = getattr(self.__class, method)
-        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, self.__class.__name__))
+            protectMethod, (self.__class, method, permission_id)))
 
     def __protectMethods(self, methods, permission_id, r):
         "Set a permission on a bunch of methods."
@@ -150,3 +127,66 @@
         if self.__empty:
             self.__instances(self.__permission_id, r)
         return r
+
+def _checkPermission(permission_id):
+    """Check to make sure that the permission is valid.
+    """
+    
+    if not permissionRegistry.definedPermission(permission_id):
+        raise UndefinedPermissionError(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)
+        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)
+
+    
+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)