这是我的问题:
我需要使用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] =>
任何已经处理过此事的人?
答案 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))
}