Quellcode durchsuchen

Add confirmation step for email changes (#6071)

* Add confirmation step for email changes

This adds a confirmation step for email changes of existing users.
Like the initial account confirmation, a confirmation link is sent
to the new address.

Additionally, a notification is sent to the existing address when
the change is initiated. This message includes instruction to reset
the password immediately or to contact the instance admin if the
change was not initiated by the account owner.

Fixes #3871

* Add review fixes
master
Patrick Figel vor 6 Jahren
committed by Eugen Rochko
Ursprung
Commit
04ecf44c2f
12 geänderte Dateien mit 116 neuen und 8 gelöschten Zeilen
  1. +1
    -1
      Gemfile
  2. +1
    -1
      Gemfile.lock
  3. +4
    -0
      app/controllers/auth/registrations_controller.rb
  4. +14
    -1
      app/mailers/user_mailer.rb
  5. +7
    -4
      app/models/user.rb
  6. +15
    -0
      app/views/user_mailer/email_changed.en.html.erb
  7. +13
    -0
      app/views/user_mailer/email_changed.en.text.erb
  8. +15
    -0
      app/views/user_mailer/reconfirmation_instructions.en.html.erb
  9. +12
    -0
      app/views/user_mailer/reconfirmation_instructions.en.text.erb
  10. +4
    -1
      config/initializers/devise.rb
  11. +4
    -0
      config/locales/devise.en.yml
  12. +26
    -0
      spec/mailers/user_mailer_spec.rb

+ 1
- 1
Gemfile Datei anzeigen

@@ -28,7 +28,7 @@ gem 'browser'
gem 'charlock_holmes', '~> 0.7.5'
gem 'iso-639'
gem 'cld3', '~> 3.2.0'
gem 'devise', '~> 4.2'
gem 'devise', '~> 4.3'
gem 'devise-two-factor', '~> 3.0'
gem 'doorkeeper', '~> 4.2'
gem 'fast_blank', '~> 1.0'


+ 1
- 1
Gemfile.lock Datei anzeigen

@@ -561,7 +561,7 @@ DEPENDENCIES
charlock_holmes (~> 0.7.5)
cld3 (~> 3.2.0)
climate_control (~> 0.2)
devise (~> 4.2)
devise (~> 4.3)
devise-two-factor (~> 3.0)
doorkeeper (~> 4.2)
dotenv-rails (~> 2.2)


+ 4
- 0
app/controllers/auth/registrations_controller.rb Datei anzeigen

@@ -37,6 +37,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController
new_user_session_path
end

def after_update_path_for(_resource)
edit_user_registration_path
end

def check_enabled_registrations
redirect_to root_path if single_user_mode? || !allowed_registrations?
end


+ 14
- 1
app/mailers/user_mailer.rb Datei anzeigen

@@ -13,7 +13,9 @@ class UserMailer < Devise::Mailer
return if @resource.disabled?

I18n.with_locale(@resource.locale || I18n.default_locale) do
mail to: @resource.unconfirmed_email.blank? ? @resource.email : @resource.unconfirmed_email, subject: I18n.t('devise.mailer.confirmation_instructions.subject', instance: @instance)
mail to: @resource.unconfirmed_email.blank? ? @resource.email : @resource.unconfirmed_email,
subject: I18n.t(@resource.pending_reconfirmation? ? 'devise.mailer.reconfirmation_instructions.subject' : 'devise.mailer.confirmation_instructions.subject', instance: @instance),
template_name: @resource.pending_reconfirmation? ? 'reconfirmation_instructions' : 'confirmation_instructions'
end
end

@@ -39,4 +41,15 @@ class UserMailer < Devise::Mailer
mail to: @resource.email, subject: I18n.t('devise.mailer.password_change.subject')
end
end

def email_changed(user, **)
@resource = user
@instance = Rails.configuration.x.local_domain

return if @resource.disabled?

I18n.with_locale(@resource.locale || I18n.default_locale) do
mail to: @resource.email, subject: I18n.t('devise.mailer.email_changed.subject')
end
end
end

+ 7
- 4
app/models/user.rb Datei anzeigen

@@ -41,12 +41,15 @@ class User < ApplicationRecord

ACTIVE_DURATION = 14.days

devise :registerable, :recoverable,
:rememberable, :trackable, :validatable, :confirmable,
:two_factor_authenticatable, :two_factor_backupable,
otp_secret_encryption_key: ENV['OTP_SECRET'],
devise :two_factor_authenticatable,
otp_secret_encryption_key: ENV['OTP_SECRET']
devise :two_factor_backupable,
otp_number_of_backup_codes: 10

devise :registerable, :recoverable, :rememberable, :trackable, :validatable,
:confirmable

belongs_to :account, inverse_of: :user, required: true
belongs_to :invite, counter_cache: :uses
accepts_nested_attributes_for :account


+ 15
- 0
app/views/user_mailer/email_changed.en.html.erb Datei anzeigen

@@ -0,0 +1,15 @@
<p>Hello <%= @resource.email %>!</p>

<% if @resource&.unconfirmed_email? %>
<p>We're contacting you to notify you that the email you use on <%= @instance %> is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
<p>We're contacting you to notify you that the email you use on <%= @instance %> has been changed to <%= @resource.email %>.</p>
<% end %>

<p>
If you did not change your email, it is likely that someone has gained access to your account. Please change your password immediately or contact the instance admin if you're locked out of your account.
</p>

<p>Sincerely,<p>

<p>The <%= @instance %> team</p>

+ 13
- 0
app/views/user_mailer/email_changed.en.text.erb Datei anzeigen

@@ -0,0 +1,13 @@
Hello <%= @resource.email %>!

<% if @resource&.unconfirmed_email? %>
We're contacting you to notify you that the email you use on <%= @instance %> is being changed to <%= @resource.unconfirmed_email %>.
<% else %>
We're contacting you to notify you that the email you use on <%= @instance %> has been changed to <%= @resource.email %>.
<% end %>

If you did not change your email, it is likely that someone has gained access to your account. Please change your password immediately or contact the instance admin if you're locked out of your account.

Sincerely,

The <%= @instance %> team

+ 15
- 0
app/views/user_mailer/reconfirmation_instructions.en.html.erb Datei anzeigen

@@ -0,0 +1,15 @@
<p>Hello <%= @resource.unconfirmed_email %>!</p>

<p>You requested a change to the email address you use on <%= @instance %>.</p>

<p>To confirm your new email, please click on the following link:<br>
<%= link_to 'Confirm my email address', confirmation_url(@resource, confirmation_token: @token) %></p>

<p>If the above link did not work, copy and paste this URL into your address bar: <br>
<span><%= confirmation_url(@resource, confirmation_token: @token) %></span>

<p>Please also check out our <%= link_to 'terms and conditions', terms_url %>.</p>

<p>Sincerely,<p>

<p>The <%= @instance %> team</p>

+ 12
- 0
app/views/user_mailer/reconfirmation_instructions.en.text.erb Datei anzeigen

@@ -0,0 +1,12 @@
Hello <%= @resource.unconfirmed_email %>!

You requested a change to the email address you use on <%= @instance %>.

To confirm your new email, please click on the following link:
<%= confirmation_url(@resource, confirmation_token: @token) %>

Please also check out our terms and conditions <%= terms_url %>

Sincerely,

The <%= @instance %> team

+ 4
- 1
config/initializers/devise.rb Datei anzeigen

@@ -137,6 +137,9 @@ Devise.setup do |config|
# Setup a pepper to generate the encrypted password.
# config.pepper = '104d16705f794923e77c5e5167b52452d00646dc952a2d30b541c24086e647012c7b9625f253c51912e455981e503446772973d5f1638631196c819d7137fad4'

# Send a notification to the original email when the user's email is changed.
config.send_email_changed_notification = true

# Send a notification email when the user's password is changed
config.send_password_change_notification = true

@@ -160,7 +163,7 @@ Devise.setup do |config|
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed, new email is stored in
# unconfirmed_email column, and copied to email column on successful confirmation.
config.reconfirmable = false
config.reconfirmable = true

# Defines which key will be used when confirming an account
# config.confirmation_keys = [:email]


+ 4
- 0
config/locales/devise.en.yml Datei anzeigen

@@ -18,8 +18,12 @@ en:
mailer:
confirmation_instructions:
subject: 'Mastodon: Confirmation instructions for %{instance}'
email_changed:
subject: 'Mastodon: Email changed'
password_change:
subject: 'Mastodon: Password changed'
reconfirmation_instructions:
subject: 'Mastodon: Confirm email for %{instance}'
reset_password_instructions:
subject: 'Mastodon: Reset password instructions'
unlock_instructions:


+ 26
- 0
spec/mailers/user_mailer_spec.rb Datei anzeigen

@@ -33,6 +33,20 @@ describe UserMailer, type: :mailer do
instance: Rails.configuration.x.local_domain
end

describe 'reconfirmation_instructions' do
let(:mail) { UserMailer.confirmation_instructions(receiver, 'spec') }

it 'renders reconfirmation instructions' do
receiver.update!(email: 'new-email@example.com', locale: nil)
expect(mail.body.encoded).to include 'new-email@example.com'
expect(mail.body.encoded).to include 'spec'
expect(mail.body.encoded).to include Rails.configuration.x.local_domain
expect(mail.subject).to eq I18n.t('devise.mailer.reconfirmation_instructions.subject',
instance: Rails.configuration.x.local_domain,
locale: I18n.default_locale)
end
end

describe 'reset_password_instructions' do
let(:mail) { UserMailer.reset_password_instructions(receiver, 'spec') }

@@ -57,4 +71,16 @@ describe UserMailer, type: :mailer do
include_examples 'localized subject',
'devise.mailer.password_change.subject'
end

describe 'email_changed' do
let(:mail) { UserMailer.email_changed(receiver) }

it 'renders email change notification' do
receiver.update!(locale: nil)
expect(mail.body.encoded).to include receiver.email
end

include_examples 'localized subject',
'devise.mailer.email_changed.subject'
end
end

Laden…
Abbrechen
Speichern