Weird IndexableObjectWrapper + TopicIndex + aq_acquired interactions.
You know you are in trouble when you need to read the c-code of Acquisition to understand a problem. :) This took me half the day to figure out, and in fact, I still don't fully understand it. So I need help with this. CPS has an index, called cps_filter_sets. It's a TopicIndex, and TopicIndexes can have expressions as filters. This one has: "getattr(o, 'portal_type', None) not in ('Section', 'Workspace')" Where o is the object that are being indexed. But, this being an expression, it's protected, and therefore, a getattr becomes a guarded_gettatr. guarded_getattr does it's security check by doing: validate = SecurityManagement.getSecurityManager().validate aq_acquire(inst, name, aq_validate, validate) Where in this case inst will be the object that is being indexed. aq_acquire will, if the first parameter is not an AcquisitionWrapper, and the third parameter is not None, wrap the object. Now, in our case, the object is an IndexableObjectWrapper, wrapping an Acquisition wrapped object. So, aq_acquire will Acquicision wrap the IndexableObjectWrapper, with the result that the object being used now has no context! Then, it passes this to validate, who in turn passes it to allowed, who check that the object has the users user folder in it's context. And it hasn't, because it has no context. *blam* You get an AuthorizedError, and the object does not get indexed. OK, there are several ways to fix this, one being to not use getattr. But there is still something missing from my understandning of all this: - Not every object has this problem! Why, I have no idea. I had his problem in two products, and in ONE of them, it disappeared when I introduced the otherwise useless PropertyManager as a baseclass. The other product already has propertymanager as a baseclass! Any insight into this would be appreciated. //Lennart
OK, so, for some reason some CMF objects fail when being indexed because they are wrapped in an aq wrapper that wrapped an IndexableObjectWrapper that wraps another aq_wrapper. And sometimes, the same object do not fail in otehrwise very similar situation. *sigh*. So for example, this works fine: container._setObject(id, ob) ob = container._getOb(id) <returns to the workflows constructInstance method> <yadayadyada> ob.indexObject() All if fine. And this fails: container._setObject(id, ob) ob = container._getOb(id) ob.manage_permission( permission_to_manage='Access contents information', roles=ACCESS_CONTENTS_INFO_ROLES, acquire=0) <returns to the workflows constructInstance method> <yadayadyada> ob.indexObject() Now, it only fails around every second time. Mhm. Nope, not everytime. It's regukar, a unit test will fail on the same places both times, but *exactly the same call* will still fail about every second time. Hurray. I'm so happy this problem is so easy to track down! Grrr. -- Lennart Regebro, Nuxeo http://www.nuxeo.com/ CPS Content Management http://www.cps-project.org/
Lennart Regebro wrote at 2005-9-19 17:38 +0200:
... aq_acquire will, if the first parameter is not an AcquisitionWrapper, and the third parameter is not None, wrap the object.
Now, in our case, the object is an IndexableObjectWrapper, wrapping an Acquisition wrapped object. So, aq_acquire will Acquicision wrap the IndexableObjectWrapper, with the result that the object being used now has no context!
Really? What is the "aq_parent" that was used when wrapping the object? It is context of the "IndexableObjectWrapper". The context of the indexable wrapped object does not change.
... Then, it passes this to validate, who in turn passes it to allowed, who check that the object has the users user folder in it's context.
And it hasn't, because it has no context. *blam* You get an AuthorizedError, and the object does not get indexed.
Where does the context come from used when "aq_acquire" acquisition wrapped the "IndexableObjectWrapper"? The best way around such problems would probably by to make "IndexableObjectWrapper" a public class. -- Dieter
Dieter, my man!
Now, in our case, the object is an IndexableObjectWrapper, wrapping an Acquisition wrapped object. So, aq_acquire will Acquicision wrap the IndexableObjectWrapper, with the result that the object being used now has no context!
Really?
No?
What is the "aq_parent" that was used when wrapping the object?
Eh, which one? The aq_chain of both the original aq wrapper and the indexableobjectrapper is correct. The aq_chain of the "outside" aq_wrapper is just [<self>]. Which seems expected, since aq_acquire think it got an object without acquisition, right?
It is context of the "IndexableObjectWrapper". The context of the indexable wrapped object does not change.
Right...
Then, it passes this to validate, who in turn passes it to allowed, who check that the object has the users user folder in it's context.
And it hasn't, because it has no context. *blam* You get an AuthorizedError, and the object does not get indexed.
Where does the context come from used when "aq_acquire" acquisition wrapped the "IndexableObjectWrapper"?
I don't think there is any context involved.
The best way around such problems would probably by to make "IndexableObjectWrapper" a public class.
"Public"? -- Lennart Regebro, Nuxeo http://www.nuxeo.com/ CPS Content Management http://www.cps-project.org/
Lennart Regebro wrote at 2005-9-21 08:18 +0200:
...
What is the "aq_parent" that was used when wrapping the object?
Eh, which one? The aq_chain of both the original aq wrapper and the indexableobjectrapper is correct. The aq_chain of the "outside" aq_wrapper is just [<self>]. Which seems expected, since aq_acquire think it got an object without acquisition, right?
Depending of what "<self>" is. When an acquisition wrapper is formed, there always must some context (which is put into "aq_parent"). Almost all contexts contain a full acquisition chain. Maybe, we should wrap the "IndexableObjectWrapper" into the context of the catalog?
...
Where does the context come from used when "aq_acquire" acquisition wrapped the "IndexableObjectWrapper"?
I don't think there is any context involved.
When an acquisition wrapper is formed, there is a context -- the one put as "parent" argument of the acquisition wrapper constructor.
The best way around such problems would probably by to make "IndexableObjectWrapper" a public class.
"Public"?
Yes, public (to let all security checks succeed). Of course, this means that someone with the permission to customize a catalog can obtain information he may not gain in a different way. -- Dieter
When an acquisition wrapper is formed, there always must some context (which is put into "aq_parent").
Well, as I can figure out this is the code that does the wrapping: /* Crap, we've got to construct a wrapper so we can use Wrapper_findattr */ UNLESS (self=newWrapper(self, Py_None, (PyTypeObject*)&Wrappertype)) return NULL; And that has None as the container/context. http://svn.zope.org/Zope/tags/Zope-2-8-1/lib/python/Acquisition/_Acquisition...
participants (2)
-
Dieter Maurer -
Lennart Regebro