2014-06-30

Locking down a default web2py controller

Say you have a web2py app where you want the default controller default.py to be locked down to require a user to always be authenticated to access any of the functions in that controller.

Problem: by default, user():, which calls auth() to supply the default login form handler is in default.py so if use the typical method to force auth checking on the controller itself (as explained in https://groups.google.com/d/msg/web2py/ReznbEX0Mh0/CfyEF70TrG0J)
auth.requires_login()(lambda: None)()

def index():
    return dict()

def user():
    return dict(form=auth())
This will result in a redirection loop because the initial un-logged-in access to /app/(default/index) will result in a redirect (due to requires_login()) to /app/default/user/login and on every call to default will result in a redirect to default/user/login etc.

So,we have to move user() out of the way.

To do this, we have to tell Auth where to find user(). By default it looks in default controller, but this can be modified in the Auth instantiation in the model (models/db.py):
#original auth instance
#auth = Auth(db)

#redirected auth instance
auth = Auth(db=db, controller='login')
This tells Auth instance auth to look in controller login for the user() instead of default. We use keyword db for telling it which DAL instance to use now, since we have switched to kwargs. In controllers/login.py:
# coding: utf8

#here is the default action, redirect back to the default controller
def index():
    redirect(URL(c='default'))

def user():
    return dict(form=auth())
And don't forget to move views/default/user.html to views/login/user.html!

No comments:

Post a Comment