Authorization Chains

Ferris uses the concept of authorization chains to control access to controllers and their actions. The concept is simple: A authorization chain consists of a series of functions (or callables). When trying to determine to allow or deny a request each function in the chain is called. If any of the functions return False then the request is rejected. Chains are specified using Controller.Meta.authorizations and the add_authorizations() decorator.

Using Authorizations

Here’s an example of requiring a user to be logged in to access a controller:

from ferris import Controller

def require_user(controller):
    return True if controller.user else False

class Protected(Controller):
    class Meta:
        authorizations = (require_user,)

    ...

You can also use add_authorizations() instead:

@route
@add_authorizations(require_user)
def protected_action(self):
    ...
ferris.core.controller.add_authorizations(*args)[source]

Adds additional authorization chains to a particular action. These are executed after the chains set in Controller.Meta.

To add authorizations globally use the global event bus.

Creating Authorization Functions

As shown above a simple authorization function is rather trivial:

def require_user(controller):
    return True if controller.user else False

Note that you can also include a message:

def require_user(controller):
    return True if controller.user else (False, "You must be logged in!")

Or if you’d like to redirect or present your own error page you can return any valid response:

def require_user(controller):
    if controller.user:
        return True
    url = users.create_login_url(dest_url=controller.request.url)
    return controller.redirect(url)

Built-in Authorization Functions

The module ferris.core.auth includes some built-in useful authorization functions and utilities.

ferris.core.auth.require_user(controller)[source]

Requires that a user is logged in

ferris.core.auth.require_admin(controller)[source]

Requires that a user is logged in and that the user is and administrator on the App Engine Application

There are a few function generators that use predicates. These are useful shortcut authorization functions.

ferris.core.auth.require_user_for_prefix(prefix)

Generates an authorization function that requires that users are logged in for the given prefix.

ferris.core.auth.require_admin_for_prefix(prefix)

Generates an authorization function that requires that the user is an App Engine admin for the given prefix.

ferris.core.auth.require_user_for_action(*args, **kwargs)
ferris.core.auth.require_admin_for_action(*args, **kwargs)
ferris.core.auth.require_user_for_route(*args, **kwargs)
ferris.core.auth.require_admin_for_route(*args, **kwargs)

You can also create your own generators using precidates.

ferris.core.auth.prefix_predicate(prefix)[source]
ferris.core.auth.action_predicate(action)[source]
ferris.core.auth.route_predicate(route)[source]

Then use predicate_chain to combine them with your authorization function.

ferris.core.auth.predicate_chain(predicate, chain)[source]

Returns the result of chain if predicate returns True, otherwise returns True.