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
Cees de Groot wrote:
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.
This sounds like a bug to me. I've had very similar problems to this with Squishdot.
Jim Fulton wrote:
Chris Withers wrote:
self.id = id self.title = 'Title!' self.anInt = 0 self.aString = 'testing'
None of the values above can have a __roles__ attribute, so they are covered by assertions made in their containers.
Jim, This thread might well be the same problem, if it was looking for roles on the subobject, and the subobject is Acquisition.Explicit or not Acquisition subclassing at all, it wouldn't find any roles there and wouldn't get the ones on the object through acquisition, hence raising the Authentication box that was causign problems in Squishdot. Here's the other threads on the problem for a bit more context: http://zope.nipltd.com/public/lists/dev-archive.nsf/Main?SearchView=&Query=R... http://zope.nipltd.com/public/lists/dev-archive.nsf/Main?SearchView=&Query=_... http://zope.nipltd.com/public/lists/dev-archive.nsf/ByKey/5177D01752683CA1 Does this all make any sense or have I lost the plot again? cheers, Chris
Chris Withers <chrisw@nipltd.com> said:
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.
This sounds like a bug to me. I've had very similar problems to this with Squishdot.
An extra data point: it really seems to be a bug. I've applied the patch to our servers (development and production), and the only different behavior I can see is that a folder that is protected by a mysqlUserFolder acl_users now denies be access when trying to access the folder, instead of trying to access one of the objects within the folder. And that seems to be better behavior to me, too. -- Cees de Groot http://www.cdegroot.com <cg@cdegroot.com> GnuPG 1024D/E0989E8B 0016 F679 F38D 5946 4ECD 1986 F303 937F E098 9E8B
participants (2)
-
cg@cdegroot.com -
Chris Withers