diff --git a/lib/devise/models/confirmable.rb b/lib/devise/models/confirmable.rb index 90cd0ba5..aadb10d1 100644 --- a/lib/devise/models/confirmable.rb +++ b/lib/devise/models/confirmable.rb @@ -8,6 +8,8 @@ module Devise extend ClassMethods after_create :send_confirmation_instructions + before_update :reset_confirmation, :if => :email_changed? + after_update :send_confirmation_instructions, :if => :email_changed? end end @@ -32,10 +34,28 @@ module Devise # Send confirmation instructions by email # def send_confirmation_instructions - reset_perishable_token! ::Notifier.deliver_confirmation_instructions(self) end + # Remove confirmation date and send confirmation instructions, to ensure + # after sending these instructions the user won't be able to sign in without + # confirming it's account + # + def reset_confirmation! + reset_confirmation + reset_perishable_token! + send_confirmation_instructions + end + + private + + # Remove confirmation date from the user, ensuring after a user update it's + # email, it won't be able to sign in without confirming it. + # + def reset_confirmation + self.confirmed_at = nil + end + module ClassMethods # Hook default authenticate to test whether the account is confirmed or not @@ -53,7 +73,11 @@ module Devise # def send_confirmation_instructions(options={}) confirmable = find_or_initialize_with_error_by_email(options[:email]) - confirmable.send_confirmation_instructions unless confirmable.new_record? + confirmable.reset_confirmation! unless confirmable.new_record? +# unless confirmable.new_record? +# confirmable.reset_confirmation! +# confirmable.send_confirmation_instructions +# end confirmable end diff --git a/test/models/confirmable_test.rb b/test/models/confirmable_test.rb index 9a5f9acc..6e19fee7 100644 --- a/test/models/confirmable_test.rb +++ b/test/models/confirmable_test.rb @@ -115,10 +115,45 @@ class ConfirmableTest < ActiveSupport::TestCase assert_not_equal token, user.reload.perishable_token end + test 'should reset confirmation status when sending the confirmation instructions' do + user = create_user + assert_not user.confirmed? + user.confirm! + assert user.confirmed? + confirmation_user = User.send_confirmation_instructions(:email => user.email) + assert_not user.reload.confirmed? + end + test 'should send email instructions for the user confirm it\'s email' do user = create_user assert_email_sent do User.send_confirmation_instructions(:email => user.email) end end + + test 'should resend email instructions for the user reconfirming the email if it has changed' do + user = create_user + user.email = 'new_test@example.com' + assert_email_sent do + user.save! + end + end + + test 'should not resend email instructions if the user is updated but the email is not' do + user = create_user + user.confirmed_at = Time.now + assert_email_not_sent do + user.save! + end + end + + test 'should reset confirmation status when updating email' do + user = create_user + assert_not user.confirmed? + user.confirm! + assert user.confirmed? + user.email = 'new_test@example.com' + user.save! + assert_not user.reload.confirmed? + end end