I'm migrating an existing Java Play 2.5 application to Scala and found in the view main.scala.html the use of the following deadbolt-2 class subjectPresentOr:
@subjectPresentOr() {
<ul class="nav navbar-nav navbar-right">
@defining(userProvider.getUser(session())) { user =>
... user is present html
}
} {
... user is NOT present html
}
After migrating all controllers and actions to Scala (and changing the deadbolt-2 dependency from Java -> Scala) I get the following compiler error due to the fact that subjectPresentOr requires an implicit request of type AuthenticatedRequest[Any]:
main.scala.html:49: could not find implicit value for parameter request:
be.objectify.deadbolt.scala.AuthenticatedRequest[Any]
and I have some intuition why ... some times e.g. when the user is not yet logged in there is no request of type deadbolt-2's AuthenticatedRequest[_] but the superclass type play.api.mvc.RequestHeader and it can't be rightfully so implicitly matched with its subclass AuthenticatedRequest[_].
The question is why this works in the Java version in the first place? The Java version of @subjectPresentOr doesn't require any implicit request :)
To fix it in the Scala version I would wrap the @subjectPresentOr block with pattern matching to discover the dynamic type of the implicit request and only if its dynamic type is AuthenticatedRequest[_] I will then show the block and pass to @subjectPresentOr explicitly the narrowed request of that type. This is not super elegant though but I can't figure any other way ...
The Java version of Play has a
Http.Contextavailable to it via ThreadLocals, whereas the Scala version uses requests. These may be implicit or explicit.Looking at your controllers, when you add Deadbolt to an action you will receive an
AuthenticatedRequest. So, a non-Deadbolt action ofwould receive a
requestof typeRequest, whereas the same action protected by Deadboltreceives a
requestof typeAuthenticatedRequest.If you want to convert a
Requestto anAuthenticatedRequestbecause you're calling a template that contains Deadbolt constraints yet your controller action is unconstrained, you can useWithAuthRequestAction:If you're injecting
DeadboltActionsin place ofActionBuilders, the same holds true:You can also just create an instance of
AuthenticatedRequestfrom the existingRequestand with noSubjectby usingnew AuthenticatedRequest(request, None).