Community contributed extensions

Deadbolt

Deadbolt is an authorisation mechanism for defining access rights to certain controller methods or parts of a view using a simple AND/OR/NOT syntax. It is based on the original Secure module that comes with the Play! framework.

Note that Deadbolt doesn’t provide authentication! You can still use the existing Secure module alongside Deadbolt to provide authentication, and in cases where authentication is handled outside your app you can just hook up the authorisation mechanism to whatever auth system is used.

Getting started

To installl Deadbolt, you can use the modules repository:

play install deadbolt-0.1

Identifying the current user

In order to know if access to a view or controller is authorised, you need to know who the current user is. Because various applications will have their own concept of a user, Deadbolt defines the models.deadbolt.RoleHolder interface. This interface should be implemented by any class type that represents an object that will try to access a controller method or view.

Once a RoleHolder has been implemented, it can return a list of models.deadbolt.Role objects to indicate which roles a RoleHolder has. Again, Role is an interface and so should not intrude on your application’s model architecture.

In a move taken directly from the Secure module, you define the hooks into your application by extending a static inner class of Deadbolt – RoleHolderAccessor. This class has two key methods -

static RoleHolder getRoleHolder()

getRoleHolder() should return the current user, which must implement the models.deadbolt.RoleHolder interface.

static void onAccessFailure(Class<? extends Controller> controllerClass)

onAccessFailure(Class) should handle the what happens following an unauthorised attempt to access a secured controller method.

Securing controllers

Controllers are secured using the @With annotation to ensure method calls are checked against the current user.

@With(Deadbolt.class)
public class MyController extends Controller

Rolenames are matched against result of the Role.getRoleName() method of the roles return from RoleHolder#getRoles().

There are two annotations available to define access to a controller method - @Restrict, and @Restrictions.

@Restrict

The @Restrict annotation defines a set of role names that are ANDed together.

// This restricts access to the list method to any role holder with a role whose name is "foo"
@Restrict("foo")
public static void list()
// This restricts access to the list method to any role holder with both "foo" and a "bar" roles.
@Restrict({"foo", "bar"})
public static void list()

@Restrictions

The @Restrictions annotation defines a set of @Restricts that are ORed together.

// This restricts access to the list method to any role holder with a role whose name is "foo".  This is the equivalent to just @Restrict("foo")
@Restrictions(@Restrict("foo"))
public static void list()
// This restricts access to the list method to any role holder with the "foo" role, or roles whose names are "bar" AND "gee".  Note that a role holder with a "bar" OR a "gee" role will be denied access.
@Restrictions({@Restrict("foo"), @Restrict("bar", "gee")})
public static void list()

Securing views

Views are secured with the deadbolt.restrict tag. This is slightly simpler than the annotations used by controllers, since the syntax is always that of @Restrictions, i.e. ORed role groups in the top level, ANDed roles groups in the inner level:

#{deadbolt.restrict roles:[['foo']]}
    this restricts access to this content to role holders with the "foo" role
#{/deadbolt.restrict}
#{deadbolt.restrict roles:[['foo', 'bar']]}
    this restricts access to this content to role holders with the "foo" AND 'bar' roles
#{/deadbolt.restrict}
#{deadbolt.restrict roles:[['foo'], ['bar']]}
    this restricts access to this content to role holders with the "foo" OR 'bar' role
#{/deadbolt.restrict}

Negating role names

By prefixing a rolename with ! you state the method or view is inaccessible to any role holder with that role.

// This restricts access to the list method to any role holder with a "foo" role but no "bar" role.  If a "bar" role is present, access is denied.
@Restrict({"foo", "!bar"})
public static void list()

The same applies in views:

This restricts view rendering for the content to any role holder with a "foo" role but no "bar" role.  If a "bar" role is present, rendering is skipped.
#{deadbolt.restrict roles:[['foo', '!bar']]}
    ...
#{/deadbolt.restrict}

Combining regular and negated role names in views

By nesting regular and negated role names in a view, you can have very fine-grained control over what is displayed. For example,

#{deadbolt.restrict roles:[['foo', 'bar', 'gee']]}
    something
    #{deadbolt.restrict roles:[['!bar']]}
        something only visible to role holders who aren't "bar"s
    #{/deadbolt.restrict}
    something else
#{/deadbolt.restrict}