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 #358 from akkie/master
Browse files Browse the repository at this point in the history
Migrate SecuredSettings to HttpErrorHandler
  • Loading branch information
akkie committed May 23, 2015
2 parents 3de134e + d7c1955 commit 55af950
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
*/
package com.mohiva.play.silhouette.api

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

import scala.concurrent.Future

/**
* Can be mixed into the GlobalSettings object to define a global behaviour
* Can be mixed into the `HttpErrorHandler` object to define a global behaviour
* for unauthorized and forbidden endpoints.
*/
trait SecuredSettings {
this: GlobalSettings =>
trait SecuredErrorHandler {
this: HttpErrorHandler =>

/**
* Called when a user is not authenticated.
Expand Down
14 changes: 7 additions & 7 deletions silhouette/app/com/mohiva/play/silhouette/api/Silhouette.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
logger.debug("[Silhouette] Unauthenticated user trying to access '%s'".format(request.uri))

onNotAuthenticated(request).orElse {
Play.current.global match {
case s: SecuredSettings => s.onNotAuthenticated(request, request2Messages)
Play.current.errorHandler match {
case s: SecuredErrorHandler => s.onNotAuthenticated(request, request2Messages)
case _ => None
}
}.getOrElse(DefaultEndpointHandler.handleNotAuthenticated)
Expand All @@ -144,8 +144,8 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
logger.debug("[Silhouette] Unauthorized user trying to access '%s'".format(request.uri))

onNotAuthorized(request).orElse {
Play.current.global match {
case s: SecuredSettings => s.onNotAuthorized(request, request2Messages)
Play.current.errorHandler match {
case s: SecuredErrorHandler => s.onNotAuthorized(request, request2Messages)
case _ => None
}
}.getOrElse(DefaultEndpointHandler.handleNotAuthorized)
Expand Down Expand Up @@ -452,11 +452,11 @@ trait Silhouette[I <: Identity, A <: Authenticator] extends Controller with Logg
* the [[com.mohiva.play.silhouette.api.Silhouette.onNotAuthorized]] methods.
*
* If these methods are not implemented, then
* the [[com.mohiva.play.silhouette.api.SecuredSettings.onNotAuthenticated]] or
* the [[com.mohiva.play.silhouette.api.SecuredSettings.onNotAuthorized]] methods
* the [[com.mohiva.play.silhouette.api.SecuredErrorHandler.onNotAuthenticated]] or
* the [[com.mohiva.play.silhouette.api.SecuredErrorHandler.onNotAuthorized]] methods
* will be called as fallback.
*
* If the [[com.mohiva.play.silhouette.api.SecuredSettings]] trait isn't implemented,
* If the [[com.mohiva.play.silhouette.api.SecuredErrorHandler]] trait isn't implemented,
* a default message will be displayed.
*/
object SecuredAction extends SecuredActionBuilder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* Copyright 2015 Mohiva Organisation (license at mohiva dot com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mohiva.play.silhouette.api

import javax.inject.Inject

import com.mohiva.play.silhouette.api.SecuredErrorHandlerSpec._
import org.specs2.specification.Scope
import play.api.http.{ DefaultHttpErrorHandler, HttpErrorHandler }
import play.api.i18n.{ Lang, Messages, MessagesApi }
import play.api.inject.Module
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.routing.Router
import play.api.test.{ FakeRequest, PlaySpecification, WithApplication }
import play.api.{ Configuration, OptionalSourceMapper }

/**
* Test case for the [[com.mohiva.play.silhouette.api.SecuredErrorHandler]] trait.
*/
class SecuredErrorHandlerSpec extends PlaySpecification {

"The `SilhouetteErrorHandler` implementation" should {
"return None as default value for onNotAuthenticated method " in new WithApplication with Context {
handler.onNotAuthenticated(FakeRequest(GET, "/"), messages) should beNone
}

"return None as default value for onNotAuthenticated method " in new WithApplication with Context {
handler.onNotAuthorized(FakeRequest(GET, "/"), messages) should beNone
}
}

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

/**
* The injector instance.
*/
lazy val injector = new GuiceApplicationBuilder().overrides(new Module {
def bindings(env: play.api.Environment, conf: Configuration) = Seq(
bind[HttpErrorHandler].to[ErrorHandler]
)
}).injector()

/**
* The messages for the current language.
*/
val messages = Messages(Lang("en-US"), injector.instanceOf[MessagesApi])

/**
* The error handler to test.
*/
val handler = injector.instanceOf[HttpErrorHandler].asInstanceOf[SecuredErrorHandler]
}
}

/**
* The companion object.
*/
object SecuredErrorHandlerSpec {

/**
* A custom error handler.
*/
class ErrorHandler @Inject() (
env: play.api.Environment,
config: Configuration,
sourceMapper: OptionalSourceMapper,
router: javax.inject.Provider[Router])
extends DefaultHttpErrorHandler(env, config, sourceMapper, router)
with SecuredErrorHandler
}

This file was deleted.

89 changes: 58 additions & 31 deletions silhouette/test/com/mohiva/play/silhouette/api/SilhouetteSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,31 @@
*/
package com.mohiva.play.silhouette.api

import javax.inject.Inject

import akka.actor.{ Actor, Props }
import akka.testkit.TestProbe
import com.mohiva.play.silhouette.api.exceptions.{ NotAuthorizedException, NotAuthenticatedException }
import com.mohiva.play.silhouette.api.SilhouetteSpec._
import com.mohiva.play.silhouette.api.exceptions.{ NotAuthenticatedException, NotAuthorizedException }
import com.mohiva.play.silhouette.api.services.{ AuthenticatorResult, AuthenticatorService, IdentityService }
import org.specs2.matcher.JsonMatchers
import org.specs2.mock.Mockito
import org.specs2.specification.Scope
import play.api.GlobalSettings
import play.api.i18n.{ MessagesApi, Lang, Messages }
import play.api.http.{ DefaultHttpErrorHandler, HttpErrorHandler }
import play.api.i18n.{ Lang, Messages, MessagesApi }
import play.api.inject.Module
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.concurrent.Akka
import play.api.libs.json.Json
import play.api.mvc.Results._
import play.api.mvc._
import play.api.routing.Router
import play.api.test.{ FakeApplication, FakeRequest, PlaySpecification, WithApplication }
import play.api.{ Configuration, OptionalSourceMapper }

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.reflect.ClassTag

/**
Expand Down Expand Up @@ -885,36 +892,16 @@ class SilhouetteSpec extends PlaySpecification with Mockito with JsonMatchers {
}

/**
* Runs a fake application with a secured global object.
* Runs a fake application with a secured error handler.
*/
class WithSecuredGlobal extends WithApplication(FakeApplication(withGlobal = Some(new GlobalSettings with SecuredSettings {

/**
* Called when a user isn't authenticated.
*
* @param request The request header.
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
override def onNotAuthenticated(request: RequestHeader, messages: Messages) = {
Some(Future.successful(Unauthorized("global.not.authenticated")))
}

/**
* Called when a user isn't authorized.
*
* @param request The request header.
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
override def onNotAuthorized(request: RequestHeader, messages: Messages) = {
Some(Future.successful(Forbidden("global.not.authorized")))
}

}))) with Context
class WithSecuredGlobal extends WithApplication(new GuiceApplicationBuilder().overrides(new Module {
def bindings(env: play.api.Environment, conf: Configuration) = Seq(
bind[HttpErrorHandler].to[ErrorHandler]
)
}).build()) with Context

/**
* Runs a fake application with a default global object.
* Runs a fake application with a default error handler.
*/
class WithDefaultGlobal extends WithApplication(FakeApplication()) with Context

Expand Down Expand Up @@ -1065,3 +1052,43 @@ class SilhouetteSpec extends PlaySpecification with Mockito with JsonMatchers {
}
}
}

/**
* The companion object.
*/
object SilhouetteSpec {

/**
* A secured error handler.
*/
class ErrorHandler @Inject() (
env: play.api.Environment,
config: Configuration,
sourceMapper: OptionalSourceMapper,
router: javax.inject.Provider[Router])
extends DefaultHttpErrorHandler(env, config, sourceMapper, router)
with SecuredErrorHandler {

/**
* Called when a user isn't authenticated.
*
* @param request The request header.
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
override def onNotAuthenticated(request: RequestHeader, messages: Messages) = {
Some(Future.successful(Unauthorized("global.not.authenticated")))
}

/**
* Called when a user isn't authorized.
*
* @param request The request header.
* @param messages The messages for the current language.
* @return The result to send to the client.
*/
override def onNotAuthorized(request: RequestHeader, messages: Messages) = {
Some(Future.successful(Forbidden("global.not.authorized")))
}
}
}

0 comments on commit 55af950

Please sign in to comment.