Why does it need implicit arg if code works without it - scala

There is Security Example where you can find => implicit request for def withUser(... method.
Based on that example I've created one-file-sample here:
https://github.com/Sergey80/scala-samples/blob/master/src/main/scala/implicits/usecases/RequestResponseTest.scala (where is no implicit .. and I do not see why I need use it)
The question is:
why do I need type implicit request (as was shown in Security Example) if it works without implicit. Since we are already referring on requestas val (defined above in the code).
Copy-pasting my simplified-sample here (where not implicit is used), this code has the same functions as in initial Security Example (withUser, withAtuh) with same set of parameters, the point was just to make it launchable from one file:
package implicits.usecases
object RequestResponseTest extends App {
type User = String // for simplicity sake - all are strings
type Request = String
type Result = String
trait Action // there are two auth Action - Ok and Not Ok
case class OkAction(content:Result) extends Action
case class UnauthorizedAction(content:Result) extends Action
var userDB = List("user1", "user2", "user3") // our simple database
val user = "user1" // usually user available from the session
var request : Request = "request" // current request
// check authorization and wraps request into Action
def withAuth(f: User => (Request => Result) ): Action = {
println("withAuth in play...")
val result:Result = f("user1")(request) // (is user was found or not)
def isAuthorized(user:User): Boolean = {
println("check authorisation...")
true // authorize everyone, welcome :)
}
def onUnAuthorized(request: Request): Action = {
println("wrapped to Action as not authorized")
UnauthorizedAction(request)
}
if (result == "ok") {
if (isAuthorized(request)) {
println("wrapped to Action as authorized")
OkAction(request)
} else onUnAuthorized(request)
} else onUnAuthorized(request)
}
//
def withUser(f: User => (Request => Result)) : Action = {
println("withUser in play...")
def findInDb(user: User): Option[User] = {
userDB.find(u => u == user)
}
val authResult:Action = withAuth ( // call 'withAuth'
/* Create anonymous function to please the 'withAuth'
it is already known who is current user, and what request is, but doesn't what Result is.
And he Result is the fact whether the user exists in users database or not.
So it tries to get the Result by searching for the current user.
If user has been found then it makes sense to continue with Authorisation (withAuth)
*/
user => request => { // passing anonymous function with user, request, and result (where result is based on user existence in the user db )
val userOption = findInDb("user1") // find the user in users db
val result:Result = userOption match { // check if user exists
case Some(_) => // user has been found
println("user has been found")
"ok"
case None => // user has not been found
println("user has not been found")
"not ok"
}
result // "ok" / "not ok" (user has been found or not)
} // end of passing anonymous function to 'withAuth'
)
authResult match {
case OkAction(_) => f(user)(request) // if authorized do The work
}
authResult
} // edn of 'withUser'
// Let's run this and to some work (no `implicit request` here)
def doWork() = withUser { // doWork -> withUser -> withAuth (like Decorator/Wrapper pattern)
user => request => {
// if user exists (withUser) and authorization is ok (withAuth), then this work will done
println("do some important work here!!")
"work is done!" // Result is just a String
}
}
val result = doWork() // doWork doesn't care about user or request
}
/* Output:
withUser in play...
withAuth in play...
user has been found
check authorisation...
wrapped to Action as authorized
do some important work here!!
*/
Update:
I understand if implicit was put on type Request to let compiler look up for value of this type which is defined implicitly somewhere. Like Inversion of Control injection. But there in Security Example it is put on value itself. On "request" value. If I'm putting 'request' it automatically means that I already have access to it and compiler knows about it (without implicit).

One word answer: convenience.
Let's take this simple example from your first link:
def login = Action { implicit request =>
Ok(views.html.login(loginForm))
}
You probably don't need the implicit here, but it's often convenient to have. Here's why:
This is really calling Action.apply. In particular, an overload that accepts a parameter:
block: Request[A] => Result
The block being passed here is the anonymous function:
request => Ok(views.html.login(loginForm))
The Request is probably not being used at all here, so whether it's implicit or not doesn't really matter. However, Play has many functions which require an implicit Request (for i18n, checking the uri accessed, whether or not a secure path was used, etc).
If views.html.login (a Play view) requires an implicit Request parameter, then it would be very useful to mark request as implicit, which we have the option of doing so.
implicit request => Ok(views.html.login(loginForm))
All the above code is doing is creating an anonymous function Request[A] => Result, in which the Request[A] parameter is made implicit. It isn't looking for an implicit, it's creating one. Similar to:
def anon(req: Request[A]): Result = {
implicit val request = req
Ok(views.html.login(loginForm)
}
Why? It makes for a much less boiler-plate, especially when many methods within the block require Request parameters. There's also no ambiguity, because the implicit is contained within the block of the anonymous function, and in this example, there is only one Request that each method should receive (there's only method call in this example, but there could be several more).
Otherwise you'd have to write:
def login = Action { request =>
Ok(views.html.login(loginForm)(request))
}
The withUser example isn't really any different. It just involves another nested anonymous function where request is made implicit.

This simple snippet explained me the thing (let me remember). Kind of essential:
implicit val integer = 3
def function4(implicit i:Int) = i // this works as default variable (ALMOST)
// same as this
def function4_1(i:Int = implicitly[Int]) = i // implicit scope has Int = 3
val result4 = function4 // should be without ()
val result4_1 = function4_1() // requires ()
println("result4: " + result4) // 3
println("result4_1: " + result4_1) // 3
Also I've prepared couple examples here: 1 2 (2 - improving my initial code with Request-Response case)

Related

Play Framework Authentication in a single page app

I am trying to add authentication to my Play Framework single page app.
What I would like to have is something like:
def unsecured = Action {
Ok("This action is not secured")
}
def secured = AuthorizedAction {
// get the authenticated user's ID somehow
Ok("This action is secured")
}
For a traditional web app, I had previously done this, following Play Framework docs:
def authenticate = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.login(formWithErrors)),
user => {
Redirect(routes.Application.home).withSession(Security.username -> user._1)
}
)
}
def logout = Action {
Redirect(routes.Auth.login).withNewSession.flashing(
"success" -> "You are now logged out."
)
}
and the Authorized Action is extending ActionBuilder as follows:
object AuthorizedAction extends ActionBuilder[Request] with Results {
/**
* on auth success: proceed with the request
* on auth failure: redirect to login page with flash
*/
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
// TODO: is "isDefined" enough to determine that user is logged in?
if(request.session.get("username").isDefined) {
block(request)
}
else {
Future.successful(Redirect(routes.Auth.login).flashing(
"failure" -> "You must be logged in to access this page."
))
}
}
}
For single page applications however, this approach doesn't exactly work anymore.
This article by James Ward explains how the new approach is to be designed, and includes a Java implementation:
Securing SPA and rest services
The implementation was redone in Scala by Marius Soutier: Securing SPA in Scala
In his example, he implements a Security trait:
trait Security { self: Controller =>
val cache: CacheApi
val AuthTokenHeader = "X-XSRF-TOKEN"
val AuthTokenCookieKey = "XSRF-TOKEN"
val AuthTokenUrlKey = "auth"
/** Checks that a token is either in the header or in the query string */
def HasToken[A](p: BodyParser[A] = parse.anyContent)(f: String => Long => Request[A] => Result): Action[A] =
Action(p) { implicit request =>
val maybeToken = request.headers.get(AuthTokenHeader).orElse(request.getQueryString(AuthTokenUrlKey))
maybeToken flatMap { token =>
cache.get[Long](token) map { userid =>
f(token)(userid)(request)
}
} getOrElse Unauthorized(Json.obj("err" -> "No Token"))
}
}
Functions are now secured like this instead of a plain Action:
def ping() = HasToken() { token => userId => implicit request =>
user.findByID (userId) map { user =>
Ok(Json.obj("userId" -> userId)).withToken(token -> userId)
} getOrElse NotFound (Json.obj("err" -> "User Not Found"))
}
where .withToken is defined as:
implicit class ResultWithToken(result: Result) {
def withToken(token: (String, Long)): Result = {
cache.set(token._1, token._2, CacheExpiration)
result.withCookies(Cookie(AuthTokenCookieKey, token._1, None, httpOnly = false))
}
def discardingToken(token: String): Result = {
cache.remove(token)
result.discardingCookies(DiscardingCookie(name = AuthTokenCookieKey))
}
}
I am not liking how complex the "ping" function above has become, and would have preferred to use an Action Builder (like the first example), where auth failure is caught and dealt with at a single point. (as of now, if I want to secure functions ping2 and ping3, each one has to check whether the user is found and deal with the "not found" case)
I have tried to put together an action builder, inspired by Marius' implementation, most particularly his use of the cacheApi which is necessary.
However the AuthorizedAction is an object, and cacheApi needs to be injected (so need to change the object to singleton class), or cannot be declared in an object without being defined.
I also feel like the AuthorizedAction needs to remain an object, in order to be used as:
def secured = AuthorizedAction {
Would anyone please clear up the confusion, and possibly help with some implementation details?
Thanks a lot
The simplest way in my opinion is to go with ActionBuilder. You can define an action builder as a class (and pass it some dependencies) or as an object.
First you'll need to define a type a request that will contain the information about the user:
// You can add other useful information here
case class AuthorizedRequest[A](request: Request[A], user: User) extends WrappedRequest(request)
Now define your ActionBuilder
class AuthorizedAction(userService: UserService) extends ActionBuilder[AuthorizedRequest] {
override def invokeBlock[A](request: Request[A], block: (AuthorizedRequest[A]) ⇒ Future[Result]): Future[Result] = {
request.headers.get(AuthTokenHeader).orElse(request.getQueryString(AuthTokenUrlKey)) match {
case Some(token) => userService.findByToken(token).map {
case Some(user) =>
val req = AuthorizedRequest(request, user)
block(req)
case None => Future.successful(Results.Unauthorized)
}
case None => Future.successful(Results.Unauthorized)
}
}
}
Now you can use it in your controller:
val authorizedAction = new AuthorizedAction(userService)
def ping = authorizedAction { request =>
Ok(Json.obj("userId" -> request.user.id))
}

Asynchronous wait for database-value in Playframework (2.4-M3) and Slick (3.0.0-RC3)

I'd like to keep my application as asynchronously as possible. Now I have this repository:
object LanguageRepository extends LanguageRepositoryTrait
{
private val languages = TableQuery[Languages]
private def db:Database = Database.forDataSource(DB.getDataSource())
private def filterQuery(id: Long): Query[Languages, Language, Seq] = languages.filter(_.id === id)
private def filterCode(code: String): Query[Languages, Language, Seq] = languages.filter(_.code === code)
private def all() : Query[Languages, Language, Seq] = languages
override def find(id: Long): Future[Language] =
{
try db.run(filterQuery(id).result.head)
finally db.close()
}
override def find(code: String): Future[Language] =
{
try db.run(filterCode(code).result.head)
finally db.close()
}
override def get(): Future[Seq[Language]] =
{
try db.run(all().result)
finally db.close()
}
}
When I call a url like "domain.tld/{language}" I want to check whether the given language(code) actually exists. Like, if the site isn't available in french (fr) I want to throw an exception or a 404.
Now, my problem is that this whole asynchronously thing is pretty cool and while I do think to understand the theory behind it, I'm rather baffled right now. I mean, I want this to be non-blocking (and asynchronously, which is the reason for me using Future and async ;))
In my controller I want to do something like:
def checkLanguage(language:String) = Action
{
val lang:Future[Language] = languageRepository.find(language)
lang.onComplete
{
case Success(s) = Ok("Yay")
case Failure(f) = 404("Oh no!")
}
}
Of course this can't work, but that's a schema of how I want to have things working. I want to wait or postpone the rendering of the site, until it's confirmed that the given language-code is valid or invalid.
I had a look at the Playframeworks async-documentation for 2.3.6 (https://www.playframework.com/documentation/2.3.6/ScalaAsync) but I couldn't really get this to work as intended.
Any input appreciated!
From your db query don't use .head instead use .headOption. that way ur return type will be a Future [Option [x]]
In ur controller u can do something like this
Lang.map { case Some (x) => Ok (x)
case None => 404 ( "not found ")
}
Try this,
Action.async {
val lang:Future[Option[Language]] = languageRepository.find(language)
lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
}
First of all, I am assuming that if there is a possibility that a language will not exist then languageRepository.find(language) should return an Option of Language. Change Future[Language] to Future[Result] and use Action.async instead of Action
Now for some explanation, Action takes a block whose result should be Result. However, what you get is Future[Option[Language]]. Play provides async method for Action which needs Future[Result] and it takes cares of completing the request.
So, you need to convert Future[Option[Language]] to Future[Result].
lang.map {l => l.map{_ => Ok("Yay") }.getOrElse(NotFound("Oh no!"))
We map over the lang, if the Option[Language] is not None then we convert it to Ok("yay") else we convert it to NotFound
Even, If you don't get Option[Language], the idea remains the same. Convert Future[Language] to Future[Result] and use Action.async instead of Action

How to wrap Actions (in any order) when using Play's ActionBuilder?

I am using Play's ActionBuilder to create various Actions that secure my controllers. For instance, I implemented IsAuthenticated to make sure that certain actions can only be accessed if the user would be logged in:
case class AuthRequest[A](user: String, request: Request[A]) extends WrappedRequest[A](request)
private[controllers] object IsAuthenticated extends ActionBuilder[AuthRequest] {
def invokeBlock[A](req: Request[A], block: (AuthRequest[A]) => Future[SimpleResult]) = {
req.session.get("user").map { user =>
block(new AuthRequest(user, req))
} getOrElse {
Future.successful(Results.Unauthorized("401 No user\n"))
}
}
}
Using IsAuthenticated I can (1) restrict an action to users who are logged in, and (b) access the user being logged in:
def auth = IsAuthenticated { implicit authRequest =>
val user = authRequest.user
Ok(user)
}
Furthermore, I use ActionBuilder HasToken to ensure that an action was invoked with a token being present in the request's header (and, I can access the token value):
case class TokenRequest[A](token: String, request: Request[A]) extends WrappedRequest[A](request)
private[controllers] object HasToken extends ActionBuilder[TokenRequest] {
def invokeBlock[A](request: Request[A], block: (TokenRequest[A]) => Future[SimpleResult]) = {
request.headers.get("X-TOKEN") map { token =>
block(TokenRequest(token, request))
} getOrElse {
Future.successful(Results.Unauthorized("401 No Security Token\n"))
}
}
}
That way, I can make sure that an action was called with that token present:
def token = HasToken { implicit tokeRequest =>
val token = tokeRequest.token
Ok(token)
}
So far, so good...
But, how could I wrap (or, nest / compose) such actions as those defined above? For instance, I would like to ensure (a) that a user would be logged in and (b) that the token would be present:
def tokenAndAuth = HasToken { implicit tokeRequest =>
IsAuthenticated { implicit authRequest =>
val token = tokeRequest.token
val user = authRequest.user
}
}
However, the above action does not compile. I tried many different implementations but always failed to achieve the desired behavior.
In general terms: How could I compose Actions defined using Play's ActionBuilder in arbitrary order? In the above example, it would not matter if I would wrap IsAuthenticated in HasToken or the other way around -- the effect would be the same: the user would have to be logged in and would have to present the token.
Note: I have created a Gist that provides the complete source code.
ActionBuilder
ActionBuilders are not made for ad-hoc composition, but rather to build a hierarchy of actions so you end up using only a couple of actions throughout your controllers.
So in your example you should build IsAuthenticated on top of HasToken as I illustrated here.
This is a viable solution and can actually simplify your code. How often do you really need to compose on the spot?
EssentialAction
Ad-hoc composition could be achieved with EssentialActions (simply because they haven't changed from 2.1), but they have a few downsides, as Johan pointed out. Their API is not really intended for ad-hoc use either, and Iteratees are too low-level and too cumbersome for controller actions.
Actions
So finally your last option would be to write Actions directly. Actions do not support passing a WrappedRequest by default (that's why ActionBuilder exists). However you can still pass a WrappedRequest and have the next Action deal with it.
The following is the best I have come up with so far and is rather fragile I guess.
case class HasToken[A](action: Action[A]) extends Action[A] {
def apply(request: Request[A]): Future[SimpleResult] = {
request.headers.get("X-TOKEN") map { token =>
action(TokenRequest(token, request))
} getOrElse {
Future.successful(Results.Unauthorized("401 No Security Token\n"))
}
}
lazy val parser = action.parser
}
case class IsAuthenticated[A](action: Action[A]) extends Action[A] {
def apply(request: Request[A]): Future[SimpleResult] = {
request.session.get("user").map { user =>
action(new AuthRequest(user, request))
} getOrElse {
Future.successful(Results.Unauthorized("401 No user\n"))
}
}
lazy val parser = action.parser
}
object ActionComposition extends Controller {
def myAction = HasToken {
Action.async(parse.empty) { case TokenRequest(token, request) =>
Future {
Ok(token)
}
}
}
def myOtherAction = IsAuthenticated {
Action(parse.json) { case AuthRequest(user, request) =>
Ok
}
}
def both = HasToken {
IsAuthenticated {
Action(parse.empty) { case AuthRequest(user, request: TokenRequest[_]) =>
Ok(request.token)
}
}
}
}
Results
You can also compose at the Result level and only use the built-in actions. This is especially useful when trying to factor out error handling and other repetitive stuff. I have an example here.
Conclusion
We are still missing the capabilities that Play 2.1's action composition offered. So far to me it seems that ActionBuilder + Result composition is the winner as its successor.
The output from an action builder is an action, an action is essentially a function from request => future result, so you can actually just call it like this:
def tokenAndAuth = HasToken.async { implicit tokenRequest =>
IsAuthenticated { implicit authRequest =>
val token = tokenRequest
val user = authRequest.user
Ok("woho!")
}(tokenRequest) // <-- call the inner action yourself, returns Future[SimpleResult]
}
There may be problems if there is a body that you want to parse though, I think it will be parsed by the body parser of the outer request but I'm not sure what the inner one will do if you would specify a parser.
The reason why you cannot do this in a simpler way is that you do not only want to compose logic but also pass data into each action, if you had actions that would just bail on missing auth or token you could absolutely compose them as the play docs on action composition describes.
Side note: since you are only looking at headers and not accessing the body in either of your custom action decorators it might be a better idea to look into EssentialAction:s as those would let you reject the request without first parsing the body when auth or token is missing.

Scala pass function as argument and execute conditionally

Say I have an object with a method called protect.
This is supposed to take a function with JValue => JValue(non generic parameters).
def protect(func: (JValue) => JValue) = {
if (Something.is) {
InMemoryResponse(Array(), Nil, Nil, 200)
} else {
InMemoryResponse(Array(), Nil, Nil, 401)
}
}
How can I now call the function passing its original argument?
The goal is to check if a user session exists before responding to a REST request. If it doesn't then a 401 Forbidden will be returned automatically, so something like the following. In this case I want to pass Users.getUsers as the argument function and limit as the param to the function.
So inside protect, if the Session exists the function will execute and display.
serve {
case "user" :: limit :: Nil JsonGet _ =>
AuthorizedReq.protect(json => Users.getUsers(limit))
I ended up using this:
object AuthorizedReq extends Logger {
private[this] val error: JValue = ("error" -> "Unauthorized request");
def protect(func: (JValue) => JValue, json: JValue): JValue = {
if (LoginSession.is) {
new OkResponse
func(json)
} else {
new UnauthorizedResponse
error;
}
}
}
}
In combination with:
serve {
case "user" :: limit :: Nil JsonPost json -> _ =>
for {
json <- AuthorizedReq.protect(json => Users.getUsers(json), json)
} yield json: JValue
}
If the user is not authenticated, server responds with 401, otherwise the original function executes. It should be easy enough to introduce roles and realms.
This replaces Lift's default auth mechanism, which lacks documentation.
As far as I can see you're not actually passing the function Users.getUsers as a parameter. You're passing a function which calls this function, using the limit parameter.
Because when you create the anonymous function that you're passing as a parameter you also create a closure, the value of limit is still available to the function (although not visible to you). You should be able to just call func with no arguments and have it work fine.

Overloaded method error in Scala Play Framework

I am writing a method to set the session cookie properly after a user authenticates. Setting the cookies as follows does not work. The following snippet results in an error with the 'withSession' call:
Overloaded method value [withSession] cannot be applied to ((String, Long))
Code:
/**
* Process login form submission.
*/
def authenticate = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.login(formWithErrors)),
credentials => {
val user = models.User.findByEmail(credentials._1)
user match {
case Some(u) => {
Redirect(routes.Dashboard.index).withSession(Security.username -> u.id)
}
case None => Redirect(routes.Auth.login)
}
}
)
}
'credentials' is simply a tuple with the email and password submitted by the user. If I get rid of 'withSession' part then it runs fine. If I move the 'Redirect' statement out of the pattern matching code then is works fine. Why does it not work as I have it above and how do I fix it?
I think withSession expects a String, String
Have a look at http://www.playframework.org/documentation/api/2.0.3/scala/index.html#play.api.mvc.SimpleResult
def withSession(session: (String, String)*): PlainResult = withSession(Session(session.toMap))