How to check if the user is authorized for a controller or action

12 views
Skip to first unread message

Kirk Strauser

unread,
Jun 30, 2009, 10:05:33 AM6/30/09
to turbo...@googlegroups.com
I'm building a navigation system and only want to show actions that a user is
authorized to access. I've been digging around for that documentation but
can't seem to find it and would appreciate a pointer.

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

cd34

unread,
Jun 30, 2009, 3:44:30 PM6/30/09
to TurboGears
The subject of the post versus the question posed within appear to be
different. If you are truly talking about protecting a controller or
action, then, you would need to look at root.py on a quickstarted
project which shows you how a manager or editor can be handed limited
access to an action within a controller:

@expose('tg201.templates.index')
@require(predicates.has_permission('manage', msg=l_('Only for
managers')))
def manage_permission_only(self, **kw):
"""Illustrate how a page for managers only works."""
return dict(page='managers stuff')

@expose('tg201.templates.index')
@require(predicates.is_user('editor', msg=l_('Only for the
editor')))
def editor_user_only(self, **kw):
"""Illustrate how a page exclusive for the editor works."""
return dict(page='editor stuff')

Likewise, if you wanted to protect an entire controller for a specific
user:

class TestController(BaseController):
allow_only = predicates.is_user('specificusername', msg="only
specificusername can log in here")

or that they authenticated:

class TestController(BaseController):
allow_only = authorize.not_anonymous()

or that they are in the manage group:

class TestController(BaseController):
allow_only = predicates.has_permission('manage', msg=l_('Only for
managers'))

If you want to access the repoze information within your template:

<py:if test="request.identity!=None">
Logged in as: <div py:content="request.identity['repoze.who.userid']"
py:strip=""/>
</py:if>

I'm reasonably sure you can access the predicates within the
template. I've not dug deep enough into the code for that yet.

Kirk Strauser

unread,
Jun 30, 2009, 4:09:27 PM6/30/09
to turbo...@googlegroups.com
On Tuesday 30 June 2009 02:44:30 pm cd34 wrote:
> The subject of the post versus the question posed within appear to be
> different. If you are truly talking about protecting a controller or
> action, then, you would need to look at root.py on a quickstarted
> project which shows you how a manager or editor can be handed limited
> access to an action within a controller:

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

Kirk Strauser

unread,
Jul 16, 2009, 2:32:40 PM7/16/09
to turbo...@googlegroups.com

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

Kevin Horn

unread,
Jul 16, 2009, 5:38:46 PM7/16/09
to turbo...@googlegroups.com
Thanks for this, Kirk...very useful.

Kevin Horn

clive....@googlemail.com

unread,
Jul 17, 2009, 4:43:24 AM7/17/09
to TurboGears
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

Kirk Strauser

unread,
Jul 17, 2009, 10:55:32 AM7/17/09
to turbo...@googlegroups.com
On Jul 17, 2009, at 3:43 AM, clive....@googlemail.com wrote:

> 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


Gustavo Narea

unread,
Jul 17, 2009, 8:23:12 PM7/17/09
to turbo...@googlegroups.com
Hello,

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 |

KMCB

unread,
Jul 18, 2009, 7:18:32 AM7/18/09
to TurboGears
Gustavo,


Any thoughts on V2's availability?

By the way, I have notice that you are very good on supporting your
tool downstream. That is great to see.

Good Job

KMCB

Kirk Strauser

unread,
Jul 20, 2009, 2:14:19 PM7/20/09
to turbo...@googlegroups.com, Gustavo Narea
On Friday 17 July 2009 07:23:12 pm Gustavo Narea wrote:

> 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

Gustavo Narea

unread,
Jul 28, 2009, 11:45:36 AM7/28/09
to Kirk Strauser, turbo...@googlegroups.com
Hello, Kirk, and sorry about the delay to reply.

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. :-)
--

Gustavo Narea

unread,
Jul 28, 2009, 11:53:25 AM7/28/09
to turbo...@googlegroups.com
Hello, and I'm sorry for the delay.

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!

Reply all
Reply to author
Forward
0 new messages