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