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

Ken Manheimer klm@zope.com
Fri, 30 Nov 2001 14:39:28 -0500


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

Modified Files:
      Tag: Zope-3x-branch
	protectClass.py 
Log Message:
Implement some baseline configuration directives -
protectClass.protect() and .instances - and __call__().
  


=== Zope3/lib/python/Zope/App/Security/protectClass.py 1.1.2.2 => 1.1.2.3 ===
 # FOR A PARTICULAR PURPOSE.
 
-class protectClass:
-    __complex=0
+"""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 provoke instances of the
+ProtectionDeclarationException class."""
 
+from Zope.Configuration.name import resolve
+from Interface.Method import Method
+
+class ProtectionDeclarationException(Exception):
+    """Security-protection-specific exceptions."""
+    pass
+
+class protectClass:
     def __init__(self, name, permission=None, interface=None,
                  method=None, methods=None):
+        self.__class = resolve(name)
         self.__name=name
         self.__permission=permission
-        self.__interface=interface
-        self.__method=method
-        self.__methods=methods
+        self.protect(permission, interface, method, methods)
+        # So subsequent simple-declaration-style self() calls process instances
+        self.__empty = 1
 
     def protect(self, permission=None, interface=None,
-                method=None, methods=None, instances=None):
+                method=None, methods=None):
         "Protect a specific aspect"
-        # stub
-        self.__complex=1
+
+        self.__empty = 0
+
+        if not (interface or method or methods):
+            return
+        if permission is None:
+            permission = self.__permission
+            if permission is None:
+                raise ProtectionDeclarationException("No permission specified")
+
+        if interface:
+            self.__protectInterface(interface, permission)
+        if method:
+            self.__protectMethod(method, permission)
+        if methods:
+            self.__protectMethods(methods, permission)
 
     def instances(self, permission=None):
         "Protect instances of the class, as opposed to methods"
-        # stub
-        self.__complex=1
+        self.__empty = 0
 
-    def __call__(self):
-        "Handle empty case"
+        if permission is None:
+            permission = self.__permission
+        if permission is None:
+            raise ProtectionDeclarationException("No permission specified")
+        self.__class.__permission__ = permission
+
+    def __protectMethod(self, method, permission):
+        "Set a permission on a particular method."
+        m = getattr(self.__class, method)
+        try:
+            setattr(m, "__permission__", permission)
+        except AttributeError, TypeError:
+            if hasattr(m, "im_func"):
+                setattr(m.im_func, "__permission__", permission)
+            else:
+                raise ProtectionDeclarationException(
+                    "Couldn't assign permission to method %s of class %s"
+                    % (m, self.__class.__name__))
 
+    def __protectMethods(self, methods, permission):
+        "Set a permission on a bunch of methods."
+        for method in methods.split(","):
+            self.__protectMethod(method.strip(), permission)
+
+
+    def __protectInterface(self, interface, permission):
+        "Set a permission on methods in an interface."
+        interface = resolve(interface)
+        for n, d in interface.namesAndDescriptions():
+            if isinstance(d, Method):
+                self.__protectMethod(n, permission)
+
+    def __call__(self):
+        "Handle empty/simple declaration."
+        if self.__empty:
+            self.instances(self.__permission)
 
 def publicClass(name, interface=None, method=None, methods=None):
     "Declare a class and some of it's methods to be public"