【问题标题】:Scala DeadboltAction andThen custom play ActionBuilderScala DeadboltAction 然后自定义播放 ActionBuilder
【发布时间】:2018-11-23 17:10:23
【问题描述】:

这是我的问题: 我需要使用 deadbolt 在控制器中检查用户权限,然后向请求中添加一些内容(使用 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 来明确此转换。

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

有人处理过这个问题吗?

【问题讨论】:

    标签: scala playframework deadbolt-2


    【解决方案1】:

    由于DeadboltActions#Pattern 返回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)
    }
    

    【讨论】:

    • 感谢您的回答。我希望能够调用死锁操作(Pattern、SubjectPresent ...),然后应用我的自定义操作。您没有在组合中使用任何死锁操作。您能否发布一个使用死锁操作的示例?
    • 据我所知(我肯定是错的),您将无法使用这些方法,因为它们返回 Action,不能用于动作组合。假设这一点,您只需将这些操作重新实现为ActionBuilders。如果您确实弄清楚如何直接使用它们,请发布问题的答案,因为我自己对答案非常感兴趣!
    • 我就是这么想的。我让 playframework 的人在研究它。一旦他们给我一些东西,我就会发布它。谢谢
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 2012-10-24
      • 2014-08-10
      • 2018-03-23
      • 2013-06-22
      相关资源
      最近更新 更多