Can I do async form validation in Play Framework 2.x (Scala)?

后端 未结 5 744
执笔经年
执笔经年 2021-02-01 03:14

I\'m making a real push to understand the async powers of Play but finding a lot of conflict with regard to places where async invocation fits and places where the framework see

5条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-01 03:40

    I've seen on theguardian's GH repo how they handle this case scenario in a asynchronous way while still having the support of the form error helpers from play. From a quick look, seems like they are storing the form errors in an encrypted cookie in a way as to display those errors back to the user the next time the user goes to the login page.

    Extracted from: https://github.com/guardian/facia-tool/blob/9ec455804edbd104861117d477de9a0565776767/identity/app/controllers/ReauthenticationController.scala

    def processForm = authenticatedActions.authActionWithUser.async { implicit request =>
      val idRequest = idRequestParser(request)
      val boundForm = formWithConstraints.bindFromRequest
      val verifiedReturnUrlAsOpt = returnUrlVerifier.getVerifiedReturnUrl(request)
    
      def onError(formWithErrors: Form[String]): Future[Result] = {
        logger.info("Invalid reauthentication form submission")
        Future.successful {
          redirectToSigninPage(formWithErrors, verifiedReturnUrlAsOpt)
        }
      }
    
      def onSuccess(password: String): Future[Result] = {
          logger.trace("reauthenticating with ID API")
          val persistent = request.user.auth match {
            case ScGuU(_, v) => v.isPersistent
            case _ => false
          }
          val auth = EmailPassword(request.user.primaryEmailAddress, password, idRequest.clientIp)
          val authResponse = api.authBrowser(auth, idRequest.trackingData, Some(persistent))
    
          signInService.getCookies(authResponse, persistent) map {
            case Left(errors) =>
              logger.error(errors.toString())
              logger.info(s"Reauthentication failed for user, ${errors.toString()}")
              val formWithErrors = errors.foldLeft(boundForm) { (formFold, error) =>
                val errorMessage =
                  if ("Invalid email or password" == error.message) Messages("error.login")
                  else error.description
                formFold.withError(error.context.getOrElse(""), errorMessage)
              }
    
              redirectToSigninPage(formWithErrors, verifiedReturnUrlAsOpt)
    
            case Right(responseCookies) =>
              logger.trace("Logging user in")
              SeeOther(verifiedReturnUrlAsOpt.getOrElse(returnUrlVerifier.defaultReturnUrl))
                .withCookies(responseCookies:_*)
          }
      }
    
      boundForm.fold[Future[Result]](onError, onSuccess)
    }
    
    def redirectToSigninPage(formWithErrors: Form[String], returnUrl: Option[String]): Result = {
      NoCache(SeeOther(routes.ReauthenticationController.renderForm(returnUrl).url).flashing(clearPassword(formWithErrors).toFlash))
    }
    

提交回复
热议问题