Action composition
Using the DeadboltActions
class, you can compose constrained functions. To get started, inject DeadboltActions
into your controller.
class ExampleController @Inject() (deadbolt: DeadboltActions) extends Controller
You now have functions equivalent to those of the builders mentioned above. In the following examples I'm using the default handler, i.e. no handler is specified, but it's also possible to use a different handler with handler = <some handler, possibly from the handler cache>
.
SubjectPresent and SubjectNotPresent
Sometimes, you don't need fine-grained checks - you just need to see if there is a user present (or not present).
// DeadboltHandler#getSubject must result in a Some for access to be granted
def someFunctionA = deadbolt.SubjectPresent()() { authRequest =>
Future {
Ok("Content accessible")
}
}
// DeadboltHandler#getSubject must result in a None for access to be granted
def someFunctionB = deadbolt.SubjectNotPresent()() { authRequest =>
Future {
Ok("Content accessible")
}
}
Restrict
This uses the Subject
's Role
s to perform AND/OR/NOT checks. The values given to the builder must match the Role.name
of the subject's roles.
AND is defined as an Array[String]
(or more correctly, String*
, OR is a List[Array[String]]
, and NOT is a rolename with a !
preceding it.
// subject must have the "foo" role
def restrictedFunctionA = deadbolt.Restrict(List(Array("foo")))() { authRequest =>
Future {
Ok("Content accessible")
}
}
// subject must have the "foo" AND "bar" roles
def restrictedFunctionB = deadbolt.Restrict(List(Array("foo", "bar")))() { authRequest =>
Future {
Ok("Content accessible")
}
}
// subject must have the "foo" OR "bar" roles
def restrictedFunctionC = deadbolt.Restrict(List(Array("foo"), Array("bar")))() { authRequest =>
Future {
Ok("Content accessible")
}
}
That whole and/or/array/list thing looks pretty ugly, so instead you can use anyOf
, allOf
and allOfGroup
from the be.objectify.deadbolt.scala
package object instead.
allOf
can be used to define an AND relationship, e.g.Array("foo", "bar")
can be written asallOf("foo", "bar")
- this would then need to be placed in a list for use within a restriction.anyOf
can be used to define an OR relationship, e.g.List(Array("foo"), Array("bar"))
can be written asanyOf(allOf("foo"), allOf("bar"))
.allOfGroup
is a convenient way of defining a single AND relationship, e.g.List(Array("foo", "bar"))
can be written asallOfGroup("foo", "bar")
.
This means the previous template can be rewritten as follows.
// subject must have the "foo" role
def restrictedFunctionA = deadbolt.Restrict(allOfGroup("foo"))() { authRequest =>
Future {
Ok("Content accessible")
}
}
// subject must have the "foo" AND "bar" roles
def restrictedFunctionB = deadbolt.Restrict(allOfGroup("foo", "bar"))() { authRequest =>
Future {
Ok("Content accessible")
}
}
// subject must have the "foo" OR "bar" roles
def restrictedFunctionC = deadbolt.Restrict(anyOf(allOf("foo"), allOf("bar")))() { authRequest =>
Future {
Ok("Content accessible")
}
}
Pattern
This uses the Subject
's Permission
s to perform a variety of checks.
// subject must have a permission with the exact value "admin.printer"
def permittedFunctionA = deadbolt.Pattern(value = "admin.printer",
patternType = PatternType.EQUALITY)() { authRequest =>
Future {
Ok("Content accessible")
}
}
// subject must have a permission that matches the regular expression (without quotes) "(.)*\.printer"
def permittedFunctionB = deadbolt.Pattern(value = "(.)*\.printer",
patternType = PatternType.REGEX)() { authRequest =>
Future {
Ok("Content accessible")
}
}
// the checkPermssion function of the current handler's DynamicResourceHandler will be used. This is a user-defined test in DynamicResourceHandler#checkPermission
def permittedFunctionC = deadbolt.Pattern(value = "something arbitrary",
patternType = PatternType.CUSTOM)() { authRequest =>
Future {
Ok("Content accessible")
}
}
// the checkPermssion function of the current handler's DynamicResourceHandler will be used. Additional information is passed to it via the meta parameter. This is a user-defined test in DynamicResourceHandler#checkPermission
def permittedFunctionC = deadbolt.Pattern(value = "something arbitrary",
patternType = PatternType.CUSTOM,
meta = Some("this can be an Option[Any]"))() { authRequest =>
Future {
Ok("Content accessible")
}
}
// subject must have no permissions with the exact value "admin.printer"
def permittedFunctionA = deadbolt.Pattern(value = "admin.printer",
patternType = PatternType.EQUALITY,
invert = true)() { authRequest =>
Future {
Ok("Content accessible")
}
}
Dynamic
The most flexible constraint - this is a completely user-defined constraint that uses DynamicResourceHandler#isAllowed
to determine access.
def foo = deadbolt.Dynamic(name = "someClassifier")() { authRequest =>
Future {
Ok("Content accessible")
}
}
You can also pass addition information to the constraint using the meta
parameter.
def foo = deadbolt.Dynamic(name = "someClassifier",
meta = Some("this can be an Option[Any]"))() { authRequest =>
Future {
Ok("Content accessible")
}
}
Updated less than a minute ago