diff --git a/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb b/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb index dc18b9de0c2..a4c64188c26 100644 --- a/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb +++ b/app/jobs/onceoff/fix_primary_emails_for_staged_users.rb @@ -1,6 +1,23 @@ module Jobs class FixPrimaryEmailsForStagedUsers < Jobs::Onceoff def execute_onceoff(args) + users = User.where(active: false, staged: true).joins(:email_tokens) + destroyer = UserDestroyer.new(Discourse.system_user) + + users.group("email_tokens.email") + .having("COUNT(email_tokens.email) > 1") + .count + .each_key do |email| + + users.where("email_tokens.email = ?", email) + .order(id: :asc) + .offset(1) + .each do |user| + + destroyer.destroy(user) + end + end + User.exec_sql <<~SQL INSERT INTO user_emails ( user_id, @@ -8,10 +25,10 @@ module Jobs "primary", created_at, updated_at - ) SELECT + ) SELECT DISTINCT users.id, email_tokens.email, - 'TRUE', + TRUE, users.created_at, users.updated_at FROM users diff --git a/spec/jobs/clean_up_unused_staged_users.rb b/spec/jobs/clean_up_unused_staged_users_spec.rb similarity index 100% rename from spec/jobs/clean_up_unused_staged_users.rb rename to spec/jobs/clean_up_unused_staged_users_spec.rb diff --git a/spec/jobs/fix_primary_emails_for_staged_users_spec.rb b/spec/jobs/fix_primary_emails_for_staged_users_spec.rb new file mode 100644 index 00000000000..1951c3b6506 --- /dev/null +++ b/spec/jobs/fix_primary_emails_for_staged_users_spec.rb @@ -0,0 +1,25 @@ +require 'rails_helper' + +RSpec.describe Jobs::FixPrimaryEmailsForStagedUsers do + it 'should clean up duplicated staged users' do + common_email = 'test@reply' + + staged_user = Fabricate(:user, staged: true, active: false) + staged_user2 = Fabricate(:user, staged: true, active: false) + staged_user3 = Fabricate(:user, staged: true, active: false) + + [staged_user, staged_user2, staged_user3].each do |user| + user.email_tokens = [Fabricate.create(:email_token, email: common_email, user: user)] + end + + active_user = Fabricate(:coding_horror) + + UserEmail.delete_all + + expect { described_class.new.execute_onceoff({}) } + .to change { User.count }.by(-2) + + expect(User.all).to contain_exactly(Discourse.system_user, staged_user, active_user) + expect(staged_user.reload.email).to eq(common_email) + end +end