[Zope] Management View

Paul Winkler pw_lists at slinkp.com
Thu Sep 9 12:52:33 EDT 2004


On Thu, Sep 09, 2004 at 09:30:51AM -0500, Edward Hartfield wrote:
> Johan Carlsson wrote:
>    Why do you need different authentication logic?
> 
> My client wants to do form-based authentication and have user data 
> stored in a database so they can manage users without having to know 
> anything about Zope.  

Lots of people do this.  The usual way is to use a UserFolder that 
interacts with your data source.  If you want to do something custom, 
SimpleUserFolder is a nice place to start, it provides examples
of getting users from SQL.

> My idea is to create a folder object that can be 
> given a method (AuthenticateMethod) to call when someone tries to 
> traverse the folder's contents.  AuthenticateMethod returns true or 
> false.  The folder itself knows nothing of the authentication scheme.  
> That's AuthenticateMethod's concern.

And this method would presumably make requests to your database?

Hmm.  Here's an alternative that was suggested to me when
I had some similar requirements, and worked out pretty well:  
let the User object do it instead, by supplementing its local roles.

First, decide what role you will use for protecting your 
Zope data.  You only need one role. Let's call it 'myrole'. 
Give that role "View" (or whatever) permissions 
on the data you're restricting. Don't grant the
role to any users - your User object will be dynamically
granting itself this role depending on the context object
and your own authorization rules.  Here's a way to do that:

Subclass a UserFolder implementation (such as SimpleUserFolder)
and have its getUser() method return a custom User class.
Define a method of this user class named something like 
_getExtraRolesInContext(self, object), which, given a context 
object, does your database lookups or whatever, and returns 
either ['myrole'] if you want to authorize or [] if you don't.
 
Next, write a trivial getRolesInContext() method 
that adds the output of the parent class' getRolesInContext()
to _getExtraRolesInContext().

Finally, wrap the base class' allowed() method, something
like:

    def allowed(self, object,  object_roles=None): 
        """Return true if the user has one of the given roles
        in the context of object. 
        sadly, getRolesInContext is not called by this in the base class,
        or we wouldn't have to define this method.
        """

        if object_roles is None: return 0 
        extra_roles = self._getExtraRolesInContext(object)
        for role in object_roles:
            if role in extra_roles:
                if self._check_context(object):
                    return 1 
        # fall back to the old behavior 
        return TheBaseClass.allowed(self, object, object_roles)

> My partner and I agree that it doesn't make sense to throw away Zope's 
> built-in security.

Good :-)
I don't even know how you could possibly do so.

>  But we don't like the hack required to logout a user 
> with basic authentication.  

Have you tried CookieCrumbler?

> Also, we need to implement a record-level 
> authorization scheme.

I assume by "record" you mean an individual persistent 
object in Zope?

> The easiest, most cost-effective way to do this 
> seems to be using a database to define user permissions just the way we 
> want.

You can do this in the scenario I described above.
It's really not much work, and it allows you to keep data
in any Folder-like containers you wish. The authentication/
authorization magic is entirely encapsulated by the 
UserFolder and User.  For one thing this just feels cleaner
to me; for another thing, you won't have people wondering
why security is broken because they accidentally added a vanilla
Folder or Plone Folder or whatever.

-- 

Paul Winkler
http://www.slinkp.com


More information about the Zope mailing list