Search code examples
scalaplayframework-2.0securesocialreactivemongoplay-reactivemongo

Compile error on a Future[Option[BasicProfile]] method in play


i'm writing a play 2.3 application using secure social and reactivemongo library, with scala. Now i'm trying to implement the UserService[T] trait but i'm getting compile errors on the updatePasswordInfo method. This is the method:

def updatePasswordInfo(user: LoginUser,info: PasswordInfo): scala.concurrent.Future[Option[BasicProfile]] = {
    implicit val passwordInfoFormat = Json.format[PasswordInfo]
    //the document query
    val query = Json.obj("providerId" -> user.providerId,
                         "userId" -> user.userId
                        )
    //search if the user exists
    val futureUser: Future[Option[LoginUser]] = UserServiceLogin.find(query).one
    futureUser map {
      case Some(x) => val newPassword = Json.obj("passswordInfo" -> info)// the new password
                      UserServiceLogin.update(query, newPassword) //update the document
                      val newDocument: Future[Option[LoginUser]] = UserServiceLogin.find(query).one
                      newDocument map {
                        case Some(x) => x
                        case None => None

                      } //return the new LoginUser
      case None => None
    }

  }

And this is the compiler error:

/Users/alberto/git/recommendation-system/app/security/UserService.scala:203: type mismatch;
[error]  found   : scala.concurrent.Future[Product with Serializable]
[error]  required: Option[securesocial.core.BasicProfile]
[error]                       newDocument map {

What's wrong?


Solution

  • If you really want to do the find to fail fast (though it is not so useful) and then reload the updated user from the database, something like this should do without the need for using scalaz :

    def updatePasswordInfo(user: LoginUser,info: PasswordInfo): scala.concurrent.Future[Option[BasicProfile]] = {
        implicit val passwordInfoFormat = Json.format[PasswordInfo]
        //the document query
        val query = Json.obj("providerId" -> user.providerId,
                             "userId" -> user.userId)
        val newPassword = Json.obj("passswordInfo" -> info)
        //update the document
        for {
            userO <- UserServiceLogin.find(query).one[BasicProfile] //fail fast (not sure this is really useful)
            updatedUser<-UserServiceLogin.update(query, newPassword).map(_=>userO).recover{case _ =>None}
            actualUser <- UserServiceLogin.find(query).one[BasicProfile]
        } yield actualUser
    
      }