Controller wide auth in web2py
Lately I’ve been spending a lot of time working on a home project that uses web2py. It’s a really powerful MVC based framework written in Python. Part of what I love about it is the speed that you can prototype code and see it on a website. It allows you to quickly mock up the interaction of several database tables and after a weekend of working with it, I was able to re-implement a project that took me three weeks of time to do in C++. However, s I worked more with it I have noticed that a lot of it’s more powerful features are either not documented, documented only in comments in the source code, or only documented in passing on the mailing-list. Part of that is because development is so fast-paced, part because development is somewhat distributed in that there are many separate places where knowledge lives, and part of that is because the main documentation is a book that only gets updated once a year at best.
So one of my goals is to add to this problem. As I have read the past several months of archives of the mailing list I’ve kept notes of what’s interesting in the problems that come up and the solutions offered. Over time I hope to document these bits of knowledge and provide links to running examples of how they can be used.
The first of these however is one that I’ve come up with myself the other day. I have an app in mind that requires the assumption that the user is logged in before taking any action in that controller. Other controllers allow some actions while not logged in, but this controller was deep in the work-flow and each function with-in it was assumed to have a valid user. What I had done initially was to decorate each function in the controller with an auth check such as:
@auth.requires_login() def index(): return dict(message="You are logged in")
The problem of course is that as the number of functions in the controller grew it became very error prone to have to decorate each function. Also it turned out that there was a small class of functions where the logged in requirement wasn’t actually a requirement and that the end-user should be able to to access the page while not logged in. So after a few false starts, I settled on:
import urllib # List of functions to be called without being logged in whitelist = ('chat') if not auth.basic() and not auth.is_logged_in() \ and not auth.environment.request.function in whitelist: request = auth.environment.request next = URL(r=request,args=request.args, vars=request.get_vars) redirect(auth.settings.login_url + '?_next='+urllib.quote(next))
Placing the above snippet in your controller file will allow the chat function to be executed without being logged in, but any other function request will redirect the viewer to the login url and then back to their original destination.
No related posts.