Hi, Chris.

On Tuesday January 6, 2009 20:00:11 Chris McDonough wrote:
> That sounds fine, as repoze.who does indeed set REMOTE_USER, and the
> relationship between what and who right now is a little weird (what is
> essentially a superset of who, which makes me a little nervous).  Splitting
> them apart seems about right.

Glad to know that.

> I'm not sure *just* adding roles really cuts it for maximum generality. 
> Maximum generality may not be a goal here, however, and that's your call. 
> But I'll note that roles granted to users or groups seems to be just
> another way to spell global assertions.
> A common thing to want to do is be able to make security assertions against
> a *particular resource* (which might be represented as PATH_INFO in a URL,
> or some object in a graph, or whatever).  For example, you'd like to be
> able to say that ("joe has permission to edit blog entry 1" and "joe cannot
> edit blog entry 2") instead of "joe has permission to edit blog entries"
> and then relying on imperative controller logic or decorators in the
> downstream app itself to figure out whether joe has permission to edit
> *this* blog entry.

You can achieve that with repoze.what predicates. You can write your own 
predicate to check for that condition:

    # This has not been tested:
    from paste.request import parse_dict_querystring
    from repoze.what.predicates import Predicate

    class can_edit_THIS_post(Predicate):
        message = 'Only Bob can edit posts 1 and 2'

        def _eval_with_environ(self, environ):
            form_vars = parse_dict_querystring(environ)
            blog_id = form_vars.get('blog_id')
            user = environ.get('REMOTE_USER')
            # Ignore this if this post is not #1 or #2!
            if blog_id not in ('1', '2'):
                return True
            return user == 'bob'

Then, for example, in a TG2-powered application, you would use it like this:

    from tg import require
    from repoze.what.predicates import All, has_permission
    from my_cool_app.predicates import can_edit_THIS_post
    class BlogController(BaseController):
        # ...
        @require(All(has_permission('edit-post'), can_edit_THIS_post()))
        def edit_post(self, blog_id, new_title, new_contents):
            # process the post edition...

> I came up with a pattern for this in repoze.decsec (proposal at
> http://www.plope.com/Members/chrism/decsec_proposal and implementation
> notes at http://www.plope.com/Members/chrism/decsec_revisited).  It's too
> frameworky for general purpose use but it is implemented and described.

Those documents are rather interesting. ACLs are a good alternative to 
predicate-based assertions, *and* I think they are not mutually exclusive.

In fact, I think they may complement each other under some situations:
 * For example, repoze.decsec may use repoze.what predicates for conditions in 
     [ {'action':'allow', 'principal':'Bob',   'permission':'system.Write'
        'condition': has_ip("")} ]
   (where has_ip is a repoze.what predicate -- not yet written, AFAIK)
 * repoze.what may provide a predicate that evaluates an ACL in a given 
context. For example, if you have the following ACL:
   [   {'action':'allow', 'principal':'system.Everyone',
       {'action':'allow', 'principal':'system.Authenticated',
        'permission':'application.Write'}  ]
with plain repoze.what predicates in TG2 you could use:
    # ...
    def Read(self):
    def Write(self):
but with ACLs, repoze.what may provide the eval_acl predicate (for example) 
which will use an ACL loaded in the repoze.what middleware and could be used 
in the fake TG2 controller in question as:
    # ...
    def Read(self):
    def Write(self):
(eval_acl would pass the script path in the environ to evaluate the ACL 
against the resource in question)

To sum up, I think ACL support would be a great addition to repoze.what, 
instead of plain roles granted to users/groups, as an alternative (not a 
replacement) to the current groups/permissions-based pattern with individual 
predicate assertions.

But I wonder what would be the best way to support ACLs...
 * Support ACLs through a plugin that uses repoze.decsec?
 * Support ACLs in repoze.what itself using repoze.decsec?
 * Merge both packages?

Anyway, did I get it right? Is ACL support what you were proposing 
specifically? :)

> > Anti-spam pattern
> > =================
> <<<snip>>>
> I'm not sure what this has to do with authorization. This seems like it
> should be a separate system.
> > CAPTCHA pattern
> > ===============
> <<<snip>>>
> Same observation here: this sounds like it should be a separate system.

I think that if a given routine is performed based on whether the current user 
is a known spammer (or if a submitted content is spam), according to an anti-
spam service, then that's an authorization pattern.

Likewise, I think that if a given routine is performed based on whether we are 
certain that the current user is human, then that's another authorization 

And because both authorization patterns are widely used, I think they should 
be supported out-of-the-box, *although* I wouldn't mind to implement such 
functionalities in two independent packages, as repoze.what plugins that 
provide the predicates mentioned above.

Gustavo Narea <http://gustavonarea.net/>.

Get rid of unethical constraints! Get freedomware:
Repoze-dev mailing list

Reply via email to