security.declareProtected doesn't always work?
Hi there, I have some issues with using declareProtected() outside product classes (deriving from ObjectManager or SimpleItem). An external method example that _does_ work, taken from the ZDG: import Globals import Acquisition from AccessControl import ClassSecurityInfo class Book(Acquisition.Implicit): def __init__(self, title): self._title=title # Create a SecurityInfo for this class security = ClassSecurityInfo() security.declareObjectPublic() security.declarePublic('getTitle') def getTitle(self): return self._title Globals.InitializeClass(Book) # The actual external method def GetBooks(self): books=[] books.append(Book('King Lear')) books.append(Book('Romeo and Juliet')) books.append(Book('The Tempest')) return books Now replace the line "security.declarePublic('getTitle')" with something like "security.declareProtected('View', 'getTitle')", and suddenly nobody is allowed to call getTitle() on a Book object anymore. This doesn't only occur in external method code, but also in product code, which is where I ran into it. Take for instance this class: class TOCEntry(Acquisition.Implicit): security = ClassSecurityInfo() security.declareObjectPublic() def __init__(self, id): self.id = id security.declareProtected('View', 'render') def render(self): """Render entry. """ return self.id Globals.InitializeClass(TOCEntry) 'render()' can now never be called from a DTML method or a ZPT template, while using 'security.declarePublic('render') does work. One gets errors like this: """ Error Type: Undefined Error Value: You are not allowed to access render in this context not found in 'entry/render', at line 8, column 3 """ which doesn't look very grammatical either. :) I haven't been able to figure out what causes the difference; classes that are initialized with Zope don't seem to have this problem, but this little class does. I've tried inheriting from Persistent or SimpleItem.Item but that doesn't seem to make any difference.. So what's going on? Am I missing something? If so, where is this documented? Martijn
Martijn Faassen writes:
I have some issues with using declareProtected() outside product classes (deriving from ObjectManager or SimpleItem). An external method example that _does_ work, taken from the ZDG:
import Globals import Acquisition from AccessControl import ClassSecurityInfo
class Book(Acquisition.Implicit): def __init__(self, title): self._title=title
# Create a SecurityInfo for this class security = ClassSecurityInfo() security.declareObjectPublic()
security.declarePublic('getTitle') def getTitle(self): return self._title
Globals.InitializeClass(Book)
# The actual external method def GetBooks(self): books=[] books.append(Book('King Lear')) books.append(Book('Romeo and Juliet')) books.append(Book('The Tempest')) return books
Now replace the line "security.declarePublic('getTitle')" with something like "security.declareProtected('View', 'getTitle')", and suddenly nobody is allowed to call getTitle() on a Book object anymore. You must acquistion wrap your book objects. Otherwise, Zope's security code is unable to find the permission-role mapping.
Try: return books.__of__(self) Dieter
Dieter Maurer wrote: [snip]
Now replace the line "security.declarePublic('getTitle')" with something like "security.declareProtected('View', 'getTitle')", and suddenly nobody is allowed to call getTitle() on a Book object anymore. You must acquistion wrap your book objects. Otherwise, Zope's security code is unable to find the permission-role mapping.
Try:
return books.__of__(self)
Aah, of course, makes sense. They should put this in the developer's guide! The thing that tripped me up is that it works at all for declarePublic. :) Thanks, Martijn
Aah, of course, makes sense. They should put this in the developer's guide! The thing that tripped me up is that it works at all for declarePublic. :)
Martijn, I can put it in the developer's guide.. maybe the next time you're through there, you can add a comment with the issue and we can fold it in during the next editing cycle? -- Chris McDonough Zope Corporation http://www.zope.org http://www.zope.com "Killing hundreds of birds with thousands of stones"
Martijn Faassen writes:
Dieter Maurer wrote: [snip]
Now replace the line "security.declarePublic('getTitle')" with something like "security.declareProtected('View', 'getTitle')", and suddenly nobody is allowed to call getTitle() on a Book object anymore. You must acquistion wrap your book objects. Otherwise, Zope's security code is unable to find the permission-role mapping.
Try:
return books.__of__(self)
Aah, of course, makes sense. They should put this in the developer's guide! The thing that tripped me up is that it works at all for declarePublic. :) The basic security mechanism uses the attribute "m__roles__" in order to protect "m". If this attribute it "None", then "m" is public. Otherwise, it is expected to be a sequence of roles that are allowed to use "m".
But, "ExtensionsClass" brings with it computed attributes. This allows "m__roles__" to be not a sequence but a method returning a sequence. When you protect "m" with a permission "p", then "m__roles__" is set to "PermissionRole(p)". This instance dynamically evaluates into a sequence of roles by crawling up the "aq_container" (which is correctly "aq_parent" after "aq_inner") chain and translating "p" into roles by interpreting the "permission-to-role" mapping it finds on its way to the application object. Therefore, "declarePublic" works for non-wrapped instances while "declareProtected" requires the wrapping. Dieter
The basic security mechanism uses the attribute "m__roles__" in order to protect "m". If this attribute it "None", then "m" is public. Otherwise, it is expected to be a sequence of roles that are allowed to use "m".
But, "ExtensionsClass" brings with it computed attributes. This allows "m__roles__" to be not a sequence but a method returning a sequence. When you protect "m" with a permission "p", then "m__roles__" is set to "PermissionRole(p)". This instance dynamically evaluates into a sequence of roles by crawling up the "aq_container" (which is correctly "aq_parent" after "aq_inner") chain and translating "p" into roles by interpreting the "permission-to-role" mapping it finds on its way to the application object.
Therefore, "declarePublic" works for non-wrapped instances while "declareProtected" requires the wrapping.
Dieter
Very well put, Dieter -- both as an explanation of the problem at hand, as well as a general description of one of the more esoteric regions of Zope. I think it belongs in a document somewhere. Thanks. I knew I read these email lists for a reason. Ziniti
I have added this nugget of knowledge as a comment to the ZDG. John Ziniti wrote:
The basic security mechanism uses the attribute "m__roles__" in order to protect "m". If this attribute it "None", then "m" is public. Otherwise, it is expected to be a sequence of roles that are allowed to use "m".
But, "ExtensionsClass" brings with it computed attributes. This allows "m__roles__" to be not a sequence but a method returning a sequence. When you protect "m" with a permission "p", then "m__roles__" is set to "PermissionRole(p)". This instance dynamically evaluates into a sequence of roles by crawling up the "aq_container" (which is correctly "aq_parent" after "aq_inner") chain and translating "p" into roles by interpreting the "permission-to-role" mapping it finds on its way to the application object.
Therefore, "declarePublic" works for non-wrapped instances while "declareProtected" requires the wrapping.
Dieter
Very well put, Dieter -- both as an explanation of the problem at hand, as well as a general description of one of the more esoteric regions of Zope. I think it belongs in a document somewhere. Thanks. I knew I read these email lists for a reason.
Ziniti
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
participants (4)
-
Chris McDonough -
Dieter Maurer -
John Ziniti -
Martijn Faassen