I would probably refactor the code into something like this:
def authenticate() = Action.async { implicit request =>
loginForm.bindFromRequest.fold(
hasErrors = displayFormWithErrors,
success = loginUser)
}
private def displayFormWithErrors[T](errors:Form[T]) =
Future.successful(BadRequest(views.html.logon(errors)))
private def loginUser(userData:(String, String)) = {
val (username, password) = userData
findUser(username, password)
.flatMap {
case None =>
showLoginFormWithError("user/pass incorect!!!")
case Some(user) if (!user.active) =>
showLoginFormWithError("inactive!!!")
case Some(user) =>
updateUserAndRedirect(user)
}
}
private def findUser(username:String, password:String) =
this.collection
.find(BSONDocument("name" -> username))
.one[Account]
.map(_.filter(_.password == hashedPass(password, username)))
private def showLoginFormWithError(error:String) =
Future.successful(BadRequest(
views.html.logon(loginForm.withGlobalError(error))))
private def updateUserAndRedirect(user:Account) =
updateLastLogin(user)
.flatMap(_ => gotoLoginSucceeded(user.id.stringify))
private def updateLastLogin(user:Account) =
collection
.update(BSONDocument("_id" -> user.id),
BSONDocument("$set" ->
BSONDocument("lastLogin" ->
BSONDateTime(new JodaDateTime().getMillis()))))