diff --git a/lib/file_store/s3_store.rb b/lib/file_store/s3_store.rb index 076ea2171ab..aa444ba1fce 100644 --- a/lib/file_store/s3_store.rb +++ b/lib/file_store/s3_store.rb @@ -9,6 +9,8 @@ module FileStore class S3Store < BaseStore TOMBSTONE_PREFIX ||= "tombstone/" + attr_reader :s3_helper + def initialize(s3_helper = nil) @s3_helper = s3_helper || S3Helper.new(s3_bucket, TOMBSTONE_PREFIX) end diff --git a/lib/tasks/uploads.rake b/lib/tasks/uploads.rake index 0cf836dfab8..7d12991443d 100644 --- a/lib/tasks/uploads.rake +++ b/lib/tasks/uploads.rake @@ -718,15 +718,17 @@ end task "uploads:list_posts_with_broken_images" => :environment do if ENV["RAILS_DB"] - list_broken_posts + list_broken_posts(recover_from_s3: ENV["RECOVER_MISSING"]) else RailsMultisite::ConnectionManagement.each_connection do |db| - list_broken_posts + list_broken_posts(recover_from_s3: ENV["RECOVER_MISSING"]) end end end -def list_broken_posts +def list_broken_posts(recover_from_s3: false) + object_keys = nil + Post.where("raw LIKE '%upload:\/\/%'").find_each do |post| begin begin @@ -743,6 +745,22 @@ def list_broken_posts if img["data-orig-src"] puts "#{post.full_url} #{img["data-orig-src"]}" + + if recover_from_s3 && Discourse.store.external? + object_keys ||= begin + s3_helper = Discourse.store.s3_helper + + s3_helper.list("original").map(&:key).concat( + s3_helper.list("#{FileStore::S3Store::TOMBSTONE_PREFIX}original").map(&:key) + ) + end + + recover_from_s3_by_sha1( + post: post, + sha1: Upload.sha1_from_short_url(img["data-orig-src"]), + object_keys: object_keys + ) + end end end rescue => e @@ -750,3 +768,28 @@ def list_broken_posts end end end + +def recover_from_s3_by_sha1(post:, sha1:, object_keys: []) + object_keys.each do |key| + if key =~ /#{sha1}/ + url = "https:#{SiteSetting.Upload.absolute_base_url}/#{key}" + + begin + tmp = FileHelper.download( + url, + max_file_size: SiteSetting.max_image_size_kb.kilobytes, + tmp_file_name: "recover_from_s3" + ) + + upload = UploadCreator.new( + tmp, + File.basename(key) + ).create_for(post.user_id) + + post.rebake! if upload.persisted? + ensure + tmp&.close + end + end + end +end