[Zope3-dev] Protecting class methods

Steve Alexander steve@cat-box.net
Mon, 14 Jul 2003 20:56:45 +0300


> <content class="myclass">
>   <require 
>       permission="zope.ManageContent"
>       attributes="new" />
> </content>
> 
> and
> 
> <class class="myclass">
>   <require 
>       permission="zope.ManageContent"
>       attributes="new" />
> </class>
> 
> But none of them seemed to take effect. Is there anything I can do to
> assign a permission to this classmethod? Or am I better making an
> instance method that calls it and protecting the instance method?

Both the <class> and <content> directives make security declarations 
about the instances of a class, not about a class itself.

There could be a separate directive to make declarations directly for a 
class.

Unfortunately, the checker machinery looks up a checker for an object's 
class and not for the object itself. So, you can't register a checker 
for your class like that.

What you can do is provide a __Security_checker__ attribute for your 
class that is a NamesChecker that allows access to 'new'.
You don't want to provide this checker for instances, just for the 
class. So, you need to use a descriptor that stores and retrieves a 
different value for the class from the value for an object.

Something like this:


__metaclass__ = type

class ClassObjDescriptor:

     def __init__(self, name, class_value):
         self.name = name
         self.class_value = class_value

     def __get__(self, inst, cls=None):
         if inst is None:
             # being called for the class
             return self.class_value
         try:
             return inst.__dict__[self.name]
         except KeyError:
             raise AttributeError, self.name

     def __set__(self, inst, value):
         inst.__dict__[self.name] = value

     def __delete__(self, inst):
         try:
             del inst.__dict__[self.name]
         except KeyError:
             raise AttributeError, self.name

class MyClass:

   __Security_checker__ = ClassObjDescriptor('__Security_checker__',
                                             NamesChecker(['new']))

   def new(cls):
       return whatever
   new = classmethod(new)


--
Steve Alexander