Search code examples
scalamongodbcasbah

Is there a more idiomatic way to use Casbah to check a password?


I have the following code:

def authenticateByUsername(username: String, password:String): Boolean = {
    val user = users.findOne(MongoDBObject(USERNAME -> username))
    if(user.isDefined){
        val pw = user.get.getAs(PASSWORD)
        if(pw.isDefined) 
            BCrypt.checkpw(pw.get, password)
        else false
    }else false
}

Is there a more idiomatic way of doing this? It's an if-else nightmare, which just doesn't seem right in Scala.


Solution

  • You're correct that there's a better way, and in general using get (or, to a slightly lesser degree, isDefined) on an Option is a red flag. In this case you can use a for-comprehension:

    def authenticateByUsername(username: String, password: String): Boolean = {
      val result: Option[Boolean] = for {
        user <- users.findOne(MongoDBObject(USERNAME -> username))
        pass <- user.getAs(PASSWORD)
      } yield BCrypt.checkpw(pass, password)
    
      result getOrElse false
    }
    

    Or, a little more concisely:

    def authenticateByUsername(username: String, password: String): Boolean =
      users.findOne(MongoDBObject(USERNAME -> username)).flatMap(
        _.getAs(PASSWORD)
      ).map(
        BCrypt.checkpw(_, password)
      ).getOrElse(false)
    

    The latter is essentially just a desugared version of the for-comprehension.