bad at scala
bad at scala

Reputation: 297

How to return only if a condition is true?

I am still getting the hang of Scala and functional programming.

I am trying to implement an authentication method, but I only want to return if the password matches the hash and I'm not quite sure how to do that.

Please forgive the code below, I am still struggling trying to wrap my head around functional. Hopefully, I have given enough to illustrate what I want to accomplish. I only want to return a result, IF and ONLY IF the password matches the supplied password, else I want it to act like nothing was found.

def authenticate(name: String, password: String): Option[Member] = {
  DB.withConnection { implicit c =>
    SQL("select * from member where lower(membername)={membername}").on(
    'membername -> name.toLowerCase()
  ).as(Member.member.singleOpt)

    if(BCrypt.checkpw(password, Member.member.password)) {
       Member.member.singleOpt
    } else {
       null
    }
  }
}

I am using PlayFramework and Anorm. But, I think this is more of a general Scala question.

Upvotes: 3

Views: 530

Answers (3)

Neville Li
Neville Li

Reputation: 420

The return type is Option which means it must be either Some (containing a single value) or None (containing nothing). Member.member.password should be of type Option[Member] already so the else case should probably be None (sub class of any Option).

http://www.scala-lang.org/api/current/index.html#scala.Option

Upvotes: 2

yǝsʞǝla
yǝsʞǝla

Reputation: 16412

Your method returns an Option[Member] which is good functional style. If your authentication passes you can return Some[Member] which is what Member.member.singleOpt is. Otherwise return None instead of null.

Upvotes: 1

Michael Zajac
Michael Zajac

Reputation: 55569

as(Member.member.singleOpt) returns an Option[Member]. You can filter an Option just like any collection, which will allow you to filter out a user with bad credentials.

def authenticate(name: String, password: String): Option[Member] = {
    DB.withConnection { implicit c =>
        SQL("select * from member where lower(membername)={membername}").on(
            'membername -> name.toLowerCase()
        ).as(Member.member.singleOpt)
        .filter(member => BCrypt.checkpw(password, member.password))
    }
}

The inner function of filter will only be called if the Member is found. If BCrypt.checkpw(password, member.password) is false, then Some(member) will become None, so authenticate will return None when the credentials are incorrect.

Upvotes: 4

Related Questions