UploadRecovery should recover attachments too.

This commit is contained in:
Guo Xiang Tan 2018-09-19 10:44:36 +08:00
parent 5a9b029014
commit 4a92c5b2d6
4 changed files with 63 additions and 23 deletions

View File

@ -168,6 +168,10 @@ class Upload < ActiveRecord::Base
Digest::SHA1.file(path).hexdigest
end
def self.extract_upload_url(url)
url.match(/(\/original\/\dX[\/\.\w]*\/([a-zA-Z0-9]+)[\.\w]*)/)
end
def self.get_from_url(url)
return if url.blank?
@ -177,7 +181,7 @@ class Upload < ActiveRecord::Base
end
return if uri&.path.blank?
data = uri.path.match(/(\/original\/\dX[\/\.\w]*\/([a-zA-Z0-9]+)[\.\w]*)/)
data = extract_upload_url(uri.path)
return if data.blank?
sha1 = data[2]
upload = nil

View File

@ -8,18 +8,36 @@ class UploadRecovery
begin
analyzer = PostAnalyzer.new(post.raw, post.topic_id)
analyzer.cooked_stripped.css("img").each do |img|
if dom_class = img["class"]
if (Post.white_listed_image_classes & dom_class.split).count > 0
next
analyzer.cooked_stripped.css("img", "a").each do |media|
if media.name == "img"
if dom_class = media["class"]
if (Post.white_listed_image_classes & dom_class.split).count > 0
next
end
end
end
if img["data-orig-src"]
if @dry_run
puts "#{post.full_url} #{img["data-orig-src"]}"
else
recover_post_upload(post, img["data-orig-src"])
orig_src = media["data-orig-src"]
if orig_src
if @dry_run
puts "#{post.full_url} #{orig_src}"
else
recover_post_upload(post, Upload.sha1_from_short_url(orig_src))
end
end
elsif media.name == "a"
href = media["href"]
if data = Upload.extract_upload_url(href)
sha1 = data[2]
unless upload = Upload.get_from_url(href)
if @dry_run
puts "#{post.full_url} #{href}"
else
recover_post_upload(post, sha1)
end
end
end
end
end
@ -32,8 +50,7 @@ class UploadRecovery
private
def recover_post_upload(post, short_url)
sha1 = Upload.sha1_from_short_url(short_url)
def recover_post_upload(post, sha1)
return unless sha1.present?
attributes = {

5
spec/fixtures/pdf/small.pdf vendored Normal file
View File

@ -0,0 +1,5 @@
%PDF-1.
1 0 obj<</Pages 2 0 R>>endobj
2 0 obj<</Kids[3 0 R]/Count 1>>endobj
3 0 obj<</Parent 2 0 R>>endobj
trailer <</Root 1 0 R>>

View File

@ -6,14 +6,24 @@ RSpec.describe UploadRecovery do
let(:upload) do
UploadCreator.new(
file_from_fixtures("logo.png"),
file_from_fixtures("smallest.png"),
"logo.png"
).create_for(user.id)
end
let(:upload2) do
UploadCreator.new(
file_from_fixtures("small.pdf", "pdf"),
"some.pdf"
).create_for(user.id)
end
let(:post) do
Fabricate(:post,
raw: "![logo.png](#{upload.short_url})",
raw: <<~SQL,
![logo.png](#{upload.short_url})
<a class="attachment" href="#{upload2.url}">some.pdf</a>
SQL
user: user
).tap(&:link_post_uploads)
end
@ -21,17 +31,20 @@ RSpec.describe UploadRecovery do
let(:upload_recovery) { UploadRecovery.new }
before do
SiteSetting.authorized_extensions = 'png|pdf'
SiteSetting.queue_jobs = false
end
describe '#recover' do
after do
public_path = "#{Discourse.store.public_dir}#{upload.url}"
[upload, upload2].each do |u|
public_path = "#{Discourse.store.public_dir}#{u.url}"
[
public_path,
public_path.sub("uploads", "uploads/tombstone")
].each { |path| File.delete(path) if File.exists?(path) }
[
public_path,
public_path.sub("uploads", "uploads/tombstone")
].each { |path| File.delete(path) if File.exists?(path) }
end
end
describe 'when given an invalid sha1' do
@ -54,17 +67,18 @@ RSpec.describe UploadRecovery do
upload_recovery.recover(Post.where("updated_at >= ?", 1.day.ago))
end
it 'should recover the upload' do
it 'should recover uploads and attachments' do
stub_request(:get, "http://test.localhost#{upload.url}")
.to_return(status: 200)
expect do
upload.destroy!
end.to change { post.reload.uploads.count }.from(1).to(0)
upload2.destroy!
end.to change { post.reload.uploads.count }.from(2).to(0)
expect do
upload_recovery.recover
end.to change { post.reload.uploads.count }.from(0).to(1)
end.to change { post.reload.uploads.count }.from(0).to(2)
end
end
end