I’m trying to migrate an old Play application to Play 2.7 starting by zero and I encounter some issues.
In my main template I used something like that to enable some menus items: @if(session.get(“role”) == “SUPERADMIN” || session.get(“role”) == “ADMIN”)
now session.get is deprecated.
Which is the new syntax?
Authentication. Before 2.7 I used something like that:
public class Secured extends Security.Authenticator {
@Override
public String getUsername(Http.Context ctx) {
return ctx.session().get("id");
}
@Override
public Result onUnauthorized(Http.Context ctx) {
ctx.flash().put("danger", "You need to login before access the application.");
return redirect(controllers.routes.HomeController.login());
}
}
and in the controller I used:
@Security.Authenticated(Secured.class)
public Result index() {
return ok(index.render());
}
Now everything seems to be deprecated. But if I use only @Security.Authenticated() I’m unable to enter in the method cause: Unauthorized You must be authenticated to access this page.
To authenticate the user I use the following method:
public Result authenticate(Http.Request request) {
DynamicForm requestData = formFactory.form().bindFromRequest(request);
String email = requestData.get("email").trim();
String password = requestData.get("password").trim();
User user = userRepository.findByEmail(email);
if (user == null) {
return redirect(routes.HomeController.login()).flashing("danger", "Incorrect email or password.");
}
if(!checkPassword(password, user.getPassword())) {
return redirect(routes.HomeController.login()).flashing("danger", "Incorrect email or password.");
}
return redirect(routes.HomeController.index()).addingToSession(request, "role", user.getRole()).
addingToSession(request,"email", user.getEmail()).
addingToSession(request, "id", user.getId());
}
Have I to set something in my authentication method?
I can answer your first question.
You need to explicitly pass in an instance of play.mvc.Http.Request into your template, and use request.session().getOptional("role").orElse(null).
I agree. Reminds me of the change in 2.6 where you need to explicitly pass in the HttpExecutionContext for certain cases. While I understand why, but it feels more and more cumbersome and sometimes cause runtime errors if missed.
For the second question, I think to had solved as follow:
public class Secured extends Security.Authenticator {
@Override
public Optional getUsername(Http.Request ctx) {
return ctx.session().getOptional("id");
}
@Override
public Result onUnauthorized(Http.Request ctx) {
return redirect(controllers.routes.HomeController.login()).flashing("danger", "You need to login before access the application.");
}
}
The funny thing is that HttpExecutionContext only exists because of Http.Context which uses a thread-local and then needs tricks when you are moving the execution from one thread to another one. As soon as Http .Context disappears, I’m pretty sure HttpExecutionContext can also disappear as well. In the end what we want is to move away from a thread-local that you need to worry about, gives the wrong expectations (can Http.Context.current() be accessed from anywhere? Why not?), is hard to test, to debug and to reason about when it fails.
I understand that passing the request to your view may be verbose and we will try to find ways to reduce it. Suggestions from users are very welcomed, by the way. How would you make the session data available without passing it as a parameter and without the thread-local problems?
I totally agree with the removal of Http.Context.current(), for all the reasons you and the team have listed, i.e. promotes (indirectly as a side effect) bad design patterns and usages, etc…
I am excited to hear that HttpExecutionContext can also go away. Is this already happening or a WIP for future enhancements?
I use Play mostly as backend API services, so having to pass request objects around in templates does not affect me as much, and the few templates I do have, I am already passing in the request object due to some weird i18n issues, but I can see it being annoy for others.
It is not happening yet. We have a stale PR now to remove most of the things related to Http.Context. But since we didn’t deprecate HttpExecutionContext in 2.7, we will first do it in the next major release, and later removed. For now, that are no concrete plans yet. So stay tuned.
Another issue. In 2.6 I created a little template to use in all the other templates (as @wflash()) for display flash message based on a severity, like the following:
You can submit a PR to add specific information about the Authenticator changes. As you can see there, we tried to have very complete examples of what the code was before and after the migration.