Estoy intentando autenticar usuarios mediante el servicio de autenticación remota. método de ayuda que he escrito para enviar el mensaje al servicio y en espera de resultado:Limitación de la función Play 2
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")
}
}
Devuelve Left[String]
con una descripción del error si el mensaje no puede ser enviado, o no hay respuesta. Si se recibe respuesta de servicio, devuelve Right[Option[User]]
. El servicio responde con Option[User]
dependiendo del resultado de la autenticación.
para realizar la autenticación real que he creado formulario con un par de validadores, aquí está:
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
}
})
)
Una cosa que me preocupa de este código, se llama authenticateAwait
dos veces. Significa que se enviarán exactamente dos mensajes por validación individual. Lo que realmente necesito es llamar al authenticateAwait
una vez, almacenar el resultado y realizar varias validaciones en él. Parece que no hay una solución simple.
Para realizar la autenticación, acceder a los campos de formulario requeridos, significa que el formulario debe ser vinculado y luego validado, pero no hay forma de adjuntar errores al formulario existente (¿estoy equivocado?).
Los errores se pueden adjuntar al formulario solo durante su creación, por lo tanto, debo realizar la autenticación en los validadores, pero se produce el problema antes mencionado.
La solución temporal con la que vine es definir un método y un var
dentro de él.
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
}
})
)
}
Esto es claramente un truco. ¿Hay mejores soluciones?
Actualización: En mi opinión, la forma solo debe sanitizar la entrada, pero la autenticación debe realizarse más adelante fuera del formulario. El problema es que los errores se envían a la vista como parte del Form
y es imposible adjuntar errores al formulario existente. No hay una forma simple de crear una nueva forma con los errores también.
se llama AJAX; úselo y no creará bloques de código descomunales tratando de resolver un problema que no existe (sugerencia: no es necesario crear un nuevo formulario) – virtualeyes