From 5ea89d1fcbe1c7b7fe931c4592b19424208ce93f Mon Sep 17 00:00:00 2001 From: Martin Brennan <martin@discourse.org> Date: Thu, 9 Mar 2023 11:52:26 +1000 Subject: [PATCH] FIX: UploadReference order by tiebreaker for UploadSecurity (#20602) Follow up to 4d2a95ffe6d63b8d2b5019654dd086f6a9bbbd44. Sometimes due to the original UploadReference migration or other issues, multiple UploadReference records can have the exact same created_at date and time. To tiebreak and correct the SQL order when this happens, we can add a secondary `id ASC` ordering when we check for the first upload reference. --- lib/upload_security.rb | 2 +- spec/lib/upload_security_spec.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/upload_security.rb b/lib/upload_security.rb index c00c1376ecf..ecdc3c43b40 100644 --- a/lib/upload_security.rb +++ b/lib/upload_security.rb @@ -143,7 +143,7 @@ class UploadSecurity LEFT JOIN posts ON upload_references.target_type = 'Post' AND upload_references.target_id = posts.id SQL .where("posts.deleted_at IS NULL") - .order(created_at: :asc) + .order("upload_references.created_at ASC, upload_references.id ASC") .first return false if first_reference.blank? PUBLIC_UPLOAD_REFERENCE_TYPES.include?(first_reference.target_type) diff --git a/spec/lib/upload_security_spec.rb b/spec/lib/upload_security_spec.rb index 8834ff4fc40..a4feac8646d 100644 --- a/spec/lib/upload_security_spec.rb +++ b/spec/lib/upload_security_spec.rb @@ -257,6 +257,18 @@ RSpec.describe UploadSecurity do create_secure_post_reference expect(subject.should_be_secure?).to eq(false) end + + context "when the created_at dates for upload references are identical" do + it "orders by id as well and returns false" do + now = Time.zone.now + custom_emoji = CustomEmoji.create(name: "meme", upload: upload) + create_secure_post_reference + + UploadReference.find_by(target: custom_emoji).update!(created_at: now) + UploadReference.find_by(target: post_in_secure_context).update!(created_at: now) + expect(subject.should_be_secure?).to eq(false) + end + end end describe "when the upload is first used for a badge" do