玩2形式限制

lam*_*das 6 forms validation scala playframework playframework-2.0

我正在尝试通过远程身份验证服务对用户进行身份验证.我写了帮助方法,用于向服务发送消息并等待结果:

def authenticateAwait(email:       String,
                      password:    String
                     ): Either[String, Option[User]] = {
  try {
    val future = authenticate(email, password)
    Right(Await.result(future, timeout.duration))
  } catch {
    case _ ? Left("Unable to connect to authentication server")
  }
}
Run Code Online (Sandbox Code Playgroud)

Left[String]如果无法发送消息,或者没有响应,则返回错误描述.如果收到服务响应,则返回Right[Option[User]].服务Option[User]根据身份验证结果进行响应.

为了执行实际的身份验证,我创建了一些带有几个验证器的表单,这里是:

val loginForm = Form(
  tuple(
    "email"    ? email,
    "password" ? nonEmptyText
  ) verifying ("Invalid email or password", result => result match {
    case (email, password) ?
      User.authenticateAwait(email, password) match {
        case Left(_) ? true
        case Right(optUser) ? optUser.isDefined
      }
  }) verifying ("Unable to connect to authentication server", result => result match {
    case (email, password) ?
      User.authenticateAwait(email, password) match {
        case Left(_) ? false
        case Right(optUser) ? true
      }
  })
)
Run Code Online (Sandbox Code Playgroud)

有一件事让我担心这个代码,它会调用authenticateAwait两次.这意味着每次验证将发送两条消息.我真正需要的是调用authenticateAwait一次,存储结果并对其执行各种验证.似乎没有简单的解决方案.

要执行身份验证,访问所需的表单字段,这意味着表单应该绑定然后验证,但是没有办法将错误附加到现有表单(我错了吗?).

错误只能在创建过程中附加到表单,因此我应该在验证器中执行身份验证,但之后会出现上述问题.

我带来的临时解决方案是定义一个方法和一个var内部.

def loginForm = {
  var authResponse: Either[String, Option[commons.User]] = null

  Form(
    tuple(
      "email"    ? email,
      "password" ? nonEmptyText
    ) verifying ("Invalid email or password", result ? result match {
      case (email, password) ?
        authResponse = User.authenticateAwait(email, password)
        authResponse match {
          case Left(_) ? true
          case Right(optUser) ? optUser.isDefined
        }
    }) verifying ("Unable to connect to authentication server", result ? result match {
      case (email, password) ?
        authResponse match {
          case Left(_) ? false
          case Right(optUser) ? true
        }
    })
  )
}
Run Code Online (Sandbox Code Playgroud)

这显然是一个黑客.还有更好的解决方案吗?

更新: 在我看来,表单应该只清理输入,但是应该在表单之外执行身份验证.问题是错误作为一部分发送到视图,Form并且不可能将错误附加到现有表单.没有简单的方法来创建带有错误的新表单.

Mir*_*ari 3

你必须明白的是 Form 是不可变的。但是有一个易于使用的实用方法来构造一个添加了错误的新表单:

loginForm.copy(errors = Seq(FormError("email", "Already registered")))
Run Code Online (Sandbox Code Playgroud)