diff --git a/lib/generators/sorcery/templates/initializer.rb b/lib/generators/sorcery/templates/initializer.rb index fbef16fc..f1db17d6 100644 --- a/lib/generators/sorcery/templates/initializer.rb +++ b/lib/generators/sorcery/templates/initializer.rb @@ -16,11 +16,20 @@ # config.not_authenticated_action = # When a non logged-in user tries to enter a page that requires login, save - # the URL he wants to reach, and send him there after login, using 'redirect_back_or_to'. + # the URL he wants to reach, and send him there after login, using 'redirect_to_before_login_path'. # Default: `true` # # config.save_return_to_url = + # Set whether to use 'redirect_back_or_to' defined in Rails 7. + # Rails 7 released a new method called 'redirect_back_or_to' as a replacement for 'redirect_back'. + # That may conflict with the method by the same name defined by Sorcery. + # If you set this option to true, Sorcery's 'redirect_back_or_to' calls 'super' to use + # the method of the same name defined in Rails 7. + # Default: `false` + # + # config.use_redirect_back_or_to_by_rails = + # Set domain option for cookies; Useful for remember_me submodule. # Default: `nil` # diff --git a/lib/sorcery.rb b/lib/sorcery.rb index 2a0af8cc..eff8c5bb 100644 --- a/lib/sorcery.rb +++ b/lib/sorcery.rb @@ -1,6 +1,10 @@ require 'sorcery/version' module Sorcery + def self.deprecator + @deprecator ||= ActiveSupport::Deprecation.new(nil, 'Sorcery') + end + require 'sorcery/model' module Adapters diff --git a/lib/sorcery/controller.rb b/lib/sorcery/controller.rb index cd8e4284..83e9786b 100644 --- a/lib/sorcery/controller.rb +++ b/lib/sorcery/controller.rb @@ -18,7 +18,7 @@ def self.included(klass) Config.configure! end - module InstanceMethods + module InstanceMethods # rubocop:disable Metrics/ModuleLength # To be used as before_action. # Will trigger auto-login attempts via the call to logged_in? # If all attempts to auto-login fail, the failure callback will be called. @@ -96,7 +96,20 @@ def current_user=(user) # used when a user tries to access a page while logged out, is asked to login, # and we want to return him back to the page he originally wanted. - def redirect_back_or_to(url, flash_hash = {}) + def redirect_back_or_to(...) + if Config.use_redirect_back_or_to_by_rails + super + else + Sorcery.deprecator.warn( + '`redirect_back_or_to` overrides the method of the same name defined in Rails 7. ' \ + 'To avoid overriding, set `config.use_redirect_back_or_to_by_rails = true` and use `redirect_to_before_login_path`. ' \ + 'In a future release, `config.use_redirect_back_or_to_by_rails = true` will become the default.' + ) + redirect_to_before_login_path(...) + end + end + + def redirect_to_before_login_path(url, flash_hash = {}) redirect_to(session[:return_to_url] || url, flash: flash_hash) session[:return_to_url] = nil end diff --git a/lib/sorcery/controller/config.rb b/lib/sorcery/controller/config.rb index 1a9bf112..1f04a91d 100644 --- a/lib/sorcery/controller/config.rb +++ b/lib/sorcery/controller/config.rb @@ -20,6 +20,9 @@ class << self attr_accessor :after_logout attr_accessor :after_remember_me + # set whether to use 'redirect_back_or_to' defined in Rails 7. + attr_accessor :use_redirect_back_or_to_by_rails + def init! @defaults = { :@user_class => nil, @@ -32,7 +35,8 @@ def init! :@after_logout => Set.new, :@after_remember_me => Set.new, :@save_return_to_url => true, - :@cookie_domain => nil + :@cookie_domain => nil, + :@use_redirect_back_or_to_by_rails => false } end diff --git a/lib/sorcery/engine.rb b/lib/sorcery/engine.rb index eb5de9b3..5d1644f1 100644 --- a/lib/sorcery/engine.rb +++ b/lib/sorcery/engine.rb @@ -7,6 +7,10 @@ module Sorcery class Engine < Rails::Engine config.sorcery = ::Sorcery::Controller::Config + initializer 'sorcery.deprecator' do |app| + app.deprecators[:sorcery] = Sorcery.deprecator + end + # TODO: Should this include a modified version of the helper methods? initializer 'extend Controller with sorcery' do # FIXME: on_load is needed to fix Rails 6 deprecations, but it breaks diff --git a/spec/controllers/controller_spec.rb b/spec/controllers/controller_spec.rb index b8efb678..a208b0d8 100644 --- a/spec/controllers/controller_spec.rb +++ b/spec/controllers/controller_spec.rb @@ -22,6 +22,12 @@ expect(Sorcery::Controller::Config.not_authenticated_action).to eq :my_action end + + it "enables configuration option 'use_redirect_back_or_to_by_rails'" do + sorcery_controller_property_set(:use_redirect_back_or_to_by_rails, true) + + expect(Sorcery::Controller::Config.use_redirect_back_or_to_by_rails).to be true + end end # ----------------- PLUGIN ACTIVATED ----------------------- @@ -182,5 +188,44 @@ expect(assigns[:result]).to eq user end + + describe 'redirect_back_or_to' do + describe 'use_redirect_back_or_to_by_rails' do + context 'when true' do + before do + sorcery_controller_property_set(:use_redirect_back_or_to_by_rails, true) + allow_any_instance_of(ActionController::TestRequest) # rubocop:disable RSpec/AnyInstance + .to receive(:referer).and_return('http://test.host/referer_action') + end + + context 'when Rails::VERSION::MAJOR >= 7', skip: Rails::VERSION::MAJOR < 7 do + it 'uses Rails 7 redirect_back_or_to method' do + get :test_redirect_back_or_to + + expect(response).to redirect_to('http://test.host/referer_action') + end + end + end + + context 'when false' do + before { sorcery_controller_property_set(:use_redirect_back_or_to_by_rails, false) } + + it 'uses Sorcery redirect_back_or_to method and warns about overriding the Rails 7 method' do + deprecator = Sorcery.deprecator + expected_message = '`redirect_back_or_to` overrides the method of the same name defined in Rails 7. ' \ + 'To avoid overriding, set `config.use_redirect_back_or_to_by_rails = true` and use `redirect_to_before_login_path`. ' \ + 'In a future release, `config.use_redirect_back_or_to_by_rails = true` will become the default.' + + expect(deprecator).to receive(:warn).with(expected_message) + + session[:return_to_url] = 'http://test.host/some_action' + get :test_redirect_back_or_to + + expect(response).to redirect_to('http://test.host/some_action') + expect(flash[:notice]).to eq 'haha!' + end + end + end + end end end diff --git a/spec/rails_app/app/controllers/sorcery_controller.rb b/spec/rails_app/app/controllers/sorcery_controller.rb index 8214e36a..2c136eef 100644 --- a/spec/rails_app/app/controllers/sorcery_controller.rb +++ b/spec/rails_app/app/controllers/sorcery_controller.rb @@ -36,6 +36,11 @@ def test_auto_login end def test_return_to + @user = login(params[:email], params[:password]) + redirect_to_before_login_path(:index, notice: 'haha!') + end + + def test_redirect_back_or_to @user = login(params[:email], params[:password]) redirect_back_or_to(:index, notice: 'haha!') end @@ -314,7 +319,7 @@ def test_login_from_battlenet def test_return_to_with_external_twitter if (@user = login_from(:twitter)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -322,7 +327,7 @@ def test_return_to_with_external_twitter def test_return_to_with_external_jira if (@user = login_from(:jira)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -332,7 +337,7 @@ def test_return_to_with_external_jira def test_return_to_with_external_facebook if (@user = login_from(:facebook)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -340,7 +345,7 @@ def test_return_to_with_external_facebook def test_return_to_with_external_github if (@user = login_from(:github)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -348,7 +353,7 @@ def test_return_to_with_external_github def test_return_to_with_external_paypal if (@user = login_from(:paypal)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -356,7 +361,7 @@ def test_return_to_with_external_paypal def test_return_to_with_external_wechat if (@user = login_from(:wechat)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -364,7 +369,7 @@ def test_return_to_with_external_wechat def test_return_to_with_external_microsoft if (@user = login_from(:microsoft)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -372,7 +377,7 @@ def test_return_to_with_external_microsoft def test_return_to_with_external_google if (@user = login_from(:google)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -380,7 +385,7 @@ def test_return_to_with_external_google def test_return_to_with_external_liveid if (@user = login_from(:liveid)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -388,7 +393,7 @@ def test_return_to_with_external_liveid def test_return_to_with_external_vk if (@user = login_from(:vk)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -396,7 +401,7 @@ def test_return_to_with_external_vk def test_return_to_with_external_salesforce if (@user = login_from(:salesforce)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -404,7 +409,7 @@ def test_return_to_with_external_salesforce def test_return_to_with_external_slack if (@user = login_from(:slack)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -412,7 +417,7 @@ def test_return_to_with_external_slack def test_return_to_with_external_instagram if (@user = login_from(:instagram)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -420,7 +425,7 @@ def test_return_to_with_external_instagram def test_return_to_with_external_auth0 if (@user = login_from(:auth0)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -428,7 +433,7 @@ def test_return_to_with_external_auth0 def test_return_to_with_external_line if @user = login_from(:line) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -436,7 +441,7 @@ def test_return_to_with_external_line def test_return_to_with_external_discord if (@user = login_from(:discord)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end @@ -444,7 +449,7 @@ def test_return_to_with_external_discord def test_return_to_with_external_battlenet if (@user = login_from(:battlenet)) - redirect_back_or_to 'bla', notice: 'Success!' + redirect_to_before_login_path 'bla', notice: 'Success!' else redirect_to 'blu', alert: 'Failed!' end diff --git a/spec/rails_app/config/routes.rb b/spec/rails_app/config/routes.rb index 4bf82c29..c7b80d2a 100644 --- a/spec/rails_app/config/routes.rb +++ b/spec/rails_app/config/routes.rb @@ -6,6 +6,7 @@ get :test_logout get :some_action post :test_return_to + post :test_redirect_back_or_to get :test_auto_login post :test_login_with_remember_in_login get :test_login_from_cookie