diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 4d75d5e..4017970 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -2,15 +2,12 @@ class SessionsController < ApplicationController skip_before_filter :authenticate!, :only => [:new, :create] def create - user = User.authenticate( - params[:session][:email], - params[:session][:password] - ) - if ! user - render 'new' - else + user = User.find_by_email(params[:session][:email]) + if user.try(:authenticate?, params[:session][:password]) self.current_user = user redirect_to :root + else + render 'new' end end end diff --git a/app/models/user.rb b/app/models/user.rb index df0315b..1e6d889 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,31 +3,18 @@ require 'bcrypt' class User < ActiveRecord::Base include BCrypt - attr_accessor :password + attr_reader :password attr_accessible :email, :password, :password_confirmation - validates_presence_of :email + validates_presence_of :email, :password_hash + validates_confirmation_of :password - validates :password, - :presence => true, - :confirmation => true - - before_save :hash_password - - def self.authenticate(email, password) - user = find_by_email(email) - return false if user.nil? - return user if Password.new(user.password_hash) == password + def password=(plain_password) + @password = plain_password + self.password_hash = Password.create(plain_password) end - - private - - def hash_password - self.password_hash = bcrypt(password) - end - - def bcrypt(string) - Password.create(string) + def authenticate?(password) + Password.new(password_hash) == password end end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 419d787..e5d7337 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -8,31 +8,39 @@ describe SessionsController do end describe 'POST create' do - context 'when the user submit invalid credentials' do - it 'renders the new template' do - User.stub(:authenticate).and_return(false) - post :create, - :session => Factory.attributes_for(:user) - response.should render_template('new') - end + let(:user) { Factory.create(:user) } + + def do_create + post :create, :session => { + :email => user.email, + :password => user.password + } end - context 'when the user submit valid credentials' do - let(:user) { Factory.create(:user) } - before do - User.stub(:authenticate).and_return(user) - end - + context 'with valid credentials' do it 'signs the user in' do - post :create, :session => Factory.attributes_for(:user) + do_create controller.current_user.should == user end it 'redirects to the home page' do - post :create, :session => Factory.attributes_for(:user) + do_create response.should redirect_to(:root) end end + + [:email, :password].each do |attr| + context "with invalid credentials (#{attr})" do + before do + user.stub(attr => user.send(attr) + '_INVALID') + end + + it 'renders the new template' do + do_create + response.should render_template('new') + end + end + end end describe 'DELETE destroy' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 99180c7..d1777e6 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -16,49 +16,39 @@ describe User do it { should_not be_valid } end - context 'when password empty' do - before do - user.password = '' - end - - it { should_not be_valid } - end - context 'when password_confirmation does not match password' do before do - user.password_confirmation = 'WRONG' + user.password_confirmation = user.password + 'INVALID' end it { should_not be_valid } end - describe '#hash_password' do - it 'is received when #save is sent' do - user.should_receive(:hash_password) - user.save + context 'when password_hash empty' do + before do + user.password_hash = '' end - it 'stores a bcrypt hash of the password' do - user.save + it { should_not be_valid } + end + + describe '#password=' do + it 'stores a bcrypt hash of the password in password_hash' do BCrypt::Password.new(user.password_hash).should == user.password end end - describe '.authenticate' do - let (:user) { Factory.create(:user) } - - it 'returns the user with valid credentials' do - User.authenticate( - user.email, - user.password - ).should == user + describe '#authenticate?' do + context 'with a valid password' do + it 'returns true' do + user.authenticate?(user.password).should be_true + end end - it 'returns false with invalid credentials' do - User.authenticate( - user.email, - 'WRONG' - ).should be_false + context 'with an invalid password' do + it 'returns false' do + user.authenticate?(user.password + '_INVALID').should be_false + end end end end