Skip to content
This repository has been archived by the owner on Sep 12, 2021. It is now read-only.

Commit

Permalink
Merge pull request #335 from akkie/messages-api
Browse files Browse the repository at this point in the history
Implement the new Play 2.4 messages API
  • Loading branch information
akkie committed May 6, 2015
2 parents 0eca774 + 3634238 commit db99501
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.mohiva.play.silhouette.api.util.Clock
import com.mohiva.play.silhouette.impl.authenticators._
import com.mohiva.play.silhouette.impl.daos.AuthenticatorDAO
import com.mohiva.play.silhouette.impl.util.{ DefaultFingerprintGenerator, SecureRandomIDGenerator }
import play.api.i18n.MessagesApi
import play.api.mvc.RequestHeader

import scala.collection.mutable
Expand Down Expand Up @@ -210,13 +211,15 @@ object FakeAuthenticator {
* @param identities A list of (login info -> identity) pairs to return inside a Silhouette action.
* @param requestProviders The list of request providers.
* @param eventBus The event bus implementation.
* @param messagesApi The Play messages API.
* @tparam I The type of the identity.
* @tparam T The type of the authenticator.
*/
case class FakeEnvironment[I <: Identity, T <: Authenticator: TypeTag](
identities: Seq[(LoginInfo, I)],
requestProviders: Seq[RequestProvider] = Seq(),
eventBus: EventBus = EventBus())
eventBus: EventBus = EventBus())(
implicit val messagesApi: MessagesApi)
extends Environment[I, T] {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
*/
package com.mohiva.play.silhouette.test

import com.mohiva.play.silhouette.api.{ Silhouette, Environment, LoginInfo }
import javax.inject.Inject

import com.mohiva.play.silhouette.api.{ Environment, LoginInfo, Silhouette }
import com.mohiva.play.silhouette.impl.authenticators._
import org.specs2.matcher.JsonMatchers
import org.specs2.specification.Scope
import play.api.i18n.MessagesApi
import play.api.libs.json.Json
import play.api.test.{ FakeRequest, PlaySpecification, WithApplication }

Expand Down Expand Up @@ -117,7 +121,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
}

