You are not logged in Log in Join
You are here: Home » Members » karl » MyWiki » PublishNotes

Log in
Name

Password

 
 
FrontPage »

PublishNotes

Traversal and security with the default publisher

This is an incomplete sliver of the traversal and security checks involved in publishing. I had to step through this a few times and finally decided I'd take notes for the next time I have to relearn it.

Traversal to the object

ZPublisher.BaseRequest:traverse()

  • Break up the URL into objects, starting at the root, which is the app object. At each object, the publisher attempts to find the next object in the path by calling methods on the current object; at the last object, the publisher attempts to return a string to put in the response.
    • __before_publishing_traverse__ is called if it exists, but return values are ignored
    • methods that return the next object:
      • __bobo_traverse__, which returns the next object (or does it stop the publishing after returning?)
      • __getattr__
      • __getitem__
    • methods that short-circuit the publishing process:
      • __call__
      • index_html attribute
      • __str__
  • The methods that short-circuit the publishng process stop the publisher from finding further subobjects; for example, if your __call__ method doesn't return a string to be published, you'll get a cryptic error message. This means that you can't use a random method to find the next object to return, but you can use __getitem__ or a ComputedAttribute?.

    Methods can do funny things and read the rest of the URL that won't be traversed with the standard publishing process, though. This is one way to avoid obvious variables in the URL.

Security

At each step, when an object is found, the security machinery decides whether it is accessible and publishing can proceed.

ZopeSecurityPolicy?.validate()

  • gets the aq_base of the objects
  • tries to get __roles__ from the object
    • tries to get __roles__ from the object's container if not there
    • checks for to see if the container is a list, dict, or tuple with Containers() (line 154); these grant access
    • tries to get __allow_access_to_unprotected_subobjects__ if not there
      • this can be true, in which case access is granted, or a dict, in which case we grant if the value for the key of the object's name is true, or a callable object, in which case we grant if the function called with the name and the value (?) returns true.
  • if __roles__ is None or contains Anonymous, grant access
  • does some narrowing with the object's owner and proxy roles (?)
  • otherwise, get the user from the security context and ask the user if it is allowed: context.user.allowed(value, roles)

    User.BasicUser?.allowed():

    • For the first user's role that intersects the object's roles:
      • get the user folder, which is the aq_parent of the user object
      • get the context, which is the aq_parent of the user folder. This is the user folder's container, except in cases that I don't know about. For the default Zope user folder, this is the Application object.

        The context can be None, in which case grant access.

      • if the object has an im_self (i.e. it's a method), use that for the object
      • If the context is in the acquisition hierarchy of the unwrapped object, grant access. Otherwise, deny access.

        This is checked by calling object.aq_inContextOf(ucontext, 1).

        This is to prevent sneaking a different user folder into the security check somehow.