FIX: Don't error out when loading a badge with a deleted image (#27688)

Badges can have their associated image uploads deleted. When this happens, any user who has that badge will have their profile page error out.

After this fix, when deleting an upload that's associated with a badge, we nullify the foreign key ID on the badge. This makes the existing safeguard work correctly.
This commit is contained in:
Ted Johansson 2024-07-04 10:03:09 +08:00 committed by GitHub
parent 947249719a
commit 6aa8d97f32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 4 deletions

View File

@ -27,6 +27,7 @@ class Upload < ActiveRecord::Base
has_many :upload_references, dependent: :destroy has_many :upload_references, dependent: :destroy
has_many :posts, through: :upload_references, source: :target, source_type: "Post" has_many :posts, through: :upload_references, source: :target, source_type: "Post"
has_many :topic_thumbnails has_many :topic_thumbnails
has_many :badges, foreign_key: :image_upload_id, dependent: :nullify
attr_accessor :for_group_message attr_accessor :for_group_message
attr_accessor :for_theme attr_accessor :for_theme

View File

@ -98,12 +98,33 @@ RSpec.describe Badge do
end end
describe "#image_url" do describe "#image_url" do
it "has CDN url" do before do
SiteSetting.enable_s3_uploads = true SiteSetting.enable_s3_uploads = true
SiteSetting.s3_cdn_url = "https://some-s3-cdn.amzn.com" SiteSetting.s3_cdn_url = "https://some-s3-cdn.amzn.com"
upload = Fabricate(:upload_s3) end
badge = Fabricate(:badge, image_upload_id: upload.id)
expect(badge.image_url).to start_with("https://some-s3-cdn.amzn.com") context "when the badge has an existing image" do
it "has a CDN url" do
upload = Fabricate(:upload_s3)
badge = Fabricate(:badge, image_upload_id: upload.id)
expect(badge.image_url).to start_with("https://some-s3-cdn.amzn.com")
end
end
context "when the badge does not have a related image" do
it "does not have a CDN url" do
upload = Fabricate(:upload_s3)
badge = Fabricate(:badge, image_upload_id: upload.id)
store = stub
store.expects(:remove_upload).returns(true)
Discourse.stubs(:store).returns(store)
upload.destroy!
expect(badge.reload.image_url).to eq(nil)
end
end end
end end

View File

@ -16,6 +16,8 @@ RSpec.describe Upload do
let(:attachment_path) { __FILE__ } let(:attachment_path) { __FILE__ }
let(:attachment) { File.new(attachment_path) } let(:attachment) { File.new(attachment_path) }
it { is_expected.to have_many(:badges).dependent(:nullify) }
describe ".with_no_non_post_relations" do describe ".with_no_non_post_relations" do
it "does not find non-post related uploads" do it "does not find non-post related uploads" do
post_upload = Fabricate(:upload) post_upload = Fabricate(:upload)