diff --git a/app/controllers/devise/registrations_controller.rb b/app/controllers/devise/registrations_controller.rb index 31ba0887bd..7f3b859a03 100644 --- a/app/controllers/devise/registrations_controller.rb +++ b/app/controllers/devise/registrations_controller.rb @@ -48,12 +48,8 @@ def update resource_updated = update_resource(resource, account_update_params) yield resource if block_given? if resource_updated - if is_flashing_format? - flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ? - :update_needs_confirmation : :updated - set_flash_message :notice, flash_key - end - bypass_sign_in resource, scope: resource_name + set_flash_message_for_update(resource, prev_unconfirmed_email) + sign_in_after_change_password respond_with resource, location: after_update_path_for(resource) else clean_up_passwords resource @@ -125,7 +121,7 @@ def after_inactive_sign_up_path_for(resource) # The default url to be used after updating a resource. You need to overwrite # this method in your own RegistrationsController. def after_update_path_for(resource) - signed_in_root_path(resource) + sign_in_after_change_password? ? signed_in_root_path(resource) : new_session_path(resource_name) end # Authenticates the current scope and gets the current resource from the session. @@ -145,4 +141,30 @@ def account_update_params def translation_scope 'devise.registrations' end + + private + + def set_flash_message_for_update(resource, prev_unconfirmed_email) + return unless is_flashing_format? + flash_key = if update_needs_confirmation?(resource, prev_unconfirmed_email) + :update_needs_confirmation + elsif sign_in_after_change_password? + :updated + else + :updated_not_sign_in + end + set_flash_message :notice, flash_key + end + + def sign_in_after_change_password + if sign_in_after_change_password? + bypass_sign_in resource, scope: resource_name + else + sign_out(resource) + end + end + + def sign_in_after_change_password? + Devise.sign_in_after_change_password && account_update_params.include?(:password) + end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 0b8f130278..d1168c08d8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -44,6 +44,7 @@ en: signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." updated: "Your account has been updated successfully." + updated_not_sign_in: "Your password has been changed successfully. please try signing in" sessions: signed_in: "Signed in successfully." signed_out: "Signed out successfully." diff --git a/lib/devise.rb b/lib/devise.rb index debd342b71..56d73f0be0 100755 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -290,6 +290,10 @@ module Test mattr_accessor :token_generator @@token_generator = nil + # When set to false, changing a password does not automatically sign in a user + mattr_accessor :sign_in_after_change_password + @@sign_in_after_change_password = true + def self.rails51? # :nodoc: Rails.gem_version >= Gem::Version.new("5.1.x") end diff --git a/lib/devise/models/registerable.rb b/lib/devise/models/registerable.rb index 1f10dd2e69..54377009cf 100644 --- a/lib/devise/models/registerable.rb +++ b/lib/devise/models/registerable.rb @@ -19,6 +19,8 @@ module ClassMethods def new_with_session(params, session) new(params) end + + Devise::Models.config(self, :sign_in_after_change_password) end end end diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index e3d9ede77d..88aba971f6 100755 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -274,4 +274,10 @@ # When using OmniAuth, Devise cannot automatically set OmniAuth path, # so you need to do it manually. For the users scope, it would be: # config.omniauth_path_prefix = '/my_engine/users/auth' + + # ==> Configuration for :registerable + + # When set to false, does not sign a user in automatically after their password is + # changed. Defaults to true, so a user is signed in automatically after changing a password. + # config.sign_in_after_change_password = true end diff --git a/test/integration/registerable_test.rb b/test/integration/registerable_test.rb index 4fa361b7cb..79ad9ac7a5 100644 --- a/test/integration/registerable_test.rb +++ b/test/integration/registerable_test.rb @@ -177,6 +177,22 @@ def user_sign_up assert warden.authenticated?(:user) end + test 'a signed in user should not still be able to use the website after changing their password if config.sign_in_after_change_password is false' do + swap Devise, sign_in_after_change_password: false do + sign_in_as_user + get edit_user_registration_path + + fill_in 'password', with: '1234567890' + fill_in 'password confirmation', with: '1234567890' + fill_in 'current password', with: '12345678' + click_button 'Update' + + assert_contain 'Your password has been changed successfully. please try signing in' + assert_equal new_user_session_path, @request.path + assert !warden.authenticated?(:user) + end + end + test 'a signed in user should not change their current user with invalid password' do sign_in_as_user get edit_user_registration_path diff --git a/test/rails_app/config/initializers/devise.rb b/test/rails_app/config/initializers/devise.rb index d79e71f579..5a160003eb 100644 --- a/test/rails_app/config/initializers/devise.rb +++ b/test/rails_app/config/initializers/devise.rb @@ -177,4 +177,10 @@ # manager.failure_app = AnotherApp # manager.default_strategies(scope: :user).unshift :some_external_strategy # end + + # ==> Configuration for :registerable + + # When set to false, does not sign a user in automatically after their password is + # changed. Defaults to true, so a user is signed in automatically after changing a password. + # config.sign_in_after_change_password = true end