I have a table User(id, password_hash, ....)
in db and a model for it:
case class User(
id: Pk[Long] = NotAssigned,
email: String,
password: Option[String] = None,
passwordHash: Option[String] = None
)
object User {
def create(newUser: User): Option[Long] = //.....
//on("password_hash" -> generatePasswordHash(newUser.password)
def generatePasswordHash(p: String) = //....
}
The point is Password
field exists only the model User
and is filled up only I register a new user:
val newUser = User(email = emailFromForm, password = Some(passwordFromForm))
I send to db only a hash of the password. Obviously, when I retrieve it from db, Password
field in None but PasswordHash
has a value.
I made Password
and PasswordHash
to be Option because I think they should be Options
, shouldn't they? I'm not sure, though, whether it's right or wrong.
The question is my is this a good approach?
Why do you want to have User.password
at all?
case class User(
id: Pk[Long] = NotAssigned,
email: String,
passwordHash: String
)
object User {
// or maybe Option[User] or Try[User]
def create(email: String, password: String): Option[Long] = {
val passwordHash = hashPassword(hash)
val newUser = User(email, passwordHash)
// save newUser to DB
}
// you may want to distinguish between "no such email" and "wrong password"
// in which case you'd have something like Either[PasswordCheckFailure, User]
def checkPassword(email: String, password: String): Option[User] = {
val possibleUser: Option[User] = // get user by email
possibleUser.filter(_.passwordHash = hashPassword(password))
}
private def hashPassword(password: String): String = ...
}
You may want to have a salt as well, see e.g. https://crackstation.net/hashing-security.htm. In this case you either store it in the same field as password or add another field:
case class User(
id: Pk[Long] = NotAssigned,
email: String,
passwordHash: String,
passwordSalt: String = // generate random string
)