Scala Play Action组合:声明通过组合多个ActionFunction生成Action的ActionBuilder

时间:2014-11-05 01:43:03

标签: scala playframework-2.0 composition

我试图围绕Play动作组合。我的主要参考是:https://www.playframework.com/documentation/2.3.6/ScalaActionsComposition

这是我想要实现的目标(能够以这种方式在我的Controller中声明一个函数):

def sensitiveOperation() = Protected {request => ...}

所以,我的行动计划是:

/**
 * Now I need to make an Action builder that wraps two things: 
 * UserAction (to make sure that request is transformed to UserRequest),
 * and then... an Action that checks if userId has a value (it proceeds by invoking the actual action)
 * , or otherwise return Unauthorized
 */

所以......我有这三件事:

class UserRequest[A](val userId: Option[String], request: Request[A]) extends WrappedRequest[A](request)

object UserAction extends ActionBuilder[UserRequest] with ActionTransformer[Request, UserRequest] {
  def transform[A](request: Request[A]) = Future.successful {
    new UserRequest(request.session.get("userId"), request)
  }
}

object CheckUserId extends ActionFilter[UserRequest] {
  def filter[A](userRequest: UserRequest[A]) = Future.successful {
    userRequest.userId match {
      case Some(userIdVal) => None
      case None => Some(Results.Unauthorized("User is not logged in. Log in first."))
    }
  }
}

所有这三件事都在编译。

我的问题是:如何声明一个使用UserAction和CheckUserId的Action?

object Protected extends ActionBuilder[Request] {
  def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    block(request)
  }
  override def composeAction[A](action: Action[A]) = ... ?? how ?? ....
}

我在下面尝试过这个,但它会出现编译错误:

override def composeAction[A](action: Action[A]) = UserAction andThen CheckUserId

其他附加

现在我可以使用它解决这个问题:

def sensitiveOperation() = (UserAction andThen CheckUserId) {request => ...}

但是,如果我能定义一个名为"受保护的"的伴侣对象,我认为它会更漂亮。实际上也是如此(和UserAction和CheckUserId)......所以我可以回到最初的想法:

def sensitiveOperation() = Protected {request => ...}

如何实现它?

提前致谢, 拉嘎

2 个答案:

答案 0 :(得分:3)

您无法使用对象执行此操作,因为对象不能是表达式的结果。但是你可以把它变成def或val,你可以把它放在一个包对象中,如果你想要的话,例如:

package object security {
  val Protected = UserAction andThen CheckUserId
}

答案 1 :(得分:0)

我想我已经找到了......

object Protected extends ActionBuilder[UserRequest] {
  def invokeBlock[A](request: Request[A], block: (UserRequest[A]) => Future[Result]) = {
    (UserAction andThen CheckUserId).invokeBlock(request, block)
  }
}