FIX: Do not add same email multiple times (#12322)
The user and an admin could create multiple email change requests for the same user. If any of the requests was validated and it became primary, the other request could not be deleted anymore.
This commit is contained in:
parent
92ad2182f5
commit
9bd436c20b
|
@ -283,17 +283,14 @@ class UsersController < ApplicationController
|
||||||
user = fetch_user_from_params
|
user = fetch_user_from_params
|
||||||
guardian.ensure_can_edit!(user)
|
guardian.ensure_can_edit!(user)
|
||||||
|
|
||||||
user_email = user.user_emails.find_by(email: params[:email])
|
|
||||||
if user_email&.primary
|
|
||||||
return render json: failed_json, status: 428
|
|
||||||
end
|
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
if user_email
|
if email = user.user_emails.find_by(email: params[:email], primary: false)
|
||||||
user_email.destroy
|
email.destroy
|
||||||
DiscourseEvent.trigger(:user_updated, user)
|
DiscourseEvent.trigger(:user_updated, user)
|
||||||
elsif
|
elsif change_requests = user.email_change_requests.where(new_email: params[:email]).presence
|
||||||
user.email_change_requests.where(new_email: params[:email]).destroy_all
|
change_requests.destroy_all
|
||||||
|
else
|
||||||
|
return render json: failed_json, status: 428
|
||||||
end
|
end
|
||||||
|
|
||||||
if current_user.staff? && current_user != user
|
if current_user.staff? && current_user != user
|
||||||
|
|
|
@ -41,10 +41,10 @@ class EmailUpdater
|
||||||
UserHistory.create!(action: UserHistory.actions[:add_email], acting_user_id: @user.id)
|
UserHistory.create!(action: UserHistory.actions[:add_email], acting_user_id: @user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
change_req = EmailChangeRequest.find_or_initialize_by(
|
change_req = EmailChangeRequest.find_or_initialize_by(user_id: @user.id, new_email: email)
|
||||||
user_id: @user.id, new_email: email, requested_by: @guardian.user
|
|
||||||
)
|
|
||||||
if change_req.new_record?
|
if change_req.new_record?
|
||||||
|
change_req.requested_by = @guardian.user
|
||||||
change_req.old_email = old_email
|
change_req.old_email = old_email
|
||||||
change_req.new_email = email
|
change_req.new_email = email
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,6 +17,15 @@ describe EmailUpdater do
|
||||||
expect(updater.errors.messages[:base].first).to be I18n.t("change_email.error_staged")
|
expect(updater.errors.messages[:base].first).to be I18n.t("change_email.error_staged")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does not create multiple email change requests" do
|
||||||
|
user = Fabricate(:user)
|
||||||
|
|
||||||
|
EmailUpdater.new(guardian: Fabricate(:admin).guardian, user: user).change_to(new_email)
|
||||||
|
EmailUpdater.new(guardian: Fabricate(:admin).guardian, user: user).change_to(new_email)
|
||||||
|
|
||||||
|
expect(user.email_change_requests.count).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
context "when an admin is changing the email of another user" do
|
context "when an admin is changing the email of another user" do
|
||||||
let(:admin) { Fabricate(:admin) }
|
let(:admin) { Fabricate(:admin) }
|
||||||
let(:updater) { EmailUpdater.new(guardian: admin.guardian, user: user) }
|
let(:updater) { EmailUpdater.new(guardian: admin.guardian, user: user) }
|
||||||
|
|
|
@ -2852,6 +2852,18 @@ describe UsersController do
|
||||||
expect(event[:event_name]).to eq(:user_updated)
|
expect(event[:event_name]).to eq(:user_updated)
|
||||||
expect(event[:params].first).to eq(user)
|
expect(event[:params].first).to eq(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "can destroy duplicate emails" do
|
||||||
|
EmailChangeRequest.create!(
|
||||||
|
user: user,
|
||||||
|
new_email: user.email,
|
||||||
|
change_state: EmailChangeRequest.states[:authorizing_new]
|
||||||
|
)
|
||||||
|
|
||||||
|
delete "/u/#{user.username}/preferences/email.json", params: { email: user_email.email }
|
||||||
|
|
||||||
|
expect(user.email_change_requests).to be_empty
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#is_local_username' do
|
describe '#is_local_username' do
|
||||||
|
|
Loading…
Reference in New Issue