BTW, does such a navigation system already exist? Surely so; I'm confident I'm
not the first person wanting to do this. :-)
--
Kirk Strauser
I have authentication up and running. What I need is a way to tell whether a
user would have access to a given controller or action without them actively
trying to visit it. In pseudocode, I want to do something like:
for controller in controllerlist:
for action in controller:
if user.has_access_to(action):
print_link_to(action)
Imagine that pseudocode in the context of a navigation bar where you want to
display links to all the pages a user can access but none of the pages that
they don't have access to.
--
Kirk Strauser
Replying to myself for the sake of other readers.
To see if the user has access to a controller:
try:
MyController()._check_security()
except webob.exc.HTTPUnauthorized:
print 'No access'
I still have no idea how to check if they have access to an action, but I'll
put back if/when I figure it out.
--
Kirk Strauser
> Just thought I'd chuck in my 2¢ ... in the use cases for the various
> controllers / actions, I'll define logical roles a user must have in
> order to perform the action / access the controller. Then, in the
> navigation menu, I simply check if the user has those roles to
> determine whether to display the relevant item or not ... I know its
> kind a low-tech, gets the job done, though :)
> Cheers,
> C
Well, my motivation is that I've already defined access rules in the
controllers and actions themselves using allow_only and @require and
setting up the right predicates. Now that my app is all snug and
secure (I hope! :-) ), I'd like to re-use that work instead of
repeating it in the navigation code.
If Foo.dosomething can check whether a user is authorized, I'd ideally
like for the navbar builder to be able to ask it (well, it's
decorators).
--
Kirk Strauser
Sorry for joining so late.
I'm afraid there's no sane/DRY way to do this, unfortunately, because of the
way repoze.what 1 works. The problem is that the conditions are attached via
decorators, which can be wrapped around (hidden) by other decorators, which
leaves us with no reliable way to get the predicate. Of course, this doesn't
apply to controller-wide authorization via .allow_only.
TG2-specific decoration mechanism for actions wouldn't cut it, because it is,
well, TG2 specific, and also because it's likely that you'll use another
decorator which doesn't use this stuff (and then all would be lost again).
This is one of the top reasons that pushed me to work on repoze.what 2, which
will come to the rescue with the proven authorization goodness called Access
Control Lists. :)
Cheers,
-- Gustavo.
Gustavo Narea <xri://=Gustavo>.
| Tech blog: =Gustavo/(+blog)/tech ~ About me: =Gustavo/about |
> I'm afraid there's no sane/DRY way to do this, unfortunately, because of
> the way repoze.what 1 works. The problem is that the conditions are
> attached via decorators, which can be wrapped around (hidden) by other
> decorators, which leaves us with no reliable way to get the predicate. Of
> course, this doesn't apply to controller-wide authorization via
> .allow_only.
Could repoze.what 1 be (easily) modified to track its predicate decorators?
For example, suppose:
def predicate(value):
def decorate(func):
attrs = getattr(func, 'predicates', [])
attrs.append(value)
setattr(func, 'predicates', attrs)
return func
return decorate
@predicate('something')
@predicate('another')
def bar(test):
print 'Test: ', test
print bar.predicates
If the Predicate base class had something like that in .__init__, could it be
used to deterministically build the list of predicates that were being applied
to an action?
I apologize for asking this before examining the code in question, but you
might be able to answer in 3 seconds what might take me a day to find. Also,
brainstorming is fun. :-)
--
Kirk Strauser
TG2 uses repoze.what predicates by attaching them to methods via decorators,
and so do many people using r.what in Pylons, but not everyone uses them that
way and repoze.what 1.0 makes no assumption about it, so all the uses are
perfectly valid.
On the other hand, TG has its own way to route requests to code, while other
frameworks use other alternatives (i.e., re-using a mapper like Routes or
Selector, or using their own mechanisms). So, assuming repoze.what kept the
predicates for each section in your code*, there would be no standard way to
determinate what predicate(s) belong to the current request.
This is, it'd be out of the scope of a framework-agnostic authorization
library like repoze.what 1. On the contrary, this task is best suitable for
the Web frameworks themselves.
repoze.what 2 will handle such routing by itself, so this wouldn't be a
problem.
* I even have to use the generic word "code" instead of "controllers" or
"controller actions", because such concepts may be implemented differently
from one framework to another, or not present at all.
Cheers!
- Gustavo.
Kirk said:
> Could repoze.what 1 be (easily) modified to track its predicate decorators?
> For example, suppose:
>
> def predicate(value):
> def decorate(func):
> attrs = getattr(func, 'predicates', [])
> attrs.append(value)
> setattr(func, 'predicates', attrs)
> return func
> return decorate
>
> @predicate('something')
> @predicate('another')
> def bar(test):
> print 'Test: ', test
>
> print bar.predicates
>
> If the Predicate base class had something like that in .__init__, could it
> be used to deterministically build the list of predicates that were being
> applied to an action?
>
> I apologize for asking this before examining the code in question, but you
> might be able to answer in 3 seconds what might take me a day to find.
> Also, brainstorming is fun. :-)
--
KMCB said:
> Any thoughts on V2's availability?
Well, although I've not been able to work on it lately and the code is not
usable yet, I'd say progress is good. I think I'm around 75% on the road to
the first alpha release.
> By the way, I have notice that you are very good on supporting your
> tool downstream. That is great to see.
Actually not as good as I used to be ;-) Nowadays spare time is scarce. :/
Cheers!