Week 4, Day 4
The morning started as usual - standup at 9 o’clock sharing our ups and downs from yesterday afternoon and we returned at our desk. Please have a look at my previous blog post and you can see what my challenge was for the afternoon.
Today my pair partner wasn’t feeling very well and stayed at home. I spent the morning going through my code again and did some additional reading on the terminology. Lunch time was around the corner in no time and after that I paird with Tim whose pair was also not feeling very well. I am really happy with the our progress in the afternoon and my main challenge was to understand this:
def self.authenticate(email, password)
  user = first(email: email)
  if user && BCrypt::Password.new(user.password_digest) == password
    user
  else
    nil
  end
end
We have created an authentication method so that our user can sign up again if they have previously registered. The first line user = first(email: email) returns the first user whose email address is a match. Technically, we have specified in our User class (see below, unique) that we cannot have duplicate emails so returning the first match is not exactly the right way to say it.
class User
  include DataMapper::Resource
  property :id, Serial
  property :email, String, required: true, unique: true
  property :password_digest, Text
end
So, the first line of our authentication method was making sense but what about the second one:
if user && BCrypt::Password.new(user.password_digest) == password
  user
else
  nil
end
Here, our if statement will be excuted if both sides of && are true. user will return true if there is match for the email address in our database…but what about the right hand side of our &&.
The ‘BCrypt::Password.new(user.password_digest) == password’ is clearly doing some dark magic. When we have initially created a user in our database, we used BCrypt to encrypt the password by generating a hash. Right now, we cannot compare the entered password directly as BCrypt’s hash is one-way only (cannot take it and go backwards). However, what we have is a password_digest that we can use to check if the password the user is trying to log in with is the correct one. And that’s the comparison BCrypt::Password.new(user.password_digest) == password is doing behind the scene, overwritting the == method with its own one.
Zhivko