[Zope-CMF] PortalContent permissions

seb bacon seb@jamkit.com
Thu, 19 Apr 2001 21:46:59 +0100


Wow, thanks for the prompt reply.  I've not got time right now to look
deeper into it, but a quick go shows that there's still some
acquisition problems - the rendered dtml isn't acquiring its
standard_html_header, for example.  I'll take a closer look tomorrow
or at the weekend, although my mastery of black magic isn't quite up
to scratch, I fear ;-)

What do you feel about losing the 'view' default and replacing it with
the first action in the actions list?  Am I right that it's OK to do
that?  

Finally, thanks again.  I really appreciate the work you folks put
back in to the community. 

seb

> I see now why this won't quite work.  ZPublisher works in this order:
> 
> 1. Finds the requested object.
> 2. Finds the innermost user folder that applies to the object.
> 3. Authenticates the user, then checks whether the user is allowed to
> access the object.
> 4. traverse() returns the object.
> 5. publish_module then uses mapply() to process the object.
> 
> The _index_html computation occurs at step 1.  We would need to be able to
> insert logic between steps 3 and 5.
> 
> Perhaps we should try something else: mapply() looks for specific
> attributes to discover the function signature and there are places
> throughout Zope that fake function signatures for mapply.  If index_html
> manifested itself as an object with a computed function signature, it
> could add logic to step 5.  index_html's apparent function signature would
> be the function signature of the skinned object (which in turn is nearly
> always faked as well... sigh.)
> 
> I've included a rough cut below based on your code.
> 
> Shane
> 
> 
> -------- 8-< ---------
> 
> from ExtensionClass import Base  # Makes ComputedAttributes work
> from AccessControl import getSecurityManager
> 
> (...)
> 
> class PortalContent:
> 
>     (...)
> 
>     def _index_html(self):
>         '''
>         Invokes the action identified by the id "view" or the first
> action.
>         '''
>         return SkinnedDefaultView(self)
> 
>     security.declareProtected(CMFCorePermissions.View, 'index_html')
>     index_html = ComputedAttribute(_index_html, 1)
> 
>     (...)
> 
> 
> class SkinnedDefaultView (Base):
>     '''
>     Invokes the right skinned view after authentication is performed,
>     providing mapply() with the info it is seeking.
>     '''
> 
>     def __init__(self, ob):
>         # Avoid mixing up acquisition.
>         self.__dict__['_ob'] = ob
> 
>     def _findSkinnedOb(self):
>         ob = self.__dict__['_ob']
>         ti = ob.getTypeInfo()
>         if ti is not None:
>             path = ti.getActionById('view', None)
>             if path is not None:
>                 view = ob.restrictedTraverse(path)
>                 return view
>             actions = ti.getActions()
>             if actions:
>                 sm = None
>                 for action in actions:
>                     verified = 0
>                     permissions = action.get('permissions', None)
>                     if not permissions:
>                         # This action requires no extra permissions.
>                         verified = 1
>                     else:
>                         if sm is None: sm = getSecurityManager()
>                         for permission in permissions:
>                             # The user must be able to match at least
>                             # one of the listed permissions.
>                             if sm.checkPermission(permission, ob):
>                                 verified = 1
>                                 break
>                     if verified:
>                         path = action['action']
>                         view = self.restrictedTraverse(path)
>                         return view
>             raise 'Not Found', ('No default view defined for type "%s"'
>                                 % ti.getId())
>         else:
>             raise 'Not Found', ('Cannot find default view for "%s"'
>                                 % string.join( ob.getPhysicalPath() ) )
> 
>     def _getSkinnedOb(self):
>         # Caches the object.
>         s = self.__dict__.get('_skinob', None)
>         if s is not None:
>             return s
>         s = self._findSkinnedOb()
>         self.__dict__['_skinob'] = s
>         return s
> 
>     def _func_code(self):
>         return self._getSkinnedOb().func_code
>     func_code = ComputedAttribute(_func_code, 1)
> 
>     def __call__(self, *args, **kw):
>         return apply(self._getSkinnedOb(), args, kw)
> 
> 
> 
> 
> _______________________________________________
> Zope-CMF maillist  -  Zope-CMF@zope.org
> http://lists.zope.org/mailman/listinfo/zope-cmf
> 
> See http://www.zope.org/Products/PTK/Tracker for bug reports and feature requests

-- 

   [] j a m k i t 
           
        seb bacon
T:  020 7749 7218
F:  020 7739 8683
M:  07968 301 336
W: www.jamkit.com