137 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| require 'spec_helper'
 | |
| 
 | |
| describe Gitlab::Sanitizers::Exif do
 | |
|   let(:sanitizer) { described_class.new }
 | |
| 
 | |
|   describe '#batch_clean' do
 | |
|     context 'with image uploads' do
 | |
|       set(:upload1) { create(:upload, :with_file, :issuable_upload) }
 | |
|       set(:upload2) { create(:upload, :with_file, :personal_snippet_upload) }
 | |
|       set(:upload3) { create(:upload, :with_file, created_at: 3.days.ago) }
 | |
| 
 | |
|       it 'processes all uploads if range ID is not set' do
 | |
|         expect(sanitizer).to receive(:clean).exactly(3).times
 | |
| 
 | |
|         sanitizer.batch_clean
 | |
|       end
 | |
| 
 | |
|       it 'processes only uploads in the selected range' do
 | |
|         expect(sanitizer).to receive(:clean).once
 | |
| 
 | |
|         sanitizer.batch_clean(start_id: upload1.id, stop_id: upload1.id)
 | |
|       end
 | |
| 
 | |
|       it 'processes only uploads for the selected uploader' do
 | |
|         expect(sanitizer).to receive(:clean).once
 | |
| 
 | |
|         sanitizer.batch_clean(uploader: 'PersonalFileUploader')
 | |
|       end
 | |
| 
 | |
|       it 'processes only uploads created since specified date' do
 | |
|         expect(sanitizer).to receive(:clean).exactly(2).times
 | |
| 
 | |
|         sanitizer.batch_clean(since: 2.days.ago)
 | |
|       end
 | |
| 
 | |
|       it 'pauses if sleep_time is set' do
 | |
|         expect(sanitizer).to receive(:sleep).exactly(3).times.with(1.second)
 | |
|         expect(sanitizer).to receive(:clean).exactly(3).times
 | |
| 
 | |
|         sanitizer.batch_clean(sleep_time: 1)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     it 'filters only jpg/tiff images' do
 | |
|       create(:upload, path: 'filename.jpg')
 | |
|       create(:upload, path: 'filename.jpeg')
 | |
|       create(:upload, path: 'filename.JPG')
 | |
|       create(:upload, path: 'filename.tiff')
 | |
|       create(:upload, path: 'filename.TIFF')
 | |
|       create(:upload, path: 'filename.png')
 | |
|       create(:upload, path: 'filename.txt')
 | |
| 
 | |
|       expect(sanitizer).to receive(:clean).exactly(5).times
 | |
|       sanitizer.batch_clean
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#clean' do
 | |
|     let(:uploader) { create(:upload, :with_file, :issuable_upload).retrieve_uploader }
 | |
| 
 | |
|     context "no dry run" do
 | |
|       it "removes exif from the image" do
 | |
|         uploader.store!(fixture_file_upload('spec/fixtures/rails_sample.jpg'))
 | |
| 
 | |
|         original_upload = uploader.upload
 | |
|         expected_args = ["exiftool", "-all=", "-tagsFromFile", "@", *Gitlab::Sanitizers::Exif::EXCLUDE_PARAMS, "--IPTC:all", "--XMP-iptcExt:all", kind_of(String)]
 | |
| 
 | |
|         expect(sanitizer).to receive(:extra_tags).and_return(["", 0])
 | |
|         expect(sanitizer).to receive(:exec_remove_exif!).once.and_call_original
 | |
|         expect(uploader).to receive(:store!).and_call_original
 | |
|         expect(Gitlab::Popen).to receive(:popen).with(expected_args) do |args|
 | |
|           File.write("#{args.last}_original", "foo") if args.last.start_with?(Dir.tmpdir)
 | |
| 
 | |
|           [expected_args, 0]
 | |
|         end
 | |
| 
 | |
|         sanitizer.clean(uploader, dry_run: false)
 | |
| 
 | |
|         expect(uploader.upload.id).not_to eq(original_upload.id)
 | |
|         expect(uploader.upload.path).to eq(original_upload.path)
 | |
|       end
 | |
| 
 | |
|       it "ignores image without exif" do
 | |
|         expected_args = ["exiftool", "-all", "-j", "-sort", "--IPTC:all", "--XMP-iptcExt:all", kind_of(String)]
 | |
| 
 | |
|         expect(Gitlab::Popen).to receive(:popen).with(expected_args).and_return(["[{}]", 0])
 | |
|         expect(sanitizer).not_to receive(:exec_remove_exif!)
 | |
|         expect(uploader).not_to receive(:store!)
 | |
| 
 | |
|         sanitizer.clean(uploader, dry_run: false)
 | |
|       end
 | |
| 
 | |
|       it "raises an error if the exiftool fails with an error" do
 | |
|         expect(Gitlab::Popen).to receive(:popen).and_return(["error", 1])
 | |
| 
 | |
|         expect { sanitizer.clean(uploader, dry_run: false) }.to raise_exception(RuntimeError, "failed to get exif tags: error")
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context "dry run" do
 | |
|       it "doesn't change the image" do
 | |
|         expect(sanitizer).to receive(:extra_tags).and_return({ 'foo' => 'bar' })
 | |
|         expect(sanitizer).not_to receive(:exec_remove_exif!)
 | |
|         expect(uploader).not_to receive(:store!)
 | |
| 
 | |
|         sanitizer.clean(uploader, dry_run: true)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe "#extra_tags" do
 | |
|     it "returns a list of keys for exif file" do
 | |
|       tags = '[{
 | |
|                 "DigitalSourceType": "some source",
 | |
|                 "ImageHeight": 654
 | |
|               }]'
 | |
| 
 | |
|       expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0])
 | |
| 
 | |
|       expect(sanitizer.extra_tags('filename')).not_to be_empty
 | |
|     end
 | |
| 
 | |
|     it "returns an empty list for file with only whitelisted and ignored tags" do
 | |
|       tags = '[{
 | |
|                 "ImageHeight": 654,
 | |
|                 "Megapixels": 0.641
 | |
|               }]'
 | |
| 
 | |
|       expect(Gitlab::Popen).to receive(:popen).and_return([tags, 0])
 | |
| 
 | |
|       expect(sanitizer.extra_tags('some file')).to be_empty
 | |
|     end
 | |
|   end
 | |
| end
 |