Scala pass function as argument and execute conditionally - scala

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.

Related

Verifying Function is called in Spray/Akka Router using Scala and Mockito

I'm trying to verify that a function in a router is being called but everytime I do, I get this error saying that there were no interactions with the mock object.
The function I would like to verify is the doStuff function so I'm mocking the modelService object.
This is my setup:
//Router
val foo(user: String, _: String, containerId: Long) => pathPrefix("foo"){
path("bar") {
post {
entity(as[someJson]) { report =>
val actions = () => (for {
msg <- eitherT((someActor? reportFunction(report.name, report.modelsTasks, user)).mapTo[\/[String, reportJson]])
id <- eitherT(Future.successful(msg.id.toRightDisjunction("Cannot obtain id")))
model <- eitherT(modelService.doStuff(user, id, containerId, report.asReportComponent()).
map(_.right[String]))
} yield model).run
handleResult(actions())
}
}
}
}
\\Test
"do some stuff when asked" in {
when(modelService.doStuff(eqTo("unknown"),
any[String], eqTo(1L), any[reportComponent]))
.thenReturn(Future.successful(expectedApp))
Post("/foo/bar", someJson("Test")) ~>
foo("unknown", "127.0.0.1", 1L) ~> check {
verify( modelService, times(1) ).doStuff(eqTo("unknown"), any[String], eqTo(1L), any[reportComponent])
}
}
But each time I run my test, I get something like this
Wanted but not invoked:
modelService.doStuff(
"unknown",
<any>,
1,
<any>
);
-> at com.this.test.spec.apply(ThisTestSpec.scala:112)
Actually, there were zero interactions with this mock.
How are you injecting the mock? could you post how you create your router class in the test?
Also, did you check that msg <- eitherT and id <- eitherT are returning a valid value? otherwise the modelService is never going to be called

scala returning a Future[Option[user]]

So, I am totally new to Scala, coming from a Java background and have been given a huge scala code base to learn. And, I am very lost and would appreciate any help.
I have the below function that I want to re-arrange. Currently, the function calls two functions in a row and then returns the result. The first function returns a boolean and the second function returns a User. However, what actually should happen is that the second function should only be called if the first function returns true. So, I need to rearrange it to check the return value of the first function before continuing. Every time I rewrite it to do that, I either get a compile error or exception. It is supposed to return a Future[Option[User]] and the first function doesn't return a User. I just want to return None if FunctionA fails, but because it expects Future[Option[X]]], it is unhappy. So, below is the function:
private def profileForCredentials(userId: String, password: String)(implicit ec: ExecutionContext): Future[Option[User]] =
{
val credentials: Throwable \/ Boolean = {
try {
FunctionA(userId, password).right[Throwable]
}
catch {
case npe: NullPointerException =>
npe.left[Boolean]
}
}
//This function doesn't need to be called unless credentials=true
FunctionB(id, userId).map {
case maybeUser#Some(user) =>
credentials match {
case \/-(x) if x =>
user.some
case _ =>
None
}
case None =>
None
}
}
You guys just got carried away with the scalaz.
I am going to bookmark this page to show people at work as an illustration why we should not be using all this fancy stuff.
Just do this:
Try {
FunctionA(userId, password)
}
.toOption
.collect { case(true) =>
FunctionB(id, userId)
}
.getOrElse(Future.value(None))

Why does it need implicit arg if code works without it

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)

Unable to find Writable inside Action.async in play framework

Appears I am missing something but here is what I have got (posting only relevant piece). where MyService.save returns Future[Option[MyCompany] ].
def myPost = Action.async(parse.json) { request =>
val mn = Json.fromJson[MyEntity](request.body)
mn.map{
case m : MyEntity => MyService.save(m).map{f=>
f.map(mm=> Ok(mm ) )
}
}.recoverTotal {
e => Future { BadRequest("Detected error:" + JsError.toFlatJson(e)) }
}
}
Although I have defined
implicit val companyWriter: Writes[MyCompany] = (...)
And this implicit is in the scope, it shows compile error
Cannot write an instance of MyCompany to HTTP response. Try to define
a Writeable[MyCompany]
FYI: This writer is used elsewhere where I do Json.toJson(myCompany) and over there it finds and works fine.
Anything in particular to async Ok that it's missing?
EDIT
It appears that Ok() method cannot figure out the MyCompany needs to be transformed to json. following seems to have worked.
Ok(Json.toJson(mm) )
Is this because arguments to Ok can vary? Separately there are too many "map" in the above code. Any recommendation for improvement and making it more concise ?
Your compiler error is about a Writeable, not a Writes. Writeables are used to convert whatever you have to something that can be written to an HTTP response, Writes are used to marshall objects to JSON. The names can be a little confusing.
As for style...
def myPost = Action.async(parse.json) { request =>
request.body.validate[MyEntity] map { myEntity =>
MyService.save(myEntity).map { maybeCompany =>
maybeCompany match {
case Some(company) => Ok(Json.toJson(company))
case None => NoContent // or whatever's appropriate
}
}
} recoverTotal { t =>
Future { BadRequest("Detected error: " + JsError.toFlatJson(e)) }
}
}

Serving rest requests: how to avoid code duplication

In the rest part of my lift application I often have code like this:
object UserRest extends RestHelper {
serve("user" :: Nil prefix {
case Req("remove-item" :: itemId :: Nil, "json", PostRequest) => {
User.currentUser.map{ u =>
//doing some things and returning message
"Ready, all right."
}.getOrElse("You must be logged in to perform this operation.")
}: JValue
case Req("update-item" :: itemId :: Nil, "json", PostRequest) => {
User.currentUser.map{ u =>
//doing some things and returning message
"Ready, all right."
}.getOrElse("You must be logged in to perform this operation.")
}: JValue
}
}
As you can see for every user operation I have this piece of code:
User.currentUser.map{ u =>
//...
}.getOrElse("You must be logged in to perform this operation.")
My question is - do I have a way to put this piece of code to one place to avoid repeating it for every request?
You could write a function to handle unboxing objects for you. Something like this should help:
def unbox[A](t:Box[A])(a: A => JValue) = {
val msg = "You must be logged in to perform this operation."
t.map { u => a(u) }.getOrElse(JString(msg))
}
Then, you'd just call it like :
unbox(User.current){ u:User =>
//doing something
JString("Ready, all right.")
}
If you are just doing this for the purposes of authentication, you should be able to use guarded LiftRules.dispatch calls. Described in Simply Lift and in more detail here.
You may also just be able to use LiftRules.httpAuthProtectedResource(UserRest), but I'm not really sure about that.