SECURITY: Destroy `EmailToken` when `EmailChangeRequest` is destroyed (#13950)

SECURITY: Destroy EmailToken when EmailChangeRequest is destroyed (#13950)

diff --git a/app/models/email_change_request.rb b/app/models/email_change_request.rb
index 60b0d04..74bb307 100644
--- a/app/models/email_change_request.rb
+++ b/app/models/email_change_request.rb
@@ -1,8 +1,8 @@
 # frozen_string_literal: true
 
 class EmailChangeRequest < ActiveRecord::Base
-  belongs_to :old_email_token, class_name: 'EmailToken'
-  belongs_to :new_email_token, class_name: 'EmailToken'
+  belongs_to :old_email_token, class_name: 'EmailToken', dependent: :destroy
+  belongs_to :new_email_token, class_name: 'EmailToken', dependent: :destroy
   belongs_to :user
   belongs_to :requested_by, class_name: "User", foreign_key: :requested_by_user_id
 
diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb
index c2cb1d3..3f204b0 100644
--- a/spec/requests/users_controller_spec.rb
+++ b/spec/requests/users_controller_spec.rb
@@ -3050,6 +3050,19 @@ describe UsersController do
       expect(user.user_emails.pluck(:email)).to contain_exactly(user_email.email, other_email.email)
       expect(user.email_change_requests).to contain_exactly(request_1)
     end
+
+    it "can destroy associated email tokens" do
+      new_email = 'new.n.cool@example.com'
+      updater = EmailUpdater.new(guardian: user.guardian, user: user)
+
+      expect { updater.change_to(new_email) }
+        .to change { user.email_tokens.count }.by(1)
+
+      expect { delete "/u/#{user.username}/preferences/email.json", params: { email: new_email } }
+        .to change { user.email_tokens.count }.by(-1)
+
+      expect(user.email_tokens.first.email).to eq(user.email)
+    end
   end
 
   describe '#is_local_username' do

GitHub sha: fb14e50741a4880cda22244eded8858e2f5336ef

This commit appears in #13950 which was approved by lis2 and SamSaffron. It was merged by jbrw.