diff --git a/README.md b/README.md index f5de6ece..510fb41f 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ explaining and the rest are commented: ```ruby require_login # This is a before action login(email, password, remember_me = false) +login!(email, password, remember_me = false) # Raises an `Sorcery::InvalidCredentials` exception on failure auto_login(user) # Login without credentials logout logged_in? # Available in views diff --git a/lib/sorcery/controller.rb b/lib/sorcery/controller.rb index f6cda708..2d457afe 100644 --- a/lib/sorcery/controller.rb +++ b/lib/sorcery/controller.rb @@ -1,4 +1,6 @@ module Sorcery + class InvalidCredentials < StandardError; end + module Controller def self.included(klass) klass.class_eval do @@ -63,6 +65,16 @@ def login(*credentials) end end + def login!(*credentials) + user = login(*credentials) + + if user.nil? + raise Sorcery::InvalidCredentials + else + user + end + end + def reset_sorcery_session reset_session # protect from session fixation attacks end diff --git a/spec/controllers/controller_spec.rb b/spec/controllers/controller_spec.rb index def1891b..0a4a136c 100644 --- a/spec/controllers/controller_spec.rb +++ b/spec/controllers/controller_spec.rb @@ -85,6 +85,39 @@ end end + describe '#login!' do + context 'when succeeds' do + before do + expect(User).to receive(:authenticate).with('bla@bla.com', 'secret') { |&block| block.call(user, nil) } + get :test_login_bang, params: { email: 'bla@bla.com', password: 'secret' } + end + + it 'assigns user to @user variable' do + expect(assigns[:user]).to eq user + end + + it 'writes user id in session' do + expect(session[:user_id]).to eq user.id.to_s + end + + it 'sets csrf token in session' do + expect(session[:_csrf_token]).not_to be_nil + end + end + + context 'when fails' do + before do + expect(User).to receive(:authenticate).with('bla@bla.com', 'opensesame!').and_return(nil) + end + + it 'raises Sorcery::InvalidCredentials exception' do + expect do + get :test_login_bang, params: { email: 'bla@bla.com', password: 'opensesame!' } + end.to raise_error(Sorcery::InvalidCredentials) + end + end + end + describe '#logout' do it 'clears the session' do cookies[:remember_me_token] = nil diff --git a/spec/rails_app/app/controllers/sorcery_controller.rb b/spec/rails_app/app/controllers/sorcery_controller.rb index 8214e36a..8252e6d3 100644 --- a/spec/rails_app/app/controllers/sorcery_controller.rb +++ b/spec/rails_app/app/controllers/sorcery_controller.rb @@ -28,6 +28,11 @@ def test_login head :ok end + def test_login_bang + @user = login!(params[:email], params[:password]) + head :ok + end + def test_auto_login @user = User.first auto_login(@user) diff --git a/spec/rails_app/config/routes.rb b/spec/rails_app/config/routes.rb index 4bf82c29..01e7d467 100644 --- a/spec/rails_app/config/routes.rb +++ b/spec/rails_app/config/routes.rb @@ -3,6 +3,7 @@ controller :sorcery do get :test_login + get :test_login_bang get :test_logout get :some_action post :test_return_to