[Zope] Question on __roles__

Cees de Groot cg@cdegroot.com
29 Dec 2000 00:43:03 +0100


I have encapsulated most bits of my software in a product. One part
simply shows database objects, and I've made a base class to 
handle most of the showing and editing stuff. In the base class,
I keep a tab on what methods etc. are used for viewing and for editing,
and I use these in the concrete classes to set the roles. Eg:

Base.py:
class Obj(OFS.SimpleItem.Item, Acquisition.Implicit,
          AccessControl.Role.RoleManager,
	  AccessControl.Owned.Owned):

    view_objects = []

    index_html = HTMLFile('default_view', globals())
    view_object.append('index_html')

    ... etcetera

Customer.py:
class Obj(Base.Obj):

    __ac_permissions__ = (
	('View Own Info', Base.Obj.view_objects),
    )

    ...

Globals.default__class_init__(Obj)

As far as I can see, this is all by the book. The whole idea is that the
set of methods is the same, but the permissions on them can differ (for
example, there are special restrictions on viewing and editing invoices).

However, these protections don't work in most cases. They seem to work 
when they pertain to methods, but they don't when they pertain to DTML files.
Is there something in the base class' base classes that influences how
role lookup works?

I've tried to trace down what happens, and found that ZPublisher.BaseRequest
has a funny bit: when trying to find out the necessary roles on an object,
it first tries to get the attribute '__roles__' on the subobject, and then
combines the current entry name plus '__roles__' and tries to get that from
the subobject. However, it seems to me that the latter getattr() needs to be
done on the object, not the subobject - at least, my tracing seems to indicate
that if it walks down, say 'Customer/53/index_html', that at a certain moment
during the traversal 

    object = <Customer instance>
    subobject = <Python method>
    entry_name = 'index_html'

Here, looking up "index_html__roles__" in the subobject, the index_html
method, doesn't seem to be very useful - it is expected to be found on 
the containing Customer instance. And indeed, if I change line 386 in 
BaseRequest.py from:

    roles = getattr(subobject, entry_name+'__roles__', roles)

to:

    roles = getattr(object, entry_name+'__roles__', roles)

things work as I expect them to work. 

As this is such a core piece of Zope, it seems quite unlikely to me
that I found a bug here (although an older version of ZPublisher does
check object instead of subobject). The only thing I can think of is
that Acquisition should work for the getattr() and somehow I managed
to disable Acquisition on these instances. 

Any hints as to what I'm doing wrong?

-- 
Cees de Groot               http://www.cdegroot.com     <cg@cdegroot.com>
GnuPG 1024D/E0989E8B 0016 F679 F38D 5946 4ECD  1986 F303 937F E098 9E8B