Hola, Jorge.
On Thursday March 12, 2009 08:35:55 Jorge Vargas wrote:
> > By the way, in your subject you talk about tgext.crud and repoze.what
> > integration, but I couldn't find anything in your email which talks about
> > such integration. Did you forget to include something?
>
> huh? the whole email is about using tgext.crud, all the things you
> said "you are doing" all that is tgext.crud doing. Everything except
> the custom predicate. All the things "I am doing" are simply to make
> both packages speak to each other, which IMO is either
>
> a- a limitation in the way they interact
> b- user error and I don't understand one or the other or both.
> c- tgext.crud or repoze.what, is assuming the other package should
> behave in a way it is wasn't supposed to behave.
>
> I think you are limiting your responses to b without looking into a or c
Hmmm, yeah, I got wrong that part. It's true, your concerns were about
repoze.what on tgext.crud, not about repoze.what in general -- although some
of my statements still remain valid.
> > I'd do:
> > class self_user(Predicate):
> > message = "Only %(user) can access her own info"
> >
> > def evaluate(self, environ, credentials):
> > vars = self.parse_variables(environ)
> > # Assuming you have routes like "/users/:username:/:action:"
> > req_user = vars.named_args.get('username')
> > if req_user != credentials.get('repoze.what.userid'):
> > self.unmet(user=req_user)
> >
> > Note that in this situation there's no reason to use the database.
>
> ok two things
> 1- why you say "you" this is tgext.crud doing, I'm not supposed to
> know its implementation details. The way crud works
> http://www.turbogears.org/2.0/docs/main/Extensions/Crud/index.html#crud-ope
>rations I don't get access to the username in the URL, My predicate is
> simply trying to figure out if the record being edited is the one for the
> current user. (ie: you can edit your own user info but not others, unless
> you are admin)
>
> 2- routes? why will you have to drop down to routes from TG for auth?
In that case, well, I've repeated this possibly a thousand times: It's a
serious bug that TG2's object dispatch mechanism (or the Rest controller)
isn't wsgiorg_args compliant.
If you want to use named arguments, then your routing software *must* provide
it (and TG2's object dispatch stuff is the default routing software).
repoze.what doesn't care, at all, if you use Routes, Selector or TG2's
dispatch mechanism; the only thing it cares about is that such a software must
be wsgiorg_args compliant.
But of course, named and positional arguments are not the only solution, they
just happen to be the most elegant one. You can still use GET or POST
variables, which would out-of-the-box -- but not with the Rest controller.
To sum up, that's a TG2-specific issue. It's not a problem in tgext.crud or
repoze.what.
> >> 2- We need a better way to attach a predicate to a exposed method, +4
> >> LOC for each one is not fun.
> >
> > I have no idea what you mean by that. What 4 LOC per exposed action?
>
> in order to overwrite the functionality of CRC to allow a different
> require decorator you have this 4 lines
>
> @require(in_group('managers'))
> @expose()
> def get_all(self,*args,**kw):
> return super(RegistrationController,self).get_all(*args,**kw)
>
> I guess you could fetch the method from the parent class and decorate
> it but I find that more cryptic than the 4 lines above. In general
> this question should be.
Ahh, right, I see what you mean!
Yes, I was afraid that'd be true.
Well, to make things easier in the Rest controller, I can make repoze.what-
pylons support an alternative to the @ActionProtector decorator (@require's
parent), so that you could have:
decorate_with_require(RegistrationController.get_all,
in_group('managers'))
instead of:
RegistrationController.get_all = require(in_group('managers'))\
(RegistrationController.get_all)
But I'm not too fond of this solution because it's not simple enough, I think
it's possibly better to handle it in the Rest controller itself, somehow.
> Is there a way to declare the controller method somewhere and decorate
> it with auth in a second stage?
I guess
RegistrationController.get_all = require(in_group('managers'))\
(RegistrationController.get_all)
would work.
But it's ugly.
> >> 3- why repoze.what made All ? can't we use any/all from python we have
> >> plenty of ways of providing that in the TG1 codebase
> >
> > There's no way to do that. They need the environ to be evaluated.
>
> seriously? you can't do this with __call__. according to help(all) it
> simply calls bool(x) so I assume there has to be a way to stick that
> in there.
bool(predicate) is not a valid option. It assumes that the Predicate class has
been monkey patched with the buggy trick of __nonzero__.
> >> 4- look at how awful is that custom predicate to simply figure out if
> >> the current user is the one trying to be edited, I have left the
> >> pprint in there to give you an idea of how horrible it was for me to
> >> find out how to query for him.
> >
> > (Answered above)
>
> I think you oversimplified the problem, there is no "User.user_name"
> in the url. therefore i need to fetch that record and compare it to
> the current user.
If you're using the artificial key "user_id" in the URL, yes, you have to use
it, unless you tell repoze.what.plugins.sql to pass User.user_id as the user
identifier.
> >> 4.1- why is repoze.what.userid == User.user_name ??
> >
> > Don't ask me, you wrote it ;-) I don't even know you used the DB =)
>
> huh? repoze.what.userid is loaded by repoze.what from the "user_name"
> field, it is inconsistent as the User.user_id attribute is a number
> (autogenerated index) while repoze.what.userid is a string (stored in
> User.user_name)
Inconsistent? repoze.what doesn't have to be "consistent" with TG.
"userid" is _the_ _right_ name, since it's valid for strings and numbers.
"user_name" is a wrong name, since it's limited to strings.
And as far as repoze.what is concerned, the user identifier can be anything
(e.g., a binary value, an ASCII string, an Unicode string, a number), not just
a name (i.e., an ASCII or Unicode string).
That TG2 seem to prefer artificial keys over natural keys is another subject,
but I think those models should've been using natural keys since day 1; you
wouldn't be concerned about this otherwise.
> I know r.what is supposed to be backend independent and not all
> backends will have user_id defined but I think we should either
> a- rename repoze.what.userid -> repoze.what.username
That's discarded because of what I said above.
> b- store a not-user friendly value in repoze.what.userid, and provide
> an additioan repoze.what.username with the user-friendly name.
It doesn't make any sense for an authorization software to have two have
identifiers for the same user.
Nevertheless, repoze.what v2 will support credential loaders (repoze.who MD
provider-like stuff) for developers who want to load additional credentials to
use them in their custom predicate checkers -- but of course the built-in
predicate checkers will only use built-in credentials (this is, is_user will
continue using repoze.what.userid).
> Also related, what will happen here if the user changes his username?
Nothing interesting, if you wrote your custom predicates correctly (i.e., in a
future-proof way).
> sightly related didn't we used to have repoze.what.user (the whole db
> user instance) stored in the environ?
No, never. The user object is in the repoze.who identity dict.
> shouldn't we be using that
> instead of repoze.what.userid for comparations?
That'd be ugly for obvious reasons. In a nutshell: You'd be limiting part of
your authorization system to a _particular_ setup of your identification
system.
> >> 4.2- there was to be a better way to know if the current user is able
> >> to edit the current resource
> >
> > There is, and all that is documented.
>
> it is? I guess you added that in the last flew days. I remember from
> our last conversation you said it will be in r.what v2
>
> I don't see it here
> http://static.repoze.org/whatdocs/Manual/Predicates/Builtin.html
Did you read:
> > That'd be the self_user predicate above,
> > in your situation.
?
> >> 4.3- my code is very very ugly and will probably break in a very easy
> >> way. like going to (http://localhost:8080/register/edit)
> >
> > That's up to your routing settings, it has nothing to do with
> > repoze.what.
>
> again why you are talking routes here? this is all "Restul URLs" and
> in fact your solution will also break if that predicate is used in a
> URL that does not expose the "username" arg, but I guess that need to
> be check with a
> if var:
> ....
> else:
> self.unmet(...)
Again, to use named/positional arguments in repoze.what predicates, your
routing software must be wsgiorg_args compliant.
If you want to use the predicate checker I wrote, set Routes up until TG2's
object dispatch stuff supports wsgiorg_args.
> >> 6- I couldn't think of a sane way of doing
> >> if user = admin:
> >> edit_form = full_user_form
> >> elif user = current:
> >> edit_form = limited_user_form
> >> else:
> >> abort(403)
> >
> > For example,
> > """
> > @expose('coolpackage.cooltemplate')
> > @require(Any(is_user('admin'), self_user()))
> > def edit(self, username):
> > if 'admin' == request.identity.get('repoze.who.userid'):
> > c.edit_form = full_user_form
> > else:
> > c.edit_form = limited_user_form
> > return {'username': username}
> > """
> >
> > or,
> > """
> > @expose('coolpackage.cooltemplate')
> > @require(Any(in_group('admins'), self_user()))
> > def edit(self, username):
> > if in_group('admins').is_met(request.environ):
> > c.edit_form = full_user_form
> > else:
> > c.edit_form = limited_user_form
> > return {'username': username}
> > """
>
> again I think you missed the point here. You are assuming this is "my
> code" and I'm writing this from scratch all this is done by tgext.crud
> I'm just "using it" your first codeblock translated into how crud
> wants items should be something like (I haven't tested it)
Yes, I assumed it was your code, sorry.
> @expose('coolpackage.cooltemplate')
> @require(Any(is_user('admin'), self_user()))
> def edit(self, username):
> if 'admin' == request.identity.get('repoze.who.userid'):
> RegistrationController.edit_form = full_user_form
> else:
> RegistrationController.edit_form = limited_user_form
> return {'username': username}
>
> which is really odd not to mention will probably cause a big havoc. As
> swapping that widget on the fly may be an issue.
You're talking about validators? Yeah, that may be a problem in Rest
controllers.
> PS: remember c is deprecated we should use tmpl_context
Oh, right. Thanks!
Saludos,
--
Gustavo Narea <xri://=Gustavo>.
| Tech blog: =Gustavo/(+blog)/tech ~ About me: =Gustavo/about |
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"TurboGears Trunk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/turbogears-trunk?hl=en
-~----------~----~----~----~------~----~------~--~---