From aedc5e363c2a8fd36b08f57a1df585d1066c9acf Mon Sep 17 00:00:00 2001 From: Kyle Drake Date: Mon, 3 Nov 2014 17:36:20 -0800 Subject: [PATCH] start tracking files in our database --- migrations/052_site_files_composite_keys.rb | 30 ++++++ models/site.rb | 21 +++- models/site_file.rb | 6 ++ tests/files/img/test.jpg | Bin 0 -> 37714 bytes tests/site_file_tests.rb | 111 ++++++++++++++------ 5 files changed, 132 insertions(+), 36 deletions(-) create mode 100644 migrations/052_site_files_composite_keys.rb create mode 100644 models/site_file.rb create mode 100644 tests/files/img/test.jpg diff --git a/migrations/052_site_files_composite_keys.rb b/migrations/052_site_files_composite_keys.rb new file mode 100644 index 00000000..d93edce8 --- /dev/null +++ b/migrations/052_site_files_composite_keys.rb @@ -0,0 +1,30 @@ +Sequel.migration do + up { + DB.drop_table :site_files + + DB.create_table! :site_files do + Integer :site_id + String :path + Bigint :size + String :sha1_hash + Boolean :is_directory, default: false + DateTime :created_at + DateTime :updated_at + primary_key [:site_id, :path], :name => :site_files_pk + end + } + + down { + DB.drop_table :site_files + + DB.create_table! :site_files do + Integer :site_id, index: true + String :path + Bigint :size + String :sha1_hash + Boolean :is_directory, default: false + DateTime :created_at + DateTime :updated_at + end + } +end \ No newline at end of file diff --git a/models/site.rb b/models/site.rb index d28b43ec..21db0433 100644 --- a/models/site.rb +++ b/models/site.rb @@ -144,6 +144,8 @@ class Site < Sequel::Model many_to_one :parent, :key => :parent_site_id, :class => self one_to_many :children, :key => :parent_site_id, :class => self + one_to_many :site_files + def account_sites_dataset Site.where(Sequel.|({id: owner.id}, {parent_site_id: owner.id})).order(:parent_site_id.desc, :username) end @@ -453,8 +455,11 @@ class Site < Sequel::Model relative_path = scrubbed_path path path = files_path path - if File.exist?(path) && - Digest::SHA1.file(path).digest == Digest::SHA1.file(uploaded.path).digest + site_file = site_files_dataset.where(path: relative_path).first + + uploaded_sha1 = Digest::SHA1.file(uploaded.path).hexdigest + + if site_file && site_file.sha1_hash == uploaded_sha1 return false end @@ -504,9 +509,20 @@ class Site < Sequel::Model FileUtils.mkdir_p dirname end + uploaded_size = uploaded.size + FileUtils.mv uploaded.path, path File.chmod 0640, path + site_file ||= SiteFile.new site_id: self.id, path: relative_path + + site_file.set_all( + size: uploaded_size, + sha1_hash: uploaded_sha1, + updated_at: Time.now + ) + site_file.save + purge_cache path ext = File.extname(path).gsub(/^./, '') @@ -581,6 +597,7 @@ class Site < Sequel::Model path = path[1..path.length] if path[0] == '/' + site_files_dataset.where(path: path).delete SiteChangeFile.filter(site_id: self.id, filename: path).delete true diff --git a/models/site_file.rb b/models/site_file.rb new file mode 100644 index 00000000..7e714808 --- /dev/null +++ b/models/site_file.rb @@ -0,0 +1,6 @@ +class SiteFile < Sequel::Model + + unrestrict_primary_key + plugin :update_primary_key + many_to_one :site +end \ No newline at end of file diff --git a/tests/files/img/test.jpg b/tests/files/img/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff7f01a5992f5740545c1d7f68054f1744407fa9 GIT binary patch literal 37714 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 literal 0 HcmV?d00001 diff --git a/tests/site_file_tests.rb b/tests/site_file_tests.rb index afb06acf..76e0a2ed 100644 --- a/tests/site_file_tests.rb +++ b/tests/site_file_tests.rb @@ -1,62 +1,88 @@ require_relative './environment.rb' +include Rack::Test::Methods + +def app + Sinatra::Application +end + +def upload(hash) + post '/site_files/upload', hash.merge(csrf_token: 'abcd'), {'rack.session' => { 'id' => @site.id, '_csrf_token' => 'abcd' }} +end + +def delete_file(hash) + post '/site_files/delete', hash.merge(csrf_token: 'abcd'), {'rack.session' => { 'id' => @site.id, '_csrf_token' => 'abcd' }} +end + describe 'site_files' do + before do + @site = Fabricate :site + ThumbnailWorker.jobs.clear + PurgeCacheWorker.jobs.clear + ScreenshotWorker.jobs.clear + end + + describe 'delete' do + it 'works' do + upload 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') + file_path = @site.files_path 'test.jpg' + File.exists?(file_path).must_equal true + delete_file filename: 'test.jpg' + File.exists?(file_path).must_equal false + SiteFile[site_id: @site.id, path: 'test.jpg'].must_be_nil + end + end + describe 'upload' do it 'succeeds with index.html file' do - site = Fabricate :site - site.site_changed.must_equal false - PurgeCacheWorker.jobs.clear - ScreenshotWorker.jobs.clear - - post '/site_files/upload', { - 'files[]' => Rack::Test::UploadedFile.new('./tests/files/index.html', 'text/html'), - 'csrf_token' => 'abcd' - }, {'rack.session' => { 'id' => site.id, '_csrf_token' => 'abcd' }} + @site.site_changed.must_equal false + upload 'files[]' => Rack::Test::UploadedFile.new('./tests/files/index.html', 'text/html') last_response.body.must_match /successfully uploaded/i - File.exists?(site.files_path('index.html')).must_equal true + File.exists?(@site.files_path('index.html')).must_equal true args = ScreenshotWorker.jobs.first['args'] - args.first.must_equal site.username + args.first.must_equal @site.username args.last.must_equal 'index.html' - site.reload.site_changed.must_equal true + @site.reload.site_changed.must_equal true end it 'succeeds with valid file' do - site = Fabricate :site - PurgeCacheWorker.jobs.clear - ThumbnailWorker.jobs.clear - post '/site_files/upload', { - 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg'), - 'csrf_token' => 'abcd' - }, {'rack.session' => { 'id' => site.id, '_csrf_token' => 'abcd' }} + upload 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') last_response.body.must_match /successfully uploaded/i - File.exists?(site.files_path('test.jpg')).must_equal true + File.exists?(@site.files_path('test.jpg')).must_equal true queue_args = PurgeCacheWorker.jobs.first['args'].first - queue_args['site'].must_equal site.username + queue_args['site'].must_equal @site.username queue_args['path'].must_equal '/test.jpg' ThumbnailWorker.jobs.length.must_equal 1 ThumbnailWorker.drain Site::THUMBNAIL_RESOLUTIONS.each do |resolution| - File.exists?(site.thumbnail_path('test.jpg', resolution)).must_equal true + File.exists?(@site.thumbnail_path('test.jpg', resolution)).must_equal true end - site.site_changed.must_equal false + @site.site_changed.must_equal false + end + + it 'overwrites existing file with new file' do + upload 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') + last_response.body.must_match /successfully uploaded/i + digest = @site.reload.site_files.first.sha1_hash + upload 'files[]' => Rack::Test::UploadedFile.new('./tests/files/img/test.jpg', 'image/jpeg') + last_response.body.must_match /successfully uploaded/i + @site.reload.changed_count.must_equal 2 + @site.site_files.count.must_equal 1 + digest.wont_equal @site.reload.site_files.first.sha1_hash end it 'works with directory path' do - site = Fabricate :site - ThumbnailWorker.jobs.clear - PurgeCacheWorker.jobs.clear - post '/site_files/upload', { + upload( 'dir' => 'derpie/derptest', - 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg'), - 'csrf_token' => 'abcd' - }, {'rack.session' => { 'id' => site.id, '_csrf_token' => 'abcd' }} + 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') + ) last_response.body.must_match /successfully uploaded/i - File.exists?(site.files_path('derpie/derptest/test.jpg')).must_equal true + File.exists?(@site.files_path('derpie/derptest/test.jpg')).must_equal true PurgeCacheWorker.jobs.length.must_equal 1 queue_args = PurgeCacheWorker.jobs.first['args'].first @@ -66,11 +92,28 @@ describe 'site_files' do ThumbnailWorker.drain Site::THUMBNAIL_RESOLUTIONS.each do |resolution| - File.exists?(site.thumbnail_path('derpie/derptest/test.jpg', resolution)).must_equal true - site.thumbnail_url('derpie/derptest/test.jpg', resolution).must_equal( - File.join "#{Site::THUMBNAILS_URL_ROOT}", site.username, "/derpie/derptest/test.jpg.#{resolution}.jpg" + File.exists?(@site.thumbnail_path('derpie/derptest/test.jpg', resolution)).must_equal true + @site.thumbnail_url('derpie/derptest/test.jpg', resolution).must_equal( + File.join "#{Site::THUMBNAILS_URL_ROOT}", @site.username, "/derpie/derptest/test.jpg.#{resolution}.jpg" ) end end + + it 'does not store new file if hash matches' do + upload( + 'dir' => 'derpie/derptest', + 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') + ) + @site.reload.changed_count.must_equal 1 + + upload( + 'dir' => 'derpie/derptest', + 'files[]' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') + ) + @site.reload.changed_count.must_equal 1 + + upload 'files[]' => Rack::Test::UploadedFile.new('./tests/files/index.html', 'text/html') + @site.reload.changed_count.must_equal 2 + end end end \ No newline at end of file