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

Commit

Permalink
Merge 9ce592a into 3c860cf
Browse files Browse the repository at this point in the history
  • Loading branch information
joaoraf committed May 10, 2015
2 parents 3c860cf + 9ce592a commit 294b9f4
Show file tree
Hide file tree
Showing 88 changed files with 633 additions and 521 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import play.api.mvc.RequestHeader

import scala.collection.mutable
import scala.concurrent.Future
import scala.concurrent.ExecutionContext
import scala.reflect.runtime.universe._

/**
Expand All @@ -53,7 +54,7 @@ class FakeIdentityService[I <: Identity](identities: (LoginInfo, I)*)
* @param loginInfo The login info to retrieve an identity.
* @return The retrieved identity or None if no identity could be retrieved for the given login info.
*/
def retrieve(loginInfo: LoginInfo): Future[Option[I]] = {
def retrieve(loginInfo: LoginInfo)(implicit ec: ExecutionContext): Future[Option[I]] = {
Future.successful(identities.find(_._1 == loginInfo).map(_._2))
}
}
Expand All @@ -76,7 +77,7 @@ class FakeAuthenticatorDAO[T <: StorableAuthenticator] extends AuthenticatorDAO[
* @param id The authenticator ID.
* @return The found authenticator or None if no authenticator could be found for the given ID.
*/
def find(id: String): Future[Option[T]] = {
def find(id: String)(implicit ec: ExecutionContext): Future[Option[T]] = {
Future.successful(data.get(id))
}

Expand All @@ -86,7 +87,7 @@ class FakeAuthenticatorDAO[T <: StorableAuthenticator] extends AuthenticatorDAO[
* @param authenticator The authenticator to add.
* @return The added authenticator.
*/
def add(authenticator: T): Future[T] = {
def add(authenticator: T)(implicit ec: ExecutionContext): Future[T] = {
data += (authenticator.id -> authenticator)
Future.successful(authenticator)
}
Expand All @@ -97,7 +98,7 @@ class FakeAuthenticatorDAO[T <: StorableAuthenticator] extends AuthenticatorDAO[
* @param authenticator The authenticator to update.
* @return The updated authenticator.
*/
def update(authenticator: T): Future[T] = {
def update(authenticator: T)(implicit ec: ExecutionContext): Future[T] = {
data += (authenticator.id -> authenticator)
Future.successful(authenticator)
}
Expand All @@ -108,7 +109,7 @@ class FakeAuthenticatorDAO[T <: StorableAuthenticator] extends AuthenticatorDAO[
* @param id The authenticator ID.
* @return An empty future.
*/
def remove(id: String): Future[Unit] = {
def remove(id: String)(implicit ec: ExecutionContext): Future[Unit] = {
data -= id
Future.successful(())
}
Expand Down Expand Up @@ -201,7 +202,7 @@ object FakeAuthenticator {
* @tparam T The type of the authenticator,
* @return A authenticator instance.
*/
def apply[T <: Authenticator](loginInfo: LoginInfo)(implicit env: Environment[_, T], requestHeader: RequestHeader): T = {
def apply[T <: Authenticator](loginInfo: LoginInfo)(implicit env: Environment[_, T], requestHeader: RequestHeader, ec: ExecutionContext): T = {
env.authenticatorService.create(loginInfo)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
package com.mohiva.play.silhouette

import com.mohiva.play.silhouette.api._
import play.api.libs.concurrent.Execution.Implicits._
import play.api.test.{ FakeHeaders, FakeRequest }

import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import scala.concurrent.{ Await, Future }
import scala.language.{ implicitConversions, postfixOps }

Expand Down Expand Up @@ -53,8 +53,8 @@ package object test {
* @tparam T The type of the authenticator,
* @return A fake request.
*/
def withAuthenticator[T <: Authenticator](authenticator: T)(implicit env: Environment[_, T]): FakeRequest[A] = {
val rh = env.authenticatorService.init(authenticator)(f).map(v => env.authenticatorService.embed(v, f))
def withAuthenticator[T <: Authenticator](authenticator: T)(implicit env: Environment[_, T], ec: ExecutionContext): FakeRequest[A] = {
val rh = env.authenticatorService.init(authenticator)(f, ec).map(v => env.authenticatorService.embed(v, f))
new FakeRequest(
id = rh.id,
tags = rh.tags,
Expand All @@ -76,8 +76,8 @@ package object test {
* @tparam T The type of the authenticator,
* @return A fake request.
*/
def withAuthenticator[T <: Authenticator](loginInfo: LoginInfo)(implicit env: Environment[_, T]): FakeRequest[A] = {
withAuthenticator(FakeAuthenticator[T](loginInfo)(env, f))
def withAuthenticator[T <: Authenticator](loginInfo: LoginInfo)(implicit env: Environment[_, T], ec: ExecutionContext): FakeRequest[A] = {
withAuthenticator(FakeAuthenticator[T](loginInfo)(env, f, ec))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.mohiva.play.silhouette.impl.authenticators._
import org.specs2.matcher.JsonMatchers
import play.api.libs.json.Json
import play.api.test.{ FakeRequest, PlaySpecification, WithApplication }
import scala.concurrent.ExecutionContext.Implicits.global

/**
* Test case for the [[com.mohiva.play.silhouette.test]] helpers.
Expand Down
3 changes: 2 additions & 1 deletion silhouette/app/com/mohiva/play/silhouette/api/Provider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.mohiva.play.silhouette.api
import play.api.mvc.Request

import scala.concurrent.Future
import scala.concurrent.ExecutionContext

/**
* A marker interface for all providers.
Expand Down Expand Up @@ -54,5 +55,5 @@ trait RequestProvider extends Provider {
* @tparam B The type of the body.
* @return Some login info on successful authentication or None if the authentication was unsuccessful.
*/
def authenticate[B](request: Request[B]): Future[Option[LoginInfo]]
def authenticate[B](request: Request[B])(implicit ec: ExecutionContext): Future[Option[LoginInfo]]
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import play.api.i18n.Messages
import play.api.mvc.{ RequestHeader, Result }

import scala.concurrent.Future
import scala.concurrent.ExecutionContext

/**
* Can be mixed into the GlobalSettings object to define a global behaviour
Expand All @@ -37,7 +38,7 @@ trait SecuredSettings {
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
def onNotAuthenticated(request: RequestHeader, messages: Messages): Option[Future[Result]] = None
def onNotAuthenticated(request: RequestHeader, messages: Messages)(implicit ec: ExecutionContext): Option[Future[Result]] = None

/**
* Called when a user is authenticated but not authorized.
Expand All @@ -48,5 +49,5 @@ trait SecuredSettings {
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
def onNotAuthorized(request: RequestHeader, messages: Messages): Option[Future[Result]] = None
def onNotAuthorized(request: RequestHeader, messages: Messages)(implicit ec: ExecutionContext): Option[Future[Result]] = None
}
55 changes: 28 additions & 27 deletions silhouette/app/com/mohiva/play/silhouette/api/Silhouette.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ import com.mohiva.play.silhouette.api.services.AuthenticatorResult
import com.mohiva.play.silhouette.api.util.DefaultEndpointHandler
import play.api.Play
import play.api.i18n.{ MessagesApi, I18nSupport }
import play.api.libs.concurrent.Execution.Implicits._
////import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc._

import scala.concurrent.Future
import scala.concurrent.ExecutionContext
import scala.language.higherKinds

/**
Expand Down Expand Up @@ -76,7 +77,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The request header.
* @return The result to send to the client.
*/
protected def onNotAuthenticated(request: RequestHeader): Option[Future[Result]] = None
protected def onNotAuthenticated(request: RequestHeader)(implicit ec: ExecutionContext): Option[Future[Result]] = None

/**
* Implement this to return a result when the user is authenticated but not authorized.
Expand All @@ -86,7 +87,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The request header.
* @return The result to send to the client.
*/
protected def onNotAuthorized(request: RequestHeader): Option[Future[Result]] = None
protected def onNotAuthorized(request: RequestHeader)(implicit ec: ExecutionContext): Option[Future[Result]] = None

/**
* Default exception handler for silhouette exceptions which translates an exception into
Expand All @@ -98,7 +99,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The request header.
* @return The result to send to the client based on the exception.
*/
protected def exceptionHandler(implicit request: RequestHeader): PartialFunction[Throwable, Future[Result]] = {
protected def exceptionHandler(implicit request: RequestHeader, ec: ExecutionContext): PartialFunction[Throwable, Future[Result]] = {
case e: NotAuthenticatedException =>
logger.info(e.getMessage, e)
handleNotAuthenticated
Expand All @@ -119,7 +120,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The request header.
* @return The result to send to the client if the user isn't authenticated.
*/
private def handleNotAuthenticated(implicit request: RequestHeader): Future[Result] = {
private def handleNotAuthenticated(implicit request: RequestHeader, ec: ExecutionContext): Future[Result] = {
logger.debug("[Silhouette] Unauthenticated user trying to access '%s'".format(request.uri))

onNotAuthenticated(request).orElse {
Expand All @@ -143,7 +144,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The request header.
* @return The result to send to the client if the user isn't authorized.
*/
private def handleNotAuthorized(implicit request: RequestHeader): Future[Result] = {
private def handleNotAuthorized(implicit request: RequestHeader, ec: ExecutionContext): Future[Result] = {
logger.debug("[Silhouette] Unauthorized user trying to access '%s'".format(request.uri))

onNotAuthorized(request).orElse {
Expand Down Expand Up @@ -180,7 +181,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @tparam T The type of the data included in the handler result.
* @return A handler result.
*/
final def apply[T](block: R[AnyContent] => Future[HandlerResult[T]])(implicit request: Request[AnyContent]): Future[HandlerResult[T]] = {
final def apply[T](block: R[AnyContent] => Future[HandlerResult[T]])(implicit request: Request[AnyContent], ec: ExecutionContext): Future[HandlerResult[T]] = {
invokeBlock(block)
}

Expand All @@ -193,8 +194,8 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @tparam T The type of the data included in the handler result.
* @return A handler result.
*/
final def apply[B, T](request: Request[B])(block: R[B] => Future[HandlerResult[T]]): Future[HandlerResult[T]] = {
invokeBlock(block)(request)
final def apply[B, T](request: Request[B])(block: R[B] => Future[HandlerResult[T]])(implicit ec: ExecutionContext): Future[HandlerResult[T]] = {
invokeBlock(block)(request, ec)
}

/**
Expand All @@ -208,7 +209,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @tparam T The type of the data included in the handler result.
* @return A handler result.
*/
protected def invokeBlock[B, T](block: R[B] => Future[HandlerResult[T]])(implicit request: Request[B]): Future[HandlerResult[T]]
protected def invokeBlock[B, T](block: R[B] => Future[HandlerResult[T]])(implicit request: Request[B], ec: ExecutionContext): Future[HandlerResult[T]]

/**
* Handles a block for an authenticator.
Expand All @@ -221,7 +222,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The current request header.
* @return A handler result.
*/
protected def handleBlock[T](authenticator: Either[A, A], block: A => Future[HandlerResult[T]])(implicit request: RequestHeader) = {
protected def handleBlock[T](authenticator: Either[A, A], block: A => Future[HandlerResult[T]])(implicit request: RequestHeader, ec: ExecutionContext) = {
authenticator match {
case Left(a) => handleInitializedAuthenticator(a, block)
case Right(a) => handleUninitializedAuthenticator(a, block)
Expand All @@ -241,10 +242,10 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @return A tuple which consists of (maybe the existing authenticator on the left or a
* new authenticator on the right -> maybe the identity).
*/
protected def handleAuthentication[B](implicit request: Request[B]): Future[(Option[Either[A, A]], Option[I])] = {
protected def handleAuthentication[B](implicit request: Request[B], ec: ExecutionContext): Future[(Option[Either[A, A]], Option[I])] = {
env.authenticatorService.retrieve.flatMap {
// A valid authenticator was found so we retrieve also the identity
case Some(a) if a.isValid => env.identityService.retrieve(a.loginInfo).map(i => Some(Left(a)) -> i)
case Some(a) if a.isValid => env.identityService.retrieve(a.loginInfo)(ec).map(i => Some(Left(a)) -> i)
// An invalid authenticator was found so we needn't retrieve the identity
case Some(a) if !a.isValid => Future.successful(Some(Left(a)) -> None)
// No authenticator was found so we try to authenticate with a request provider
Expand All @@ -270,7 +271,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The current request header.
* @return A handler result.
*/
private def handleInitializedAuthenticator[T](authenticator: A, block: A => Future[HandlerResult[T]])(implicit request: RequestHeader) = {
private def handleInitializedAuthenticator[T](authenticator: A, block: A => Future[HandlerResult[T]])(implicit request: RequestHeader, ec: ExecutionContext) = {
val auth = env.authenticatorService.touch(authenticator)
block(auth.extract).flatMap {
case hr @ HandlerResult(pr: AuthenticatorResult, _) => Future.successful(hr)
Expand All @@ -294,7 +295,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @param request The current request header.
* @return A handler result.
*/
private def handleUninitializedAuthenticator[T](authenticator: A, block: A => Future[HandlerResult[T]])(implicit request: RequestHeader) = {
private def handleUninitializedAuthenticator[T](authenticator: A, block: A => Future[HandlerResult[T]])(implicit request: RequestHeader, ec: ExecutionContext) = {
block(authenticator).flatMap {
case hr @ HandlerResult(pr: AuthenticatorResult, _) => Future.successful(hr)
case hr @ HandlerResult(pr, _) =>
Expand All @@ -315,7 +316,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @tparam B The type of the request body.
* @return Some identity or None if authentication was not successful.
*/
private def handleRequestProviderAuthentication[B](implicit request: Request[B]): Future[Option[LoginInfo]] = {
private def handleRequestProviderAuthentication[B](implicit request: Request[B], ec: ExecutionContext): Future[Option[LoginInfo]] = {
def auth(providers: Seq[RequestProvider]): Future[Option[LoginInfo]] = {
providers match {
case Nil => Future.successful(None)
Expand Down Expand Up @@ -360,7 +361,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @tparam T The type of the data included in the handler result.
* @return A handler result.
*/
protected def invokeBlock[B, T](block: SecuredRequest[B] => Future[HandlerResult[T]])(implicit request: Request[B]): Future[HandlerResult[T]] = {
protected def invokeBlock[B, T](block: SecuredRequest[B] => Future[HandlerResult[T]])(implicit request: Request[B], ec: ExecutionContext): Future[HandlerResult[T]] = {
handleAuthentication.flatMap {
// A user is both authenticated and authorized. The request will be granted
case (Some(authenticator), Some(identity)) if authorize.isEmpty || authorize.get.isAuthorized(identity) =>
Expand All @@ -369,18 +370,18 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
// A user is authenticated but not authorized. The request will be forbidden
case (Some(authenticator), Some(identity)) =>
env.eventBus.publish(NotAuthorizedEvent(identity, request, request2Messages))
handleBlock(authenticator, _ => handleNotAuthorized(request).map(r => HandlerResult(r)))
handleBlock(authenticator, _ => handleNotAuthorized(request, ec).map(r => HandlerResult(r)))
// An authenticator but no user was found. The request will ask for authentication and the authenticator will be discarded
case (Some(authenticator), None) =>
env.eventBus.publish(NotAuthenticatedEvent(request, request2Messages))
for {
result <- handleNotAuthenticated(request)
result <- handleNotAuthenticated(request, ec)
discardedResult <- env.authenticatorService.discard(authenticator.extract, result)
} yield HandlerResult(discardedResult)
// No authenticator and no user was found. The request will ask for authentication
case _ =>
env.eventBus.publish(NotAuthenticatedEvent(request, request2Messages))
handleNotAuthenticated(request).map(r => HandlerResult(r))
handleNotAuthenticated(request, ec).map(r => HandlerResult(r))
}
}
}
Expand Down Expand Up @@ -423,11 +424,11 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @return A handler result.
*/
def invokeBlock[B](request: Request[B], block: SecuredRequest[B] => Future[Result]) = {
val b = (r: SecuredRequest[B]) => block(r).map(r => HandlerResult(r))
val b = (r: SecuredRequest[B]) => block(r).map(r => HandlerResult(r))(executionContext)
(authorize match {
case Some(a) => SecuredRequestHandler(a)(request)(b)
case None => SecuredRequestHandler(request)(b)
}).map(_.result).recoverWith(exceptionHandler(request))
case Some(a) => SecuredRequestHandler(a)(request)(b)(executionContext)
case None => SecuredRequestHandler(request)(b)(executionContext)
}).map(_.result)(executionContext).recoverWith(exceptionHandler(request, executionContext))(executionContext)
}
}

Expand Down Expand Up @@ -485,7 +486,7 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* @tparam T The type of the data included in the handler result.
* @return A handler result.
*/
protected def invokeBlock[B, T](block: UserAwareRequest[B] => Future[HandlerResult[T]])(implicit request: Request[B]) = {
protected def invokeBlock[B, T](block: UserAwareRequest[B] => Future[HandlerResult[T]])(implicit request: Request[B], ec: ExecutionContext) = {
handleAuthentication.flatMap {
// A valid authenticator was found and the identity may be exists
case (Some(authenticator), identity) if authenticator.extract.isValid =>
Expand Down Expand Up @@ -518,8 +519,8 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
*/
def invokeBlock[B](request: Request[B], block: UserAwareRequest[B] => Future[Result]) = {
UserAwareRequestHandler(request) { r =>
block(r).map(r => HandlerResult(r))
}.map(_.result).recoverWith(exceptionHandler(request))
block(r).map(r => HandlerResult(r))(executionContext)
}(executionContext).map(_.result)(executionContext).recoverWith(exceptionHandler(request, executionContext))(executionContext)
}
}
}
Loading

0 comments on commit 294b9f4

Please sign in to comment.