Template constraints

Using template constraints, you can exclude portions of templates from being generated on the server-side. This is not a client-side DOM manipulation! Template constraints have the same possibilities as controller constraints.

By default, template constraints use the default Deadbolt handler but as with controller constraints you can pass in a specific handler. The cleanest way to do this is to pass the handler into the template and then pass it into the constraints. Another advantage of this approach is you can pass in a wrapped version of the handler that will cache the subject; if you have a lot of constraints in a template, this can yield a significant gain.

One important thing to note here is that templates are blocking, so any Futures used need to be completed for the result to be used in the template constraints. As a result, each constraint can take a function that expresses a Long, which is the millisecond value of the timeout. It defaults to 1000 milliseconds, but you can change this globally by setting the deadbolt.java.view-timeout value in your application.conf.

Each constraint has a variant which allows you to define fallback content. This comes in the format <constraintName>Or, e.g.

@subjectPresentOr() {
  this is protected
} {
  this will be shown if the constraint blocks the other content
}

Global state vs dependency injection in templates

Play 2.6 has deprecated global state, and so Deadbolt templates have been updated to be dependency injected instead of relying on implicit values. All templates in the Deadbolt library have been moved from the be.objectify.deadbolt.java.views.html package to be.objectify.deadbolt.java.views.html.di to make this change explicit.

If you're migrating to Play 2.6 but don't want to migrate your templates, you can add the old templates back into your build by adding the following dependency.

"be.objectify" %% "deadbolt-java-gs" % "2.6.0"

This is a drop-in library, so you don't need to do any migration at all in your templates.

SubjectPresent

@import be.objectify.deadbolt.java.views.html.di.{subjectPresent, subjectPresentOr}

@subjectPresent() {
    This content will be present if handler#getSubject results in a Some 
}

@subjectPresentOr() {
    This content will be present if handler#getSubject results in a Some 
} {
  fallback content
}

SubjectNotPresent

@import be.objectify.deadbolt.java.views.html.di.{subjectNotPresent, subjectNotPresentOr}

@subjectNotPresent() {
    This content will be present if handler#getSubject results in a None 
}

@subjectNotPresentOr() {
    This content will be present if handler#getSubject results in a None 
} {
  fallback content
}

Restrict

allOf and anyOf are convenience functions for creating a List[Array] and an Array[String]. Older documentation and examples may refer to as and la - these have been deprecated in favour of the more descriptive allOf and anyOf, but functionality remains the same.

@import be.objectify.deadbolt.java.views.html.di.{restrict, restrictOr}
@import be.objectify.deadbolt.java.utils.TemplateUtils.{allOf, anyOf}

@restrict(roles = anyOf(allOf("foo", "bar"))) {
    Subject requires the foo role for this to be visible
}

@restrict(roles = anyOf(allOf("foo", "bar"))) {
     Subject requires the foo AND bar roles for this to be visible
}

@restrict(roles = anyOf(allOf("foo"), allOf("bar"))) {
     Subject requires the foo OR bar role for this to be visible
}

@restrictOr(roles = anyOf(allOf("foo", "bar"))) {
     Subject requires the foo AND bar roles for this to be visible
} {
  Subject does not have the necessary roles
}

Having to wrap an Array in a LIst eveny time is pretty annoying, so you can instead use allOfGroup. This would allow the previous template to be rewritten as follows.

@import be.objectify.deadbolt.java.views.html.di.{restrict, restrictOr}
@import be.objectify.deadbolt.java.utils.TemplateUtils.{allOf, anyOf, allOfGroup}

@restrict(roles = allOfGroup("foo", "bar")) {
    Subject requires the foo role for this to be visible
}

@restrict(roles = allOfGroup("foo", "bar")) {
     Subject requires the foo AND bar roles for this to be visible
}

@restrict(roles = anyOf(allOf("foo"), allOf("bar"))) {
     Subject requires the foo OR bar role for this to be visible
}

@restrictOr(roles = allOfGroup("foo", "bar")) {
     Subject requires the foo AND bar roles for this to be visible
} {
  Subject does not have the necessary roles
}

Pattern

The default pattern type is PatternType.EQUALITY.

@import be.objectify.deadbolt.java.views.html.di.{pattern, patternOr}

@pattern(value = "admin.printer") {
    Subject must have a permission with the exact value "admin.printer" for this to be visible
}

@pattern(value = "(.)*\.printer", patternType = PatternType.REGEX) {
  Subject must have a permission that matches the regular expression (without quotes) "(.)*\.printer" for this to be visible
}

@pattern(value = "something arbitrary", patternType = PatternType.CUSTOM) {
  DynamicResourceHandler#checkPermission must result in true for this to be visible
}

@patternOr(value = "admin.printer") {
    Subject must have a permission with the exact value "admin.printer" for this to be visible
} {
  Subject did not have necessary permissions
}

Dynamic

@import be.objectify.deadbolt.java.views.html.di.{dynamic, dynamicOr}

@dynamic(name = "someName") {
    DynamicResourceHandler#isAllowed must result in true for this to be visible
}

@dynamicOr(name = "someName") {
    DynamicResourceHandler#isAllowed must result in true for this to be visible
} {
  Custom test failed
}