forms - 玩2形式限制

标签 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")
  }
}

它返回 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
      }
  })
)

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

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

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

我带来的临时解决方案是定义一个方法和一个 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
        }
    })
  )
}

这显然是一个 hack。有没有更好的解决方案?

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

最佳答案

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

loginForm.copy(errors = Seq(FormError("email", "Already registered")))

关于forms - 玩2形式限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12618609/

相关文章:

java - 如何管理来自在单独线程中运行的多个外部命令的多个标准输出?

scala - 为什么 Scala 中声明的非法开始?

javascript - 将表单输入值附加到操作 url 作为路径

php - JavaScript 发布 PHP Action

javascript - 根据多个条件显示带有 ng-messages 的验证消息

php - 从未检查过的自定义约束

forms - Flutter - 在点击 TextFormField 时显示对话框 NumberPicker

jquery:将表单响应从隐藏的 iframe 保存到变量

c# - 检查数据表中是否有空值的最佳方法

scala - Scala 2.10中的__FUNC__宏