1

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

这里有一些代码:

动作生成器

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

[错误] 未应用的方法仅在需要函数类型时才转换为函数。您可以通过编写Pattern _Pattern(_,_,_,_,_)(_)(_)代替Pattern.

[错误] def createSomething: Action[AnyContent] = (deadbolt.Pattern("Create_Deck", PatternType.EQUALITY)() andThen itemAction).synchronized() { 隐式请求:ItemRequest[AnyContent] =>

有谁已经处理过这个问题?

4

2 回答 2

1

正如 Jamie 所提到的,当开箱即用的组合实用方法不能直接适用时,我们可以回退到Action使用以下模式组合 s:

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))
}
于 2018-06-17T16:28:58.387 回答
1

由于DeadboltActions#Pattern返回 an 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)
}
于 2018-06-14T18:48:26.443 回答