From 70eb18d766d161438d428c62015cfc4fdb6c8724 Mon Sep 17 00:00:00 2001 From: Carlos Antonio da Silva Date: Mon, 6 Mar 2017 16:34:38 -0300 Subject: [PATCH] Notify original user email when the email changes This adds a new setting `send_email_change_notification` which will send an email to the original user email when their email is updated to a new one. It doesn't take into account the reconfirmable setting yet, it will be added next, so that if confirmable is included and reconfirmable is being used, the email will be triggered when the email change is requested, not when confirmed (e.g when we store the email in `unconfirmed_email`, not when it's later copied to `email` when that is confirmed). --- app/mailers/devise/mailer.rb | 4 ++++ app/views/devise/mailer/email_change.html.erb | 3 +++ config/locales/en.yml | 2 ++ lib/devise.rb | 6 +++++- lib/devise/models/database_authenticatable.rb | 13 ++++++++++++- lib/generators/templates/devise.rb | 5 ++++- .../templates/markerb/email_change.markerb | 3 +++ .../templates/markerb/password_change.markerb | 4 ++-- test/models/database_authenticatable_test.rb | 14 +++++++++++++- 9 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 app/views/devise/mailer/email_change.html.erb create mode 100644 lib/generators/templates/markerb/email_change.markerb diff --git a/app/mailers/devise/mailer.rb b/app/mailers/devise/mailer.rb index 555b64d2..0011a060 100644 --- a/app/mailers/devise/mailer.rb +++ b/app/mailers/devise/mailer.rb @@ -17,6 +17,10 @@ if defined?(ActionMailer) devise_mail(record, :unlock_instructions, opts) end + def email_change(record, opts={}) + devise_mail(record, :email_change, opts) + end + def password_change(record, opts={}) devise_mail(record, :password_change, opts) end diff --git a/app/views/devise/mailer/email_change.html.erb b/app/views/devise/mailer/email_change.html.erb new file mode 100644 index 00000000..8486305a --- /dev/null +++ b/app/views/devise/mailer/email_change.html.erb @@ -0,0 +1,3 @@ +

Hello <%= @email %>!

+ +

We're contacting you to notify you that your email has been changed to <%= @resource.email %>.

diff --git a/config/locales/en.yml b/config/locales/en.yml index bd4c3ebc..ac059bbe 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -23,6 +23,8 @@ en: subject: "Reset password instructions" unlock_instructions: subject: "Unlock instructions" + email_change: + subject: "Email Changed" password_change: subject: "Password Changed" omniauth_callbacks: diff --git a/lib/devise.rb b/lib/devise.rb index 7819551f..3f4f4154 100755 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -153,7 +153,11 @@ module Devise mattr_accessor :pepper @@pepper = nil - # Used to enable sending notification to user when their password is changed + # Used to send notification to the original user email when their email is changed. + mattr_accessor :send_email_change_notification + @@send_email_change_notification = false + + # Used to enable sending notification to user when their password is changed. mattr_accessor :send_password_change_notification @@send_password_change_notification = false diff --git a/lib/devise/models/database_authenticatable.rb b/lib/devise/models/database_authenticatable.rb index 70f64609..bda52134 100644 --- a/lib/devise/models/database_authenticatable.rb +++ b/lib/devise/models/database_authenticatable.rb @@ -22,6 +22,7 @@ module Devise extend ActiveSupport::Concern included do + after_update :send_email_change_notification, if: :send_email_change_notification? after_update :send_password_change_notification, if: :send_password_change_notification? attr_reader :password, :current_password @@ -132,6 +133,12 @@ module Devise encrypted_password[0,29] if encrypted_password end + # Send notification to user when email changes. + def send_email_change_notification + send_devise_notification(:email_change, to: email_was) + end + + # Send notification to user when password changes. def send_password_change_notification send_devise_notification(:password_change) end @@ -147,12 +154,16 @@ module Devise Devise::Encryptor.digest(self.class, password) end + def send_email_change_notification? + self.class.send_email_change_notification && email_changed? + end + def send_password_change_notification? self.class.send_password_change_notification && encrypted_password_changed? end module ClassMethods - Devise::Models.config(self, :pepper, :stretches, :send_password_change_notification) + Devise::Models.config(self, :pepper, :stretches, :send_email_change_notification, :send_password_change_notification) # We assume this method already gets the sanitized values from the # DatabaseAuthenticatable strategy. If you are using this method on diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index 4bc37ca5..49060987 100755 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -110,7 +110,10 @@ Devise.setup do |config| # Set up a pepper to generate the hashed password. # config.pepper = '<%= SecureRandom.hex(64) %>' - # Send a notification email when the user's password is changed + # Send a notification to the original email when the user's email is changed. + # config.send_email_change_notification = false + + # Send a notification email when the user's password is changed. # config.send_password_change_notification = false # ==> Configuration for :confirmable diff --git a/lib/generators/templates/markerb/email_change.markerb b/lib/generators/templates/markerb/email_change.markerb new file mode 100644 index 00000000..a46768b5 --- /dev/null +++ b/lib/generators/templates/markerb/email_change.markerb @@ -0,0 +1,3 @@ +Hello <%= @email %>! + +We're contacting you to notify you that your email has been changed to <%= @resource.email %>. diff --git a/lib/generators/templates/markerb/password_change.markerb b/lib/generators/templates/markerb/password_change.markerb index b41daf47..4f9f9620 100644 --- a/lib/generators/templates/markerb/password_change.markerb +++ b/lib/generators/templates/markerb/password_change.markerb @@ -1,3 +1,3 @@ -

Hello <%= @resource.email %>!

+Hello <%= @resource.email %>! -

We're contacting you to notify you that your password has been changed.

+We're contacting you to notify you that your password has been changed. diff --git a/test/models/database_authenticatable_test.rb b/test/models/database_authenticatable_test.rb index dafd7b81..11bd69a6 100644 --- a/test/models/database_authenticatable_test.rb +++ b/test/models/database_authenticatable_test.rb @@ -236,12 +236,24 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase end end - test 'should email on password change when configured' do + test 'should notify previous email on email change when configured' do + swap Devise, send_email_change_notification: true do + user = create_user + original_email = user.email + assert_email_sent original_email do + assert user.update_attributes(email: 'new-email@example.com') + end + assert_match original_email, ActionMailer::Base.deliveries.last.body.encoded + end + end + + test 'should notify email on password change when configured' do swap Devise, send_password_change_notification: true do user = create_user assert_email_sent user.email do assert user.update_attributes(password: 'newpass', password_confirmation: 'newpass') end + assert_match user.email, ActionMailer::Base.deliveries.last.body.encoded end end