I prefer to do password and user verification in form validation suggestions - there will be something like this (untested, but you get the idea):
private val loginForm = Form( mapping( "name" -> nonEmptyText, "password" -> nonEmptyText ){ (name, password) => ( this.collection.find(BSONDocument("name" -> name)).one[Account], password) }{ data => Some((data._1.name, data._2)) }.verifying(new Constraint(None, Seq())({ data: (Option[Account], String) => data match { case (Some(account: Account), _) if !account.active => Invalid(ValidationError("inactive")) case (Some(account: Account), password) if account.password==hashedPass(account.name, password) => Valid case _ => Invalid(ValidationError("login/pass mismatch")) } })) )
And then the controller becomes much simpler:
def authenticate() = Action.async { implicit request => loginForm.bindFromRequest.fold( errors => Future.successful(BadRequest(views.html.logon(errors))), usersData =>{ collection.update(BSONDocument("_id" -> usersData._1.id), BSONDocument("$set" -> BSONDocument("lastLogin" -> BSONDateTime(new org.joda.time.DateTime().getMillis())))) .flatMap(x => gotoLoginSucceeded(user.id.stringify)) } ) }
source share