mirror of
https://github.com/discourse/discourse.git
synced 2024-12-01 12:24:37 +08:00
254b57c812
A follow-up correction to this change https://github.com/discourse/discourse/pull/9001. When admin changes staff email still enforce old email confirm. Only allow auto-confirm of a new email by admin IF the target user is not also an admin. If an admin gets locked out of their email the site admin can use the rails console to solve the issue in a pinch.
246 lines
8.8 KiB
Ruby
246 lines
8.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
describe EmailUpdater do
|
|
let(:old_email) { 'old.email@example.com' }
|
|
let(:new_email) { 'new.email@example.com' }
|
|
|
|
it "provides better error message when a staged user has the same email" do
|
|
Fabricate(:user, staged: true, email: new_email)
|
|
|
|
user = Fabricate(:user, email: old_email)
|
|
updater = EmailUpdater.new(guardian: user.guardian, user: user)
|
|
updater.change_to(new_email)
|
|
|
|
expect(updater.errors).to be_present
|
|
expect(updater.errors.messages[:base].first).to be I18n.t("change_email.error_staged")
|
|
end
|
|
|
|
context "when an admin is changing the email of another user" do
|
|
let(:admin) { Fabricate(:admin) }
|
|
let(:updater) { EmailUpdater.new(guardian: user.guardian, user: user, initiating_user: admin) }
|
|
|
|
def expect_old_email_job
|
|
Jobs.expects(:enqueue).with(:critical_user_email, has_entries(to_address: old_email, type: :notify_old_email, user_id: user.id))
|
|
end
|
|
|
|
def expect_forgot_password_job
|
|
Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :forgot_password, user_id: user.id))
|
|
end
|
|
|
|
context "for a regular user" do
|
|
let(:user) { Fabricate(:user, email: old_email) }
|
|
|
|
it "does not send an email to the user for them to confirm their new email but still sends the notification to the old email" do
|
|
Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :confirm_new_email, to_address: new_email)).never
|
|
expect_old_email_job
|
|
expect_forgot_password_job
|
|
updater.change_to(new_email)
|
|
end
|
|
|
|
it "creates a change request authorizing the new email and immediately confirms it " do
|
|
updater.change_to(new_email)
|
|
change_req = user.email_change_requests.first
|
|
expect(change_req.change_state).to eq(EmailChangeRequest.states[:complete])
|
|
end
|
|
|
|
it "sends a reset password email to the user so they can set a password for their new email" do
|
|
expect_old_email_job
|
|
expect_forgot_password_job
|
|
updater.change_to(new_email)
|
|
end
|
|
end
|
|
|
|
context "for a staff user" do
|
|
let(:user) { Fabricate(:moderator, email: old_email) }
|
|
|
|
before do
|
|
Jobs.expects(:enqueue).once.with(:critical_user_email, has_entries(type: :confirm_old_email, to_address: old_email))
|
|
updater.change_to(new_email)
|
|
@change_req = user.email_change_requests.first
|
|
end
|
|
|
|
it "starts the old confirmation process" do
|
|
expect(updater.errors).to be_blank
|
|
|
|
expect(@change_req.old_email).to eq(old_email)
|
|
expect(@change_req.new_email).to eq(new_email)
|
|
expect(@change_req).to be_present
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:authorizing_old])
|
|
|
|
expect(@change_req.old_email_token.email).to eq(old_email)
|
|
expect(@change_req.new_email_token).to be_blank
|
|
end
|
|
|
|
it "does not immediately confirm the request" do
|
|
expect(@change_req.change_state).not_to eq(EmailChangeRequest.states[:complete])
|
|
end
|
|
end
|
|
|
|
context "when changing their own email" do
|
|
let(:user) { admin }
|
|
|
|
before do
|
|
admin.update(email: old_email)
|
|
Jobs.expects(:enqueue).once.with(:critical_user_email, has_entries(type: :confirm_old_email, to_address: old_email))
|
|
updater.change_to(new_email)
|
|
@change_req = user.email_change_requests.first
|
|
end
|
|
|
|
it "starts the old confirmation process" do
|
|
expect(updater.errors).to be_blank
|
|
|
|
expect(@change_req.old_email).to eq(old_email)
|
|
expect(@change_req.new_email).to eq(new_email)
|
|
expect(@change_req).to be_present
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:authorizing_old])
|
|
|
|
expect(@change_req.old_email_token.email).to eq(old_email)
|
|
expect(@change_req.new_email_token).to be_blank
|
|
end
|
|
|
|
it "does not immediately confirm the request" do
|
|
expect(@change_req.change_state).not_to eq(EmailChangeRequest.states[:complete])
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'as a regular user' do
|
|
let(:user) { Fabricate(:user, email: old_email) }
|
|
let(:updater) { EmailUpdater.new(guardian: user.guardian, user: user) }
|
|
|
|
before do
|
|
Jobs.expects(:enqueue).once.with(:critical_user_email, has_entries(type: :confirm_new_email, to_address: new_email))
|
|
updater.change_to(new_email)
|
|
@change_req = user.email_change_requests.first
|
|
end
|
|
|
|
it "starts the new confirmation process" do
|
|
expect(updater.errors).to be_blank
|
|
|
|
expect(@change_req).to be_present
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:authorizing_new])
|
|
|
|
expect(@change_req.old_email).to eq(old_email)
|
|
expect(@change_req.new_email).to eq(new_email)
|
|
expect(@change_req.old_email_token).to be_blank
|
|
expect(@change_req.new_email_token.email).to eq(new_email)
|
|
end
|
|
|
|
context 'confirming an invalid token' do
|
|
it "produces an error" do
|
|
updater.confirm('random')
|
|
expect(updater.errors).to be_present
|
|
expect(user.reload.email).not_to eq(new_email)
|
|
end
|
|
end
|
|
|
|
context 'confirming a valid token' do
|
|
it "updates the user's email" do
|
|
Jobs.expects(:enqueue).once.with(:critical_user_email, has_entries(type: :notify_old_email, to_address: old_email))
|
|
updater.confirm(@change_req.new_email_token.token)
|
|
expect(updater.errors).to be_blank
|
|
expect(user.reload.email).to eq(new_email)
|
|
|
|
@change_req.reload
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:complete])
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
context 'as a staff user' do
|
|
let(:user) { Fabricate(:moderator, email: old_email) }
|
|
let(:updater) { EmailUpdater.new(guardian: user.guardian, user: user) }
|
|
|
|
before do
|
|
Jobs.expects(:enqueue).once.with(:critical_user_email, has_entries(type: :confirm_old_email, to_address: old_email))
|
|
updater.change_to(new_email)
|
|
@change_req = user.email_change_requests.first
|
|
end
|
|
|
|
it "starts the old confirmation process" do
|
|
expect(updater.errors).to be_blank
|
|
|
|
expect(@change_req.old_email).to eq(old_email)
|
|
expect(@change_req.new_email).to eq(new_email)
|
|
expect(@change_req).to be_present
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:authorizing_old])
|
|
|
|
expect(@change_req.old_email_token.email).to eq(old_email)
|
|
expect(@change_req.new_email_token).to be_blank
|
|
end
|
|
|
|
context 'confirming an invalid token' do
|
|
it "produces an error" do
|
|
updater.confirm('random')
|
|
expect(updater.errors).to be_present
|
|
expect(user.reload.email).not_to eq(new_email)
|
|
end
|
|
end
|
|
|
|
context 'confirming a valid token' do
|
|
before do
|
|
Jobs.expects(:enqueue).once.with(:critical_user_email, has_entries(type: :confirm_new_email, to_address: new_email))
|
|
updater.confirm(@change_req.old_email_token.token)
|
|
@change_req.reload
|
|
end
|
|
|
|
it "starts the new update process" do
|
|
expect(updater.errors).to be_blank
|
|
expect(user.reload.email).to eq(old_email)
|
|
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:authorizing_new])
|
|
expect(@change_req.new_email_token).to be_present
|
|
end
|
|
|
|
it "cannot be confirmed twice" do
|
|
updater.confirm(@change_req.old_email_token.token)
|
|
expect(updater.errors).to be_present
|
|
expect(user.reload.email).to eq(old_email)
|
|
|
|
@change_req.reload
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:authorizing_new])
|
|
expect(@change_req.new_email_token.email).to eq(new_email)
|
|
end
|
|
|
|
context "completing the new update process" do
|
|
before do
|
|
Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :notify_old_email, to_address: old_email)).never
|
|
updater.confirm(@change_req.new_email_token.token)
|
|
end
|
|
|
|
it "updates the user's email" do
|
|
expect(updater.errors).to be_blank
|
|
expect(user.reload.email).to eq(new_email)
|
|
|
|
@change_req.reload
|
|
expect(@change_req.change_state).to eq(EmailChangeRequest.states[:complete])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'hide_email_address_taken is enabled' do
|
|
before do
|
|
SiteSetting.hide_email_address_taken = true
|
|
end
|
|
|
|
let(:user) { Fabricate(:user, email: old_email) }
|
|
let(:existing) { Fabricate(:user, email: new_email) }
|
|
let(:updater) { EmailUpdater.new(guardian: user.guardian, user: user) }
|
|
|
|
it "doesn't error if user exists with new email" do
|
|
updater.change_to(existing.email)
|
|
expect(updater.errors).to be_blank
|
|
expect(user.email_change_requests).to be_empty
|
|
end
|
|
|
|
it 'sends an email to the owner of the account with the new email' do
|
|
Jobs.expects(:enqueue).once.with(:critical_user_email, has_entries(type: :account_exists, user_id: existing.id))
|
|
updater.change_to(existing.email)
|
|
end
|
|
end
|
|
end
|