Here is an example of authorization from the file playback documentation (version 2.0.4; I tried to find a newer version of this document, but could not):
trait Secured { def username(request: RequestHeader) = request.session.get(Security.username) def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Auth.login) def withAuth(f: => String => Request[AnyContent] => Result) = { Security.Authenticated(username, onUnauthorized) { user => Action(request => f(user)(request)) } } def withUser(f: User => Request[AnyContent] => Result) = withAuth { username => implicit request => UserDAO.findOneByUsername(username).map { user => f(user)(request) }.getOrElse(onUnauthorized(request)) } }
All in all, it's pretty simple, and I would like to go with something like this.
Now, in Play 2.4, it is recommended not to use singletones anymore (e.g. UserDAO above), but instead of classes and runtimes (see the migration guide or DI docs ).
For example, my service and repository classes are defined as follows:
class AuthService @Inject()(accountRepo: AccountRepository) { } class AccountRepository { }
When using Play 2.4 and DI, what is the recommended / "right" / easiest way to get a service or DAO (for example, AuthService in my case or UserDAO in the sample document) to hell as Secured ?
Or should you now implement authorization for controllers in a completely different way than using this feature?
I can make it work in the following directions:
trait Secured { val authService = GuiceUtils.inject[AuthService] // ... }
Using Helper Assistant:
object GuiceUtils { lazy val injector = new GuiceApplicationBuilder().injector() def inject[T: ClassTag]: T = injector.instanceOf[T] }
But according to the answer in a related question :
In Play, you can use the injector directly while the dash app makes sense. But this is not considered good practice in production code.
If so, then what considered good practice in this use case?