Reputation: 488
I am using Scala & Play 2.0
I have a URL as such:
/v1/people/search/MTIyOjg3YjYzNmU1YTk5MDdkYjY2MzAyODZiM2RkNTMzYzYw
In my routs file:
POST /v1/people/search/:authToken controllers.v1.Application.searchPeople(authToken: String)
What I am trying to do is create a secure trait and take the :aythToken and validate via a custom Action that replaces it in my function/method call:
Make Action a CustomAuthAction
def searchPeople(authToken: String) = Action { implicit request => }
So that I can reject a request based on the already parsed :authToken without setting this value as a cookie, I already know how to that.
So how can I take the already passed by play :authToken and pass it to a custom action?
Thanks
Here is my solution:
case class CheckSessionRequest(val user: User, request: Request[AnyContent]) extends WrappedRequest(request)
def RequireAuthToken(f: CheckSessionRequest => Result): Action[AnyContent] = {
Action { request =>
UserValidation.findUserByAuthToken(StringUtil.getAuthTokenFromURL(request.toString)).map { user =>
f(CheckSessionRequest(user, request))
}.getOrElse( // STRANGE ERROR
Ok(Json.generate(StatusHandler("failed","Unknown Login Error","{}"))).withHeaders(
CONTENT_TYPE -> "application/json"
)
)
}
}
Upvotes: 0
Views: 230
Reputation: 488
case class CheckSessionRequest(val user: User, request: Request[AnyContent]) extends WrappedRequest(request)
def RequireAuthToken(f: CheckSessionRequest => Result): Action[AnyContent] = {
Action { request =>
UserValidation.findUserByAuthToken(StringUtil.getAuthTokenFromURL(request.toString)).map { user =>
f(CheckSessionRequest(user, request))
}.getOrElse( // STRANGE ERROR
Ok(Json.generate(StatusHandler("failed","Unknown Login Error","{}"))).withHeaders(
CONTENT_TYPE -> "application/json"
)
)
}
}
Then replace your "Action" call with RequireAuthToken
Upvotes: 1
Reputation: 20080
Let me quote the Play documentation:
Most of the requests received by a Play application are handled by an Action.
A play.api.mvc.Action is basically a (play.api.mvc.Request => play.api.mvc.Result) function that handles a request and generates a result to be sent to the client.
If you look to the Action Composition, it clearly explains you how to basically create your CustomAction:
def LoggingAction(f: Request[AnyContent] => Result): Action[AnyContent] = {
Action { request =>
Logger.info("Calling action")
f(request)
}
}
I have done a similar work, and that is the way it looks, it's a little bit more complicated but interesting
trait SecuredController[UserModel<:ValidableEmail] {
type LoggedRequestHandler = UserModel =>Request[AnyContent] => Result
def loggedUser(implicit request:Request[_]):Option[UserModel]
def WithAuthenticatedUser( onUserAuthenticated: => LoggedRequestHandler,
onUserAuthenticatedButEmailNotValidated: LoggedRequestHandler,
onUnauthenticated: Request[AnyContent]=>Result) = {
Action{
implicit request =>
loggedUser match{
case Some(user) if (user.emailValidated) => onUserAuthenticated(user)(request)
case Some(user) if(!user.emailValidated) => onUserAuthenticatedButEmailNotValidated(user)(request)
case None => onUserNotLogged(request)
}
}
}
This trait basically define two methods:
LoggedRequestHandler is just a type alias for a function which take my user UserModel and creates a function Request => Result
Once you have this, you can basically write the following
object EmployeeController extends SecuredController[Employee]{
def loggedUser(implicit request:Request[_]):Option[Employee]
def ViewPay = WithAuthenticatedUser{
ShowPay,
ShowEmailNotValidated,
ShowUserNotLogged
}
def ShowPay(employee:Employee): Request[AnyContent] => Result = {
}
def ShowEmailNotValidated(employee:Employee): Request[AnyContent] => Result = {
}
def ShowUserNotLogged: Request[AnyContent] => Result = {
}
}
Upvotes: 2