Hello, everybody.

Florent and I have been discussing about context-sensitivity in 
repoze.what-1.0 predicates and there's a good enhancement that may be applied 
but will break backwards compatibility, and I won't break backwards 
incompatibility unless you want it. 

If you have repoze.what predicates this would affect you, so please read on.

Right now repoze.what predicates are context-sensitive because they are 
evaluated with the WSGI environment. *But* if you have predicates that depend 
on POST/GET variables, then you have to use Paste to extract the variables you 
need from the WSGI environment. This is, GET/POST variables are used a lot in 
context-sensitivity authorization but they're not at hand (you need to write a 
little more code to get them).

So, there's a proposed solution which would make the 
Predicate.evaluate(environ, credentials) method receive one more argument: The 
GET and POST variables. So its signature would end up as:
>    evaluate(environ, credentials, variables)
(where ``variables`` is a dict, and ``variables['post']`` and 
``variables['get']`` contain the POST and GET variables respectively)

But if I implement it, then your custom predicates (if any) will break. I 
think it's a good compromise because:
 1.- If your predicates still use the ._eval_with_environ() method then you'll 
have to switch to .evaluate() the sooner or later anyway because it's 
deprecated (but still supported).
 2.- Upgrading is easy: Just add the "variables" argument to your .evaluate() 
method.

In case you don't find the big advantage of this change, think how you'd deal 
with predicates that depend on GET/POST variables:
>    from paste.request import parse_formvars
>    from repoze.what.predicates import Predicate
>
>    from yourcoolapplication.model import BlogPost, DBSession
>
>    class can_edit_post(Predicate):
>        message = 'Post %(post_id)s can only be edited by its author'
>
>        def __init__(self, post_id_variable='post_id', **kwargs):
>            self.post_id_variable = post_id_variable
>            super(can_edit_post, self).__init__(**kwargs)
>
>        def evaluate(self, environ, credentials):
>            # Extracting the post Id from the POST/GET variables
>            vars = parse_formvars(environ)
>            post_id = vars.get(self.post_id_variable)
>            if not post_id:
>                self.unmet('Post Id is not available')
>            # Loading the post object
>            post = DBSession.query(BlogPost).filter(post_id=post_id).one()
>            # Checking if it's the author
>            if post.author_userid != credentials.get('repoze.what.userid'):
>                self.unmet(post_id=post_id)

While you could write:
>    from repoze.what.predicates import Predicate
>
>    from yourcoolapplication.model import BlogPost, DBSession
>
>    class can_edit_post(Predicate):
>        message = 'Post %(post_id)s can only be edited by its author'
>
>        def __init__(self, post_id_variable='post_id', **kwargs):
>            self.post_id_variable = post_id_variable
>            super(can_edit_post, self).__init__(**kwargs)
>
>        def evaluate(self, environ, credentials, variables):
>            post_id = variables['post'].get(self.post_id_variable)
>            if not post_id:
>                self.unmet('Post Id is not available')
>            # Loading the post object
>            post = DBSession.query(BlogPost).filter(post_id=post_id).one()
>            # Checking if it's the author
>            if post.author_userid != credentials.get('repoze.what.userid'):
>                self.unmet(post_id=post_id)

Regarding variables available before the query string (if any; e.g., 
"/blog/post/post_id"), as supported in TG, they could be passed by the 
framework to the check_authorization() function so that it inserts them into 
``variables['extra']``. This would be optional, of course.

Finally, do you think this backwards incompatible change worths it? The poll 
ends by tomorrow evening here in western Europe. :)

Cheers!
-- 
Gustavo Narea <http://gustavonarea.net/>.

Get rid of unethical constraints! Get freedomware:
http://www.getgnulinux.org/
_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to