Jens Vagelpohl wrote:
I have found a strange security issue with Zope 2.8.1 that seems to
stem from code not doing what it was supposed to do in Zope 2.7.x, but
which works in 2.8.1 and then causes other side effects in code that
relied on the broken behavior.
Symptom: In Zope 2.8.1 it is *impossible* to override a
ClassSecurityInfo security declaration in an Archetypes-derived content
item. (I have a small set of unit tests that proves the behavior under
Zope 2.8.1 if anyone is interested)
A little background: When you register an Archetypes-derived content
type, it will do all the generated accessor/setter method magic and
then call InitializeClass a second time.
The code in lib/python/App/class_init.py has changed between Zope 2.7.x
and Zope 2.8 in order to support new-style classes. To be more precise,
instead of manipulating the class __dict__ directly we now use
setattr/delattr/etc. This change seems to have "un-broken" code which
did not do what the code comments suggest. Namely, when a class is sent
through class_init.default_class_init__ (better known as
Globals.InitializeClass) the class __dict__ is searched to find objects
that look like ClassSecurityInfo instances in order to read and apply
the security settings. After finding the ClassSecurityInfo instance, it
is force-deleted from the object (the comments say, "out of paranoia").
However, somehow this did not work correctly in Zope 2.7.x, where the
deletion call looked like...
(dict being the class __dict__, and key being the name of the
ClassSecurityInfo instance). Under Zope 2.8, it looks like this:
(self being the class object).
Under Zope 2.7, the security object *would still be there* when hitting
InitializeClass for the second time via Archetypes' registerType, which
in turn meant Archetypes would not instantiate its own
ClassSecurityInfo instance and stuff it with the declarations from
whatever Archetypes-derived base class you used.
In Zope 2.8, the deletion actually works as intended - but due to that
fact Archetypes will instantiate its own ClassSecurityInfo and populate
it with the declarations from the base class that I am trying to
override. So the overridden settings are all overwritten again by the
base class declaration.
My question is, what is the reasoning behind deleting the
ClassSecurityInfo object from the class after it has been read the
first time? How can this be implemented in a sane way so that custom
security declarations can be retained?
My understanding (and the way we use it when monkey patching for instance)
is that whenevery you apply new security to a class, you create a new
ClassSecurityInfo on it. It only defines "new stuff" to do. The real
synthesized security is still stored in __ac_permissions__.
security = ClassSecurityInfo()
def foo(): ...
then later on:
security = ClassSecurityInfo()
C.security = security
C.newmethod = something
Anyway that's what I do. I never relied on a preexisting C.security.
Florent Guillaume, Nuxeo (Paris, France) CTO, Director of R&D
+33 1 40 33 71 59 http://nuxeo.com [EMAIL PROTECTED]
Zope-Dev maillist - Zope-Dev@zope.org
** No cross posts or HTML encoding! **
(Related lists -