flavian
flavian

Reputation: 28511

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))

Upvotes: 0

Views: 4232

Answers (2)

flavian
flavian

Reputation: 28511

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.

Upvotes: 2

Russell
Russell

Reputation: 12439

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.

Upvotes: 0

Related Questions