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