0

I am testing Deadbolt in a Scala Play Application. My controller methods look something like this:

def getProject(projectId: Int) = actionBuilder.RestrictAction("user").defaultHandler()  {
    authRequest =>
    //retrieves project
}

In this case, I only want the user to be authorized to get the project if the projectId belongs to this user. Other more complex cases involve multiple parameters both from the query string and/or the post body.

From what I understand, the approach here would be to pass the parameters to a DynamicResourceHandler and then handling the permissions for each case individually. It is feasible, but I was expecting a bit more support from Deadbolt for this use case. What is the best approach to authorize a request based on the parameters received?

nmat
  • 7,430
  • 6
  • 30
  • 43

1 Answers1

1

Deadbolt stays fairly neutral to avoid forcing developers into a specific style, but in this case you can use the meta argument to pass the information into the constraint. The definition is

  object DynamicAction {

    def apply(name: String, meta: Option[Any] = None): DynamicAction.DynamicActionBuilder = DynamicActionBuilder(name, meta)

    case class DynamicActionBuilder(name: String, meta: Option[Any] = None) extends DeadboltActionBuilder {

      override def apply[A](bodyParser: BodyParser[A])(block: AuthenticatedRequest[A] => Future[Result])(implicit handler: DeadboltHandler) : Action[A] =
        deadboltActions.Dynamic(name, meta, handler)(bodyParser)(block)
    }
  }

so your controller function will look something like this

def getProject(projectId: Int) = actionBuilder.DynamicAction(name = "checkProject", meta = Some(projectId)).defaultHandler()  {
    authRequest =>
    //retrieves project
}

This will get a DynamicResourceHandler (I've come to hate that name, I may change it in some future version) and invoke your implementation of this function

  def isAllowed[A](name: String,
                   meta: Option[Any] = None,
                   deadboltHandler: DeadboltHandler,
                   request: AuthenticatedRequest[A]): Future[Boolean]

You will need to use asInstanceOf for the meta value.

For more complex requirements, you can pass whatever you have assembled the data into (a case class or map, for example) as the meta argument.

Steve Chaloner
  • 8,162
  • 1
  • 22
  • 38
  • Thanks for the answer. That was sort of the way I was thinking to do it yeah. I also read about using deadbolt in routes instead of the controller, but I guess it would be harder for me to access parameter values there right? – nmat Jan 26 '17 at 11:38
  • Indeed - in the routes, you can only hard-code the meta. Alternatively, you can parse the URL yourself to get the value, but that's already becoming pretty heavy. – Steve Chaloner Jan 26 '17 at 11:43