[Zope] The container has no security assertions

Mark McEahern mark@mceahern.com
Fri, 15 Nov 2002 09:51:16 -0600


[Using Zope 2.6 final on Red Hat 7.3 with Python 2.1.3]

I have a CMF portal type that's implemented as a Zope Product.  I need to
make a fairly complicated report for published content of this type.  My
basic approach is to take the portal_catalog.searchResults and stuff them
into a Python class that provides access to the results in a way that
facilitates the report.  Where I'm stuck is that I just don't know how to
get at that Python class from the Page Template where I do the report.  I'm
happy to provide as many details as possible, but I'm hoping at first to
sketch the broad outlines of what I've tried, since I think what I'm missing
is some basic understanding of the security model--that seems to be the
particular wall I'm running into...

I have a Python class that does not need to persist.  I call it a
DisplayBag.  It sits in a module in the same folder as the portal type:

   PressRelease/
     __init__.py
     DisplayBag.py
     PressRelease.py --> the portal_type

DisplayBag.py looks like this:

  from AccessControl import ClassSecurityInfo
  from Acquisition import Implicit
  import Globals

  class DisplayBag(Implicit)

    security = ClassSecurityInfo()
    security.declareObjectPublic()

    def __init__(self, ...):
      # nothing really special

    security.declarePublic('years')
    def years(self):
      # nothing really special

    # other methods, similar to years, nothing really special

  Globals.InitializeClass(DisplayBag)

The current hack I use to "get at" DisplayBag is with a method tacked onto
the PressRelease class.  (I've tried getting at the DisplayBag from an
external method.  I've had the same basic problem--the error indicated
below.)

  class PressRelease(Document.Document):

    meta_type = 'Press Release'
    security = ClassSecurityInfo()

    def __init__(self, ...):
      # nothing really special

    # other methods--nothing really special

    security.declarePublic('make_bag')
    def make_bag(self, search_results):
      d = PressReleaseDisplayBag(search_results)
      # I've also tried __of__, which makes no difference (i.e., same
error).
      # return d.__of__(self)
      return d

  InitializeClass(PressRelease)

Then, in a skins folder, I have a PageTemplate called press_releases.pt.
What this does is gets the published Press Releases and then, hackishly,
takes the first one (so I have a PressRelease on which to call make_bag), do
getObject() on it since searchResults doesn't give me the object, and call
make_bag.  I get the DisplayBag just fine--I've used tal:content="results"
('results' is the bag) to display it.  But then when I call the years()
method of the bag:

  <div tal:define="raw python:here.portal_catalog(portal_type='Press
Release',
                                                  review_state='published');
                   first_pr python:raw[0].getObject();
                   results python:first_pr.make_bag(raw)"
       tal:repeat="pr_year results/years">

I get this in the error_log (I have VerboseSecurity 0.4 installed):

[snip lots of detail, this is at the tail end of the traceback...]
Module Products.PageTemplates.Expressions, line 206, in __call__
Module Products.PageTemplates.Expressions, line 194, in _eval
Module Products.PageTemplates.Expressions, line 150, in _eval
__traceback_info__: results
Module Products.PageTemplates.Expressions, line 346, in restrictedTraverse
__traceback_info__: {'path': ['years'], 'TraversalRequestNameStack': []}
Module Products.VerboseSecurity.VerboseSecurityPolicy, line 157, in validate
Unauthorized: The container has no security assertions. Access to 'years' of
(PressReleaseDisplayBag instance at 86746f8) denied.

In the short-term, I wonder what magic incantation I need to use to
workaround that error.

Long-term, I wonder, Is there a better way for me to use Python in Zope that
isn't just so plain hard and contorted?  The reason I felt I needed to make
the DisplayBag class and not just do all the stuff it's doing either in
Python Scripts or TAL is that--well--it seems like it will be easier to test
and maintain.  I could have a profusion of scripts in the skins folder that
effectively do the same thing.  And I'd probably already be done, but I'd
really like to figure this out.

I have this itching suspicion that I haven't provided enough detail--or that
I haven't summarized well enough.

Thanks for any insights or suggestions you can offer.

// mark

-