[Zope-dev] Re: ZCatalog getObject broken

Florent Guillaume fg at nuxeo.com
Thu Mar 10 14:39:46 EST 2005


Tres Seaver  <tseaver at zope.com> wrote:
> Chris McDonough wrote:
> | I implemented a "publisherTraverse" function like this FWIW:
> |
> | def publisherTraverse(context, path):
> |     # this is a hack to get around the fact that restrictedTraverse,
> |     # unlike publisher traversal, does checks at every step of the
> |     # path.  We don't want to limit access in this way (e.g. nested
> |     # shares are possible) so we reimplement restrictedTraverse in a
> |     # way that that emulates publisher traversal semantics
> |     ob = context.unrestrictedTraverse(path)
> |     user = getSecurityManager().getUser()
> |     if not user.has_permission('View', ob):
> |         raise zExceptions_Unauthorized, "cant traverse to %s" % path
> |     return ob
> 
> I don't think that the 'has_permission' check is quite right:  at least,
> that isn't what the publisher does.  'ZPublisher.BaseRequest.traverse'
> collects roles during the traversal, and then calls the user folder's
> 'validate', passing them at the end.  Note as well that 'View' may not
> be the permission which is protecting the traversed-to object).
> 
> The "correct" emulation would probably be to call the user object's
> 'authorize' method, passing the proper values for accessed, container,
> name, value, and roles.  Figuring out the proper values is left as an
> exercise for the reader ;).

Yeah that's what I'm digging through right now :-( The publisher's
collecting of the correct __roles__ from the intermediate traversed
objects is quite complex. Also validation (actually trying to get a user
that has access) tries user folders above if it fails. A correct
publisherTraverse (which is also a method I'd like to have) is *much*
more complex than what's shown above. And BTW the traverse() method
should be shot in the head.

In the current getObject problem that concerns us, we want to do better
that restrictedTraverse, but maybe trying to emulate the full publisher
rules is overly complex.

>From what I see traverse():

1. does validation checks by actually trying to authenticate a user,
   which is done according to its credentials and from the context
   of the published object, and retried with above user folders if
   no user is found on the first one,
2. also checks for potential __roles__ found:
   - on an intermediate objects gotten by __bobo_traverse__,
   - if the published object has a __call__.__roles__.

OTOH restrictedTraverse on each step:

1. does its validation using the current security manager's validate(),
2. does not collect any roles, so validate() uses its default behavior
   which ends up basically doing aq_acquire('__roles__').

So in a first pass that should be enough to fix our common problem, I
propose to just do basically what Dieter mentionned:
- unrestrictedTraverse to the parent
- restrictedTraverse for the final step

(I'll be testing this of course.)

Florent

-- 
Florent Guillaume, Nuxeo (Paris, France)   CTO, Director of R&D
+33 1 40 33 71 59   http://nuxeo.com   fg at nuxeo.com


More information about the Zope-Dev mailing list