Scala DeadboltAction然后自定义播放ActionBuilder

时间:2018-06-14 02:23:46

标签: scala playframework deadbolt-2

这是我的问题: 我需要使用deadbolt检查控制器的用户权限,然后在请求中添加一些内容(使用ActionBuilder)。通常使用Play Action Builders将是(action1 andThen action2),但这不适用于DeadboltActions。

这里有一些代码:

ActionBuilder

import javax.inject.Inject
import models.Item
import modules.item.services.ItemServiceClient
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}

class ItemRequest[A](val items: Seq[Item], request: Request[A]) extends WrappedRequest[A](request)

class ItemAction @Inject()(val parser: BodyParsers.Default)(implicit val executionContext: ExecutionContext)
  extends ActionBuilder[ItemRequest, AnyContent] with ActionTransformer[Request, ItemRequest] {
  def transform[A](request: Request[A]): Future[ItemRequest[A]] = {
    ItemServiceClient.getItems.map{
      new ItemRequest(_, request)
    }recover{
      case _ => new ItemRequest(Seq(), request)
    }

  }
}

控制器:

@Singleton
class ItemController @Inject()(cc: ControllerComponents, deadbolt: DeadboltActions, itemAction: ItemAction) extends AbstractController(cc) with I18nSupport {

def createSomething: Action[AnyContent] = (deadbolt.Pattern("Create_Something", PatternType.EQUALITY) andThen itemAction) { implicit request: ItemRequest[AnyContent] =>
            Ok(modules.item.views.html.createSomething(Something.form, request.items))
    }
}
  

[error]未应用的方法仅在需要函数类型时转换为函数。   您可以通过撰写Pattern _Pattern(_,_,_,_,_)(_)(_)代替Pattern来明确转换此内容。

     

[error] def createSomething:Action [AnyContent] =(deadbolt.Pattern(“Create_Deck”,PatternType.EQUALITY)()andThen itemAction).synchronized(){implicit request:ItemRequest [AnyContent] =>

任何已经处理过此事的人?

2 个答案:

答案 0 :(得分:1)

由于DeadboltActions#Pattern返回Action,我认为您无法将其用于Action合成。相反,至少在Deadbolt 2.5.1中,你可能正在寻找be.objectify.deadbolt.scala.SubjectActionBuilder ActionBuilder[AuthenticatedRequest],然后你可以用你的ItemAction来组合。

这是一个简单的例子:

class MyRequest[A](request: Request[A]) extends WrappedRequest(request)
val handler: DeadboltHandler = ???
val action1: ActionFunction[Request, AuthenticatedRequest] = SubjectActionBuilder(None)
val action2: ActionTransformer[Request, MyRequest] = new ActionTransformer[Request, MyRequest] {
  override protected def transform[A](request: Request[A]): Future[MyRequest[A]] = Future.successful(new MyRequest(request))
}
val action3: ActionFunction[Request, MyRequest] = action1 andThen action2

这是一个完成我认为你想做的事情的例子,但不使用动作组合(至少从我认为你的意思):

class MyRequest[A](request: Request[A]) extends WrappedRequest[A](request)
class MyAction extends ActionTransformer[Request, MyRequest] {
  override protected def transform[A](request: Request[A]): Future[MyRequest[A]] =
    Future.successful(new MyRequest(request))
}

val deadboltActions: DeadboltActions = ???

def createSomething: Action[AnyContent] = deadboltActions.Pattern("Create_Something")() { authRequest =>
  ((new MyAction) compose Action).async { request: MyRequest[AnyContent] =>
    Future.successful(Ok(""))
  }(authRequest)
}

答案 1 :(得分:1)

正如Jamie所提到的,当开箱即用的合成实用程序方法不能直接应用时,我们可以使用以下模式回归编写Action

OuterAction { outerRequest =>
  InnerAction { request =>
    // ... some Result
  } (outerRequest)
}

例如,在您的情况下,以下内容可能有效:

val deadboltAction =
  deadbolt.Pattern[AnyContent](
    value = "admin.printer",
    patternType = PatternType.EQUALITY
  )() _

val itemAction = ...

deadboltAction { implicit authRequest: AuthenticatedRequest[AnyContent] =>
  itemAction { implicit request: ItemRequest[AnyContent] => 
    Ok(modules.item.views.html.createSomething(Something.form, request.items))
  } (authRequest)
}

为了整理一下,我们可以创建以下实用程序方法

def deadboltActionWithItemAction(block: ItemRequest[AnyContent] => Result): Action[AnyContent] =
  deadboltAction { implicit authRequest =>
    itemAction { 
      block 
    }(authRequest)
  }

然后调用网站看起来像这样

deadboltActionWithItemAction { implicit request: ItemRequest[AnyContent] =>
  Ok(modules.item.views.html.createSomething(Something.form, request.items))
}