"The `FakeAuthenticator` factory" should {
"return a `SessionAuthenticator`" in {
"return a `SessionAuthenticator`" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, SessionAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -126,7 +130,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
FakeAuthenticator[SessionAuthenticator](loginInfo) must beAnInstanceOf[SessionAuthenticator]
}

"return a `CookieAuthenticator`" in new WithApplication {
"return a `CookieAuthenticator`" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, CookieAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -135,7 +139,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
FakeAuthenticator[CookieAuthenticator](loginInfo) must beAnInstanceOf[CookieAuthenticator]
}

"return a `BearerTokenAuthenticator`" in {
"return a `BearerTokenAuthenticator`" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, BearerTokenAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -144,7 +148,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
FakeAuthenticator[BearerTokenAuthenticator](loginInfo) must beAnInstanceOf[BearerTokenAuthenticator]
}

"return a `JWTAuthenticator`" in {
"return a `JWTAuthenticator`" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, JWTAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -153,7 +157,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
FakeAuthenticator[JWTAuthenticator](loginInfo) must beAnInstanceOf[JWTAuthenticator]
}

"return a `DummyAuthenticator`" in {
"return a `DummyAuthenticator`" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, DummyAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -164,7 +168,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
}

"The `securedAction` method of the `SecuredController`" should {
"return a 401 status code if no authenticator was found" in new WithApplication {
"return a 401 status code if no authenticator was found" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
val env = FakeEnvironment[FakeIdentity, CookieAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -176,7 +180,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
status(result) must equalTo(UNAUTHORIZED)
}

"return a 401 status code if authenticator but no identity was found" in new WithApplication {
"return a 401 status code if authenticator but no identity was found" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, CookieAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -188,7 +192,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
status(result) must equalTo(UNAUTHORIZED)
}

"return a 200 status code if authenticator and identity was found" in new WithApplication {
"return a 200 status code if authenticator and identity was found" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, CookieAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -203,7 +207,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
}

"The `userAwareAction` method of the `SecuredController`" should {
"return a 401 status code if no authenticator was found" in new WithApplication {
"return a 401 status code if no authenticator was found" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
val env = FakeEnvironment[FakeIdentity, CookieAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -215,7 +219,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
status(result) must equalTo(UNAUTHORIZED)
}

"return a 401 status code if authenticator but no identity was found" in new WithApplication {
"return a 401 status code if authenticator but no identity was found" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)
implicit val env = FakeEnvironment[FakeIdentity, CookieAuthenticator](Seq(loginInfo -> identity))
Expand All @@ -227,9 +231,10 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
status(result) must equalTo(UNAUTHORIZED)
}

"return a 200 status code if authenticator and identity was found" in new WithApplication {
"return a 200 status code if authenticator and identity was found" in new WithApplication with Context {
val loginInfo = LoginInfo("test", "test")
val identity = FakeIdentity(loginInfo)

implicit val env = FakeEnvironment[FakeIdentity, CookieAuthenticator](Seq(loginInfo -> identity))
val request = FakeRequest().withAuthenticator(loginInfo)

Expand All @@ -246,7 +251,7 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
*
* @param env The Silhouette environment.
*/
class SecuredController(
class SecuredController @Inject() (
val env: Environment[FakeIdentity, CookieAuthenticator])
extends Silhouette[FakeIdentity, CookieAuthenticator] {

Expand All @@ -271,4 +276,16 @@ class FakesSpec extends PlaySpecification with JsonMatchers {
}
}
}

/**
* The context.
*/
trait Context extends Scope {
self: WithApplication =>

/**
* The Play messages API.
*/
implicit val messagesApi: MessagesApi = app.injector.instanceOf[MessagesApi]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
package com.mohiva.play.silhouette.api

import play.api.i18n.Lang
import play.api.i18n.Messages
import play.api.mvc.RequestHeader

/**
Expand All @@ -35,10 +35,10 @@ trait Authorization[I <: Identity] {
*
* @param identity The identity to check for.
* @param request The current request header.
* @param lang The current lang.
* @param messages The messages for the current language.
* @return True if the user is authorized, false otherwise.
*/
def isAuthorized(identity: I)(implicit request: RequestHeader, lang: Lang): Boolean
def isAuthorized(identity: I)(implicit request: RequestHeader, messages: Messages): Boolean
}

/**
Expand All @@ -59,7 +59,7 @@ object Authorization {
* @return The authorization.
*/
def unary_! : Authorization[I] = new Authorization[I] {
def isAuthorized(identity: I)(implicit request: RequestHeader, lang: Lang): Boolean = {
def isAuthorized(identity: I)(implicit request: RequestHeader, messages: Messages): Boolean = {
!self.isAuthorized(identity)
}
}
Expand All @@ -71,7 +71,7 @@ object Authorization {
* @return The authorization.
*/
def &&(authorization: Authorization[I]): Authorization[I] = new Authorization[I] {
def isAuthorized(identity: I)(implicit request: RequestHeader, lang: Lang): Boolean = {
def isAuthorized(identity: I)(implicit request: RequestHeader, messages: Messages): Boolean = {
self.isAuthorized(identity) && authorization.isAuthorized(identity)
}
}
Expand All @@ -83,7 +83,7 @@ object Authorization {
* @return The authorization.
*/
def ||(authorization: Authorization[I]): Authorization[I] = new Authorization[I] {
def isAuthorized(identity: I)(implicit request: RequestHeader, lang: Lang): Boolean = {
def isAuthorized(identity: I)(implicit request: RequestHeader, messages: Messages): Boolean = {
self.isAuthorized(identity) || authorization.isAuthorized(identity)
}
}
Expand Down
12 changes: 11 additions & 1 deletion silhouette/app/com/mohiva/play/silhouette/api/Environment.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.mohiva.play.silhouette.api

import com.mohiva.play.silhouette.api.services.{ AuthenticatorService, IdentityService }
import play.api.i18n.MessagesApi

/**
* The environment needed to instantiate a Silhouette controller.
Expand Down Expand Up @@ -49,6 +50,13 @@ trait Environment[I <: Identity, T <: Authenticator] {
* @return The event bus implementation.
*/
def eventBus: EventBus

/**
* The Play messages API.
*
* @return The Play messages API.
*/
def messagesApi: MessagesApi
}

/**
Expand All @@ -59,10 +67,12 @@ object Environment {
identityServiceImpl: IdentityService[I],
authenticatorServiceImpl: AuthenticatorService[T],
requestProvidersImpl: Seq[RequestProvider],
eventBusImpl: EventBus) = new Environment[I, T] {
eventBusImpl: EventBus,
messagesApiImpl: MessagesApi) = new Environment[I, T] {
val identityService = identityServiceImpl
val authenticatorService = authenticatorServiceImpl
val requestProviders = requestProvidersImpl
val eventBus = eventBusImpl
val messagesApi = messagesApiImpl
}
}
26 changes: 13 additions & 13 deletions silhouette/app/com/mohiva/play/silhouette/api/EventBus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package com.mohiva.play.silhouette.api

import akka.event.{ SubchannelClassification, ActorEventBus, LookupClassification }
import akka.util.Subclassification
import play.api.i18n.Lang
import play.api.i18n.Messages
import play.api.mvc.RequestHeader

/**
Expand All @@ -30,58 +30,58 @@ trait SilhouetteEvent
*
* @param identity The newly created identity.
* @param request The request header for the associated request.
* @param lang The lang associated for the current request.
* @param messages The messages for the current language.
* @tparam I The type of the identity.
*/
case class SignUpEvent[I <: Identity](identity: I, request: RequestHeader, lang: Lang) extends SilhouetteEvent
case class SignUpEvent[I <: Identity](identity: I, request: RequestHeader, messages: Messages) extends SilhouetteEvent

/**
* An event which will be published after an identity logged in.
*
* @param identity The logged in identity.
* @param request The request header for the associated request.
* @param lang The lang associated for the current request.
* @param messages The messages for the current language.
* @tparam I The type of the identity.
*/
case class LoginEvent[I <: Identity](identity: I, request: RequestHeader, lang: Lang) extends SilhouetteEvent
case class LoginEvent[I <: Identity](identity: I, request: RequestHeader, messages: Messages) extends SilhouetteEvent

/**
* An event which will be published after an identity logged out.
*
* @param identity The logged out identity.
* @param request The request header for the associated request.
* @param lang The lang associated for the current request.
* @param messages The messages for the current language.
* @tparam I The type of the identity.
*/
case class LogoutEvent[I <: Identity](identity: I, request: RequestHeader, lang: Lang) extends SilhouetteEvent
case class LogoutEvent[I <: Identity](identity: I, request: RequestHeader, messages: Messages) extends SilhouetteEvent

/**
* An event which will be published if a request passes authentication.
*
* @param identity The logged in identity.
* @param request The request header for the associated request.
* @param lang The lang associated for the current request.
* @param messages The messages for the current language.
* @tparam I The type of the identity.
*/
case class AuthenticatedEvent[I <: Identity](identity: I, request: RequestHeader, lang: Lang) extends SilhouetteEvent
case class AuthenticatedEvent[I <: Identity](identity: I, request: RequestHeader, messages: Messages) extends SilhouetteEvent

/**
* An event which will be published if a request did not pass authentication.
*
* @param request The request header for the associated request.
* @param lang The lang associated for the current request.
* @param messages The messages for the current language.
*/
case class NotAuthenticatedEvent(request: RequestHeader, lang: Lang) extends SilhouetteEvent
case class NotAuthenticatedEvent(request: RequestHeader, messages: Messages) extends SilhouetteEvent

/**
* An event which will be published if a request did not pass authorization.
*
* @param identity The logged in identity.
* @param request The request header for the associated request.
* @param lang The lang associated for the current request.
* @param messages The messages for the current language.
* @tparam I The type of the identity.
*/
case class NotAuthorizedEvent[I <: Identity](identity: I, request: RequestHeader, lang: Lang) extends SilhouetteEvent
case class NotAuthorizedEvent[I <: Identity](identity: I, request: RequestHeader, messages: Messages) extends SilhouetteEvent

/**
* An event bus implementation which uses a class based lookup classification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package com.mohiva.play.silhouette.api

import play.api.GlobalSettings
import play.api.i18n.Lang
import play.api.i18n.Messages
import play.api.mvc.{ RequestHeader, Result }

import scala.concurrent.Future
Expand All @@ -34,19 +34,19 @@ trait SecuredSettings {
* As defined by RFC 2616, the status code of the response should be 401 Unauthorized.
*
* @param request The request header.
* @param lang The currently selected language.
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
def onNotAuthenticated(request: RequestHeader, lang: Lang): Option[Future[Result]] = None
def onNotAuthenticated(request: RequestHeader, messages: Messages): Option[Future[Result]] = None

/**
* Called when a user is authenticated but not authorized.
*
* As defined by RFC 2616, the status code of the response should be 403 Forbidden.
*
* @param request The request header.
* @param lang The currently selected language.
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
def onNotAuthorized(request: RequestHeader, lang: Lang): Option[Future[Result]] = None
def onNotAuthorized(request: RequestHeader, messages: Messages): Option[Future[Result]] = None
}
Loading

0 comments on commit db99501

Please sign in to comment.