Próbuję uwierzytelnić użytkowników za pomocą usługi zdalnego uwierzytelniania. Pisałem metody pomocnika do wysyłania wiadomości do służby i czeka na wynik:Odtwórz 2 ograniczenia formularza
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")
}
}
Zwraca Left[String]
wraz z opisem usterki, jeśli wiadomość nie może zostać wysłana, lub nie ma odpowiedzi. Jeśli otrzymana odpowiedź serwisowa zwróci Right[Option[User]]
. Usługa odpowiada Option[User]
w zależności od wyniku uwierzytelnienia.
Aby wykonać rzeczywistą uwierzytelniania Mam utworzony formularz z kilkoma walidatorami, tutaj jest:
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
}
})
)
Jedno mnie martwi o tym kodzie, wywołuje authenticateAwait
dwukrotnie. Oznacza to, że dokładnie dwie wiadomości zostaną wysłane na pojedynczą walidację. To, czego potrzebuję, to jednorazowe wywołanie authenticateAwait
, zapisanie wyniku i wykonanie różnych walidacji. Wydaje się, że nie ma prostego rozwiązania.
Aby wykonać uwierzytelnianie, dostęp do wymaganych pól formularza, oznacza to, że formularz powinien zostać powiązany, a następnie zweryfikowany, ale nie ma możliwości dołączenia błędów do istniejącego formularza (czy jestem w błędzie?).
Błędy mogą być dołączone do formularza tylko podczas jego tworzenia, dlatego należy wykonać uwierzytelnianie w walidatorach, ale pojawia się wspomniany wyżej problem.
Tymczasowe rozwiązanie, z którym się zetknąłem, to zdefiniowanie w nim metody i 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
}
})
)
}
To jest najwyraźniej hack. Czy są jakieś lepsze rozwiązania?
Aktualizacja: Moim zdaniem forma powinna tylko zdezynfekować wejście, ale autoryzacja powinna być wykonywana później poza formę. Problem polega na tym, że błędy są wysyłane do widoku jako część Form
i nie można dołączyć błędów do istniejącego formularza. Nie ma prostego sposobu na tworzenie nowej formy z błędami.
nazywa się AJAX; użyj go i nie utworzymy potężnych bloków kodu próbujących rozwiązać problem, który nie istnieje (podpowiedź: nie ma potrzeby tworzenia nowego formularza) – virtualeyes