2012-09-27 2 views
6

원격 인증 서비스를 통해 사용자를 인증하려고합니다. 나는 서비스에 메시지를 전송하고 결과를 기다리고위한 도우미 메서드를 작성했습니다 : 메시지를 보낼 수없는 경우재생 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") 
    } 
} 

는 오류 설명과 함께 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으로 한 번 호출하여 결과를 저장하고 다양한 유효성 검사를 수행하는 것입니다. 간단한 해결책이없는 것 같습니다.

필요한 양식 필드에 액세스, 그것은 형태가 확인 후 결합되어야 의미하지만, 기존의 형태로 오류를 부착 할 수있는 방법이 없습니다, 인증을 수행하려면 (내가 잘못은?).

오류 따라서 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 
     } 
    }) 
) 
} 

이것은 분명히 해킹입니다. 더 나은 해결책이 있습니까?

업데이트 : 제 생각에 양식은 입력을 위생적으로 처리해야하지만 양식은 나중에 양식 외부에서 수행해야합니다. 문제는 오류가 Form의 일부로보기로 전송되며 오류를 기존 양식에 첨부 할 수 없다는 것입니다. 오류가있는 새로운 양식을 만드는 간단한 방법은 없습니다.

+1

AJAX라고합니다. 그것을 사용하면 존재하지 않는 문제를 해결하기 위해 ginormous code blocks을 만들지 않을 것입니다 (힌트 : 새로운 양식을 만들 필요가 없습니다) – virtualeyes

답변

3

당신이 이해해야 만하는 것은 그 양식이 변경 불가능하다는 것입니다. 그러나 오류가 추가 된 새로운 양식을 작성하는 유틸리티 메소드를 사용하기 쉽습니다.

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

확인, 유효성 검사 가미하여 인증 그냥 간단한 조작 단지를 만든다. 아래는 테스트되지 않았지만 이것은 내가 들어갈 방향이고, 올바른 투영은 이해를 위해 필터링되었습니다.

// point of validation is to sanitize inputs last I checked 
val form = Form(tuple("email"→ email, "password"→ nonEmptyText) 
val res = for{ 
    case(e,p) <- form.bindFromRequest.toRight("Invalid email or password") 
    success <- User.authenticateAwait(e,p).right 
} yield success 
res fold(Conflict(Left(_)), u=> Ok(Right(u))) 
+0

재생 샘플은 form verify 블록 안에 인증을 포함하므로 검증 자들은 가다. 솔루션에 따라 인증이 실패하면 오류가있는 양식을 다시 템플릿으로 되돌려 야합니까? – lambdas

+0

이미 그 작업을하고 있습니다. 왼쪽에는 양식 유효성 검사 오류 또는 연결 오류가 있습니다. 오른쪽에는 사용자가 포함되어 있습니다 ... 어쨌든, 결과, 충돌 (왼쪽 (_)), u => 확인 (오른쪽 (u)) – virtualeyes

+0

또한 결론은 미래 경로를 택한 것으로 가정합니다 , 그 성능은 중요합니다; 표준 웹 응용 프로그램에서.아약스가 갈 방법이 될 것입니다. IMO - 오류 발생시 양식을 다시 표시 할 필요가 없습니다. 사용자는 어디에도 가지 않고 오류 상태를 처리하고 표시하거나 성공을 반환하고 그에 따라 처리합니다. – virtualeyes