Skip to content

Commit

Permalink
Add an option to not automatically sign in a user after changing a pa…
Browse files Browse the repository at this point in the history
…ssword (#4569)
  • Loading branch information
knjko authored and tegon committed Dec 28, 2018
1 parent 8266e85 commit e3a00b2
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 8 deletions.
32 changes: 25 additions & 7 deletions app/controllers/devise/registrations_controller.rb
Expand Up @@ -50,12 +50,9 @@ 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)
bypass_sign_in resource, scope: resource_name if sign_in_after_change_password?

respond_with resource, location: after_update_path_for(resource)
else
clean_up_passwords resource
Expand Down Expand Up @@ -127,7 +124,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.
Expand All @@ -147,4 +144,25 @@ 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_but_not_signed_in
end
set_flash_message :notice, flash_key
end

def sign_in_after_change_password?
return true if account_update_params[:password].blank?

Devise.sign_in_after_change_password
end
end
1 change: 1 addition & 0 deletions config/locales/en.yml
Expand Up @@ -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_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again"
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
Expand Down
4 changes: 4 additions & 0 deletions lib/devise.rb
Expand Up @@ -293,6 +293,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
Expand Down
2 changes: 2 additions & 0 deletions lib/devise/models/registerable.rb
Expand Up @@ -21,6 +21,8 @@ module ClassMethods
def new_with_session(params, session)
new(params)
end

Devise::Models.config(self, :sign_in_after_change_password)
end
end
end
Expand Down
8 changes: 7 additions & 1 deletion lib/generators/templates/devise.rb
Expand Up @@ -9,7 +9,7 @@
# Devise will use the `secret_key_base` as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = '<%= SecureRandom.hex(64) %>'

# ==> Controller configuration
# Configure the parent class to the devise controllers.
# config.parent_controller = 'DeviseController'
Expand Down Expand Up @@ -290,4 +290,10 @@
# ActiveSupport.on_load(:devise_failure_app) do
# include Turbolinks::Controller
# 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
33 changes: 33 additions & 0 deletions test/integration/registerable_test.rb
Expand Up @@ -179,6 +179,39 @@ def user_sign_up
assert warden.authenticated?(:user)
end

test 'a signed in user should not 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 account has been updated successfully, but since your password was changed, you need to sign in again'
assert_equal new_user_session_path, @request.path
refute warden.authenticated?(:user)
end
end

test 'a signed in user should be able to use the website after changing its email with 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 'email', with: 'user.new@example.com'
fill_in 'current password', with: '12345678'
click_button 'Update'

assert_current_url '/'
assert_contain 'Your account has been updated successfully.'

assert warden.authenticated?(:user)
assert_equal "user.new@example.com", User.to_adapter.find_first.email
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
Expand Down
6 changes: 6 additions & 0 deletions test/rails_app/config/initializers/devise.rb
Expand Up @@ -180,6 +180,12 @@
# 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

ActiveSupport.on_load(:devise_failure_app) do
require "lazy_load_test_module"
include LazyLoadTestModule
Expand Down

0 comments on commit e3a00b2

Please sign in to comment.