Skip to content

Commit 315151a

Browse files
committed
Merge pull request jaliss#511 from danielkza/fix-hardcoded-execution-context
Fix hardcoded execution context
2 parents cc33a1c + c667be7 commit 315151a

36 files changed

+93
-99
lines changed

module-code/app/securesocial/controllers/LoginApi.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ trait BaseLoginApi[U] extends SecureSocial[U] {
4949
val logger = play.api.Logger("securesocial.controllers.BaseLoginApi")
5050

5151
def authenticate(providerId: String, builderId: String) = Action.async { implicit request =>
52-
import ExecutionContext.Implicits.global
5352
val result = for (
5453
builder <- env.authenticatorService.find(builderId);
5554
provider <- env.providers.get(providerId) if provider.isInstanceOf[ApiSupport]
@@ -85,7 +84,7 @@ trait BaseLoginApi[U] extends SecureSocial[U] {
8584

8685
def logout = Action.async { implicit request =>
8786
import securesocial.core.utils._
88-
import ExecutionContext.Implicits.global
87+
8988
env.authenticatorService.fromRequest(request).flatMap {
9089
case Some(authenticator) => Ok("").discardingAuthenticator(authenticator)
9190
case None => Future.successful(Ok(""))

module-code/app/securesocial/controllers/LoginPage.scala

-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ trait BaseLoginPage[U] extends SecureSocial[U] {
7676
user <- request.user
7777
authenticator <- request.authenticator
7878
} yield {
79-
import ExecutionContext.Implicits.global
8079
redirectTo.discardingAuthenticator(authenticator).map {
8180
_.withSession(Events.fire(new LogoutEvent(user)).getOrElse(request.session))
8281
}

module-code/app/securesocial/controllers/MailTokenBasedOperations.scala

-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ abstract class MailTokenBasedOperations[U] extends SecureSocial[U] {
7474
protected def executeForToken(token: String, isSignUp: Boolean,
7575
f: MailToken => Future[Result])(implicit request: RequestHeader): Future[Result] =
7676
{
77-
import scala.concurrent.ExecutionContext.Implicits.global
7877
env.userService.findToken(token).flatMap {
7978
case Some(t) if !t.isExpired && t.isSignUp == isSignUp => f(t)
8079
case _ =>

module-code/app/securesocial/controllers/PasswordChange.scala

+1-4
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ trait BasePasswordChange[U] extends SecureSocial[U] {
6666
* @return a future boolean
6767
*/
6868
def checkCurrentPassword[A](suppliedPassword: String)(implicit request: SecuredRequest[A]): Future[Boolean] = {
69-
import ExecutionContext.Implicits.global
7069
env.userService.passwordInfoFor(request.user).map {
7170
case Some(info) =>
7271
env.passwordHashers.get(info.hasher).exists {
@@ -77,7 +76,6 @@ trait BasePasswordChange[U] extends SecureSocial[U] {
7776
}
7877

7978
private def execute[A](f: Form[ChangeInfo] => Future[Result])(implicit request: SecuredRequest[A]): Future[Result] = {
80-
import ExecutionContext.Implicits.global
8179
val form = Form[ChangeInfo](
8280
mapping(
8381
CurrentPassword ->
@@ -129,7 +127,6 @@ trait BasePasswordChange[U] extends SecureSocial[U] {
129127
errors => Future.successful(BadRequest(env.viewTemplates.getPasswordChangePage(errors))),
130128
info => {
131129
val newPasswordInfo = env.currentHasher.hash(info.newPassword)
132-
import ExecutionContext.Implicits.global
133130
implicit val userLang = request2lang(request)
134131
env.userService.updatePasswordInfo(request.user, newPasswordInfo).map {
135132
case Some(u) =>
@@ -152,4 +149,4 @@ trait BasePasswordChange[U] extends SecureSocial[U] {
152149
* @param currentPassword the user's current password
153150
* @param newPassword the new password
154151
*/
155-
case class ChangeInfo(currentPassword: String, newPassword: String)
152+
case class ChangeInfo(currentPassword: String, newPassword: String)

module-code/app/securesocial/controllers/PasswordReset.scala

-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ trait BasePasswordReset[U] extends MailTokenBasedOperations[U] {
7070
def handleStartResetPassword = CSRFCheck {
7171
Action.async {
7272
implicit request =>
73-
import scala.concurrent.ExecutionContext.Implicits.global
7473
startForm.bindFromRequest.fold(
7574
errors => Future.successful(BadRequest(env.viewTemplates.getStartResetPasswordPage(errors))),
7675
email => env.userService.findByEmailAndProvider(email, UsernamePasswordProvider.UsernamePassword).map {

module-code/app/securesocial/controllers/ProviderController.scala

-2
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ trait BaseProviderController[U] extends SecureSocial[U] {
8787
* @param redirectTo the url the user needs to be redirected to after being authenticated
8888
*/
8989
private def handleAuth(provider: String, redirectTo: Option[String]) = UserAwareAction.async { implicit request =>
90-
import scala.concurrent.ExecutionContext.Implicits.global
9190
val authenticationFlow = request.user.isEmpty
9291
val modifiedSession = overrideOriginalUrl(request.session, redirectTo)
9392

@@ -112,7 +111,6 @@ trait BaseProviderController[U] extends SecureSocial[U] {
112111
logger.debug(s"[securesocial] user completed authentication: provider = ${profile.providerId}, userId: ${profile.userId}, mode = $mode")
113112
val evt = if (mode == SaveMode.LoggedIn) new LoginEvent(userForAction) else new SignUpEvent(userForAction)
114113
val sessionAfterEvents = Events.fire(evt).getOrElse(request.session)
115-
import scala.concurrent.ExecutionContext.Implicits.global
116114
builder().fromUser(userForAction).flatMap { authenticator =>
117115
Redirect(toUrl(sessionAfterEvents)).withSession(sessionAfterEvents -
118116
SecureSocial.OriginalUrlKey -

module-code/app/securesocial/controllers/Registration.scala

-3
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,13 @@ trait BaseRegistration[U] extends MailTokenBasedOperations[U] {
112112
e => {
113113
val email = e.toLowerCase
114114
// check if there is already an account for this email address
115-
import scala.concurrent.ExecutionContext.Implicits.global
116115
env.userService.findByEmailAndProvider(email, UsernamePasswordProvider.UsernamePassword).map {
117116
maybeUser =>
118117
maybeUser match {
119118
case Some(user) =>
120119
// user signed up already, send an email offering to login/recover password
121120
env.mailer.sendAlreadyRegisteredEmail(user)
122121
case None =>
123-
import scala.concurrent.ExecutionContext.Implicits.global
124122
createToken(email, isSignUp = true).flatMap { token =>
125123
env.mailer.sendSignUpEmail(email, token.uuid)
126124
env.userService.saveToken(token)
@@ -154,7 +152,6 @@ trait BaseRegistration[U] extends MailTokenBasedOperations[U] {
154152
def handleSignUp(token: String) = CSRFCheck {
155153
Action.async {
156154
implicit request =>
157-
import scala.concurrent.ExecutionContext.Implicits.global
158155
executeForToken(token, true, {
159156
t =>
160157
form.bindFromRequest.fold(

module-code/app/securesocial/core/OAuth1Provider.scala

+17-11
Original file line numberDiff line numberDiff line change
@@ -34,40 +34,42 @@ import play.api.libs.json.JsValue
3434
*/
3535
trait OAuth1Client {
3636

37-
def retrieveRequestToken(callbackURL: String)(implicit ec: ExecutionContext): Future[RequestToken]
37+
def retrieveRequestToken(callbackURL: String): Future[RequestToken]
3838

39-
def retrieveOAuth1Info(token: RequestToken, verifier: String)(implicit ec: ExecutionContext): Future[OAuth1Info]
39+
def retrieveOAuth1Info(token: RequestToken, verifier: String): Future[OAuth1Info]
4040

4141
def redirectUrl(token: String): String
4242

43-
def retrieveProfile(url: String, info: OAuth1Info)(implicit ec: ExecutionContext): Future[JsValue]
43+
def retrieveProfile(url: String, info: OAuth1Info): Future[JsValue]
44+
45+
implicit def executionContext: ExecutionContext
4446
}
4547

4648
object OAuth1Client {
4749
/**
4850
* A default implementation based on the Play client
4951
* @param serviceInfo
5052
*/
51-
class Default(val serviceInfo: ServiceInfo, val httpService: HttpService) extends OAuth1Client {
53+
class Default(val serviceInfo: ServiceInfo, val httpService: HttpService)(implicit val executionContext: ExecutionContext) extends OAuth1Client {
5254
private[core] val client = OAuth(serviceInfo, use10a = true)
5355
override def redirectUrl(token: String): String = client.redirectUrl(token)
5456

55-
private def withFuture(call: => Either[OAuthException, RequestToken])(implicit ec: ExecutionContext): Future[RequestToken] = Future {
57+
private def withFuture(call: => Either[OAuthException, RequestToken]): Future[RequestToken] = Future {
5658
call match {
5759
case Left(error) => throw error
5860
case Right(token) => token
5961
}
6062
}
6163

62-
override def retrieveOAuth1Info(token: RequestToken, verifier: String)(implicit ec: ExecutionContext) = withFuture {
64+
override def retrieveOAuth1Info(token: RequestToken, verifier: String) = withFuture {
6365
client.retrieveAccessToken(token, verifier)
6466
}.map(accessToken => OAuth1Info(accessToken.token, accessToken.secret))
6567

66-
override def retrieveRequestToken(callbackURL: String)(implicit ec: ExecutionContext) = withFuture {
68+
override def retrieveRequestToken(callbackURL: String) = withFuture {
6769
client.retrieveRequestToken(callbackURL)
6870
}
6971

70-
override def retrieveProfile(url: String, info: OAuth1Info)(implicit ec: ExecutionContext): Future[JsValue] =
72+
override def retrieveProfile(url: String, info: OAuth1Info): Future[JsValue] =
7173
httpService.url(url).sign(OAuthCalculator(serviceInfo.key, RequestToken(info.token, info.secret))).get().map(_.json)
7274
}
7375
}
@@ -102,14 +104,18 @@ object ServiceInfoHelper {
102104
/**
103105
* Base class for all OAuth1 providers
104106
*/
105-
abstract class OAuth1Provider(routesService: RoutesService,
106-
cacheService: CacheService, val client: OAuth1Client) extends IdentityProvider {
107+
abstract class OAuth1Provider(
108+
routesService: RoutesService,
109+
cacheService: CacheService,
110+
val client: OAuth1Client)
111+
extends IdentityProvider {
112+
113+
protected implicit val executionContext = client.executionContext
107114
protected val logger = play.api.Logger(this.getClass.getName)
108115

109116
def authMethod = AuthenticationMethod.OAuth1
110117

111118
def authenticate()(implicit request: Request[AnyContent]): Future[AuthenticationResult] = {
112-
import ExecutionContext.Implicits.global
113119
if (request.queryString.get("denied").isDefined) {
114120
// the user did not grant access to the account
115121
Future.successful(AuthenticationResult.AccessDenied())

module-code/app/securesocial/core/OAuth2Provider.scala

+16-11
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,21 @@ trait OAuth2Client {
3232
val settings: OAuth2Settings
3333
val httpService: HttpService
3434

35-
def exchangeCodeForToken(code: String, callBackUrl: String, builder: OAuth2InfoBuilder)(implicit ec: ExecutionContext): Future[OAuth2Info]
35+
def exchangeCodeForToken(code: String, callBackUrl: String, builder: OAuth2InfoBuilder): Future[OAuth2Info]
3636

37-
def retrieveProfile(profileUrl: String)(implicit ec: ExecutionContext): Future[JsValue]
37+
def retrieveProfile(profileUrl: String): Future[JsValue]
3838

3939
type OAuth2InfoBuilder = WSResponse => OAuth2Info
40+
41+
implicit def executionContext: ExecutionContext
4042
}
4143

4244
object OAuth2Client {
4345

44-
class Default(val httpService: HttpService, val settings: OAuth2Settings) extends OAuth2Client {
46+
class Default(val httpService: HttpService, val settings: OAuth2Settings)(implicit val executionContext: ExecutionContext)
47+
extends OAuth2Client {
4548

46-
override def exchangeCodeForToken(code: String, callBackUrl: String, builder: OAuth2InfoBuilder)(implicit ec: ExecutionContext): Future[OAuth2Info] = {
49+
override def exchangeCodeForToken(code: String, callBackUrl: String, builder: OAuth2InfoBuilder): Future[OAuth2Info] = {
4750
val params = Map(
4851
OAuth2Constants.ClientId -> Seq(settings.clientId),
4952
OAuth2Constants.ClientSecret -> Seq(settings.clientSecret),
@@ -54,22 +57,26 @@ object OAuth2Client {
5457
httpService.url(settings.accessTokenUrl).post(params).map(builder)
5558
}
5659

57-
override def retrieveProfile(profileUrl: String)(implicit ec: ExecutionContext): Future[JsValue] =
60+
override def retrieveProfile(profileUrl: String): Future[JsValue] =
5861
httpService.url(profileUrl).get().map(_.json)
5962
}
6063
}
6164
/**
6265
* Base class for all OAuth2 providers
6366
*/
64-
abstract class OAuth2Provider(routesService: RoutesService,
65-
client: OAuth2Client,
66-
cacheService: CacheService) extends IdentityProvider with ApiSupport {
67+
abstract class OAuth2Provider(
68+
routesService: RoutesService,
69+
client: OAuth2Client,
70+
cacheService: CacheService)
71+
extends IdentityProvider with ApiSupport {
72+
73+
protected implicit val executionContext: ExecutionContext = client.executionContext
6774
protected val logger = play.api.Logger(this.getClass.getName)
6875

6976
val settings = client.settings
7077
def authMethod = AuthenticationMethod.OAuth2
7178

72-
protected def getAccessToken[A](code: String)(implicit request: Request[A], ec: ExecutionContext): Future[OAuth2Info] = {
79+
protected def getAccessToken[A](code: String)(implicit request: Request[A]): Future[OAuth2Info] = {
7380
val callbackUrl = routesService.authenticationUrl(id)
7481
client.exchangeCodeForToken(code, callbackUrl, buildInfo)
7582
.recover {
@@ -91,7 +98,6 @@ abstract class OAuth2Provider(routesService: RoutesService,
9198
}
9299

93100
def authenticate()(implicit request: Request[AnyContent]): Future[AuthenticationResult] = {
94-
import scala.concurrent.ExecutionContext.Implicits.global
95101
val maybeError = request.queryString.get(OAuth2Constants.Error).flatMap(_.headOption).map {
96102
case OAuth2Constants.AccessDenied => Future.successful(AuthenticationResult.AccessDenied())
97103
case error =>
@@ -181,7 +187,6 @@ abstract class OAuth2Provider(routesService: RoutesService,
181187
val malformedJson = Json.obj("error" -> "Malformed json").toString()
182188

183189
def authenticateForApi(implicit request: Request[AnyContent]): Future[AuthenticationResult] = {
184-
import scala.concurrent.ExecutionContext.Implicits.global
185190
val maybeCredentials = request.body.asJson flatMap {
186191
_.validate[LoginJson] match {
187192
case ok: JsSuccess[LoginJson] =>

module-code/app/securesocial/core/RuntimeEnvironment.scala

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import securesocial.core.providers._
66
import securesocial.core.providers.utils.{ Mailer, PasswordHasher, PasswordValidator }
77
import securesocial.core.services._
88

9+
import scala.concurrent.ExecutionContext
910
import scala.collection.immutable.ListMap
1011

12+
import play.api.libs.concurrent.{ Execution => PlayExecution }
1113
/**
1214
* A runtime environment where the services needed are available
1315
*/
@@ -35,6 +37,8 @@ trait RuntimeEnvironment[U] {
3537
val eventListeners: List[EventListener[U]]
3638

3739
val userService: UserService[U]
40+
41+
implicit def executionContext: ExecutionContext
3842
}
3943

4044
object RuntimeEnvironment {
@@ -54,8 +58,8 @@ object RuntimeEnvironment {
5458
override lazy val passwordHashers: Map[String, PasswordHasher] = Map(currentHasher.id -> currentHasher)
5559
override lazy val passwordValidator: PasswordValidator = new PasswordValidator.Default()
5660

57-
override lazy val httpService: HttpService = new HttpService.Default()
58-
override lazy val cacheService: CacheService = new CacheService.Default()
61+
override lazy val httpService: HttpService = new HttpService.Default
62+
override lazy val cacheService: CacheService = new CacheService.Default
5963
override lazy val avatarService: Option[AvatarService] = Some(new AvatarService.Default(httpService))
6064
override lazy val idGenerator: IdGenerator = new IdGenerator.Default()
6165

@@ -65,6 +69,8 @@ object RuntimeEnvironment {
6569
)
6670

6771
override lazy val eventListeners: List[EventListener[U]] = List()
72+
override implicit def executionContext: ExecutionContext =
73+
PlayExecution.defaultContext
6874

6975
protected def include(p: IdentityProvider) = p.id -> p
7076
protected def oauth1ClientFor(provider: String) = new OAuth1Client.Default(ServiceInfoHelper.forProvider(provider), httpService)

module-code/app/securesocial/core/SecureSocial.scala

+7-4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import play.api.mvc.Result
3434
*/
3535
trait SecureSocial[U] extends Controller {
3636
implicit val env: RuntimeEnvironment[U]
37+
implicit def executionContext: ExecutionContext = env.executionContext
3738

3839
/**
3940
* A Forbidden response for ajax clients
@@ -101,12 +102,14 @@ trait SecureSocial[U] extends Controller {
101102
*/
102103
class SecuredActionBuilder(authorize: Option[Authorization[U]] = None)
103104
extends ActionBuilder[({ type R[A] = SecuredRequest[A] })#R] {
105+
106+
override protected implicit def executionContext: ExecutionContext = env.executionContext
107+
104108
private val logger = play.api.Logger("securesocial.core.SecuredActionBuilder")
105109

106110
def invokeSecuredBlock[A](authorize: Option[Authorization[U]], request: Request[A],
107111
block: SecuredRequest[A] => Future[Result]): Future[Result] =
108112
{
109-
import ExecutionContext.Implicits.global
110113
env.authenticatorService.fromRequest(request).flatMap {
111114
case Some(authenticator) if authenticator.isValid =>
112115
authenticator.touch.flatMap { updatedAuthenticator =>
@@ -121,7 +124,6 @@ trait SecureSocial[U] extends Controller {
121124
}
122125
case Some(authenticator) if !authenticator.isValid =>
123126
logger.debug("[securesocial] user tried to access with invalid authenticator : '%s'".format(request.uri))
124-
import ExecutionContext.Implicits.global
125127
notAuthenticatedResult(request).flatMap { _.discardingAuthenticator(authenticator) }
126128
case None =>
127129
logger.debug("[securesocial] anonymous user trying to access : '%s'".format(request.uri))
@@ -147,10 +149,11 @@ trait SecureSocial[U] extends Controller {
147149
* The UserAwareAction builder
148150
*/
149151
class UserAwareActionBuilder extends ActionBuilder[({ type R[A] = RequestWithUser[A] })#R] {
152+
override protected implicit def executionContext: ExecutionContext = env.executionContext
153+
150154
override def invokeBlock[A](request: Request[A],
151155
block: (RequestWithUser[A]) => Future[Result]): Future[Result] =
152156
{
153-
import ExecutionContext.Implicits.global
154157
env.authenticatorService.fromRequest(request).flatMap {
155158
case Some(authenticator) if authenticator.isValid =>
156159
authenticator.touch.flatMap {
@@ -219,7 +222,7 @@ object SecureSocial {
219222
* @tparam U the user type
220223
* @return a future with an option user
221224
*/
222-
def currentUser[U](implicit request: RequestHeader, env: RuntimeEnvironment[U], ec: ExecutionContext): Future[Option[U]] = {
225+
def currentUser[U](implicit request: RequestHeader, env: RuntimeEnvironment[U], executionContext: ExecutionContext): Future[Option[U]] = {
223226
env.authenticatorService.fromRequest.map {
224227
case Some(authenticator) if authenticator.isValid => Some(authenticator.user)
225228
case _ => None

module-code/app/securesocial/core/authenticator/AuthenticatorStore.scala

+5-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import scala.reflect.ClassTag
2525
*
2626
* @tparam A the Authenticator type the store manages
2727
*/
28-
trait AuthenticatorStore[A <: Authenticator[_]] {
28+
abstract class AuthenticatorStore[A <: Authenticator[_]](implicit val executionContext: ExecutionContext) {
2929
/**
3030
* Retrieves an Authenticator from the backing store
3131
*
@@ -60,7 +60,9 @@ object AuthenticatorStore {
6060
* @param cacheService the cache service to use
6161
* @tparam A the Authenticator type
6262
*/
63-
class Default[A <: Authenticator[_]](cacheService: CacheService) extends AuthenticatorStore[A] {
63+
class Default[A <: Authenticator[_]](cacheService: CacheService)(implicit executionContext: ExecutionContext)
64+
extends AuthenticatorStore[A] {
65+
6466
/**
6567
* Retrieves an Authenticator from the cache
6668
*
@@ -80,7 +82,6 @@ object AuthenticatorStore {
8082
* @return the saved authenticator
8183
*/
8284
override def save(authenticator: A, timeoutInSeconds: Int): Future[A] = {
83-
import ExecutionContext.Implicits.global
8485
cacheService.set(authenticator.id, authenticator, timeoutInSeconds).map { _ => authenticator }
8586
}
8687

@@ -94,4 +95,4 @@ object AuthenticatorStore {
9495
cacheService.remove(id)
9596
}
9697
}
97-
}
98+
}

0 commit comments

Comments
 (0)