diff options
Diffstat (limited to 'spec/lib/uploaded_file_spec.rb')
-rw-r--r-- | spec/lib/uploaded_file_spec.rb | 433 |
1 files changed, 275 insertions, 158 deletions
diff --git a/spec/lib/uploaded_file_spec.rb b/spec/lib/uploaded_file_spec.rb index 5ff46193b4f..8425e1dbd46 100644 --- a/spec/lib/uploaded_file_spec.rb +++ b/spec/lib/uploaded_file_spec.rb @@ -14,226 +14,343 @@ RSpec.describe UploadedFile do FileUtils.rm_f(temp_file) end - describe ".from_params" do - let(:upload_path) { nil } - let(:file_path_override) { nil } + context 'from_params functions' do + RSpec.shared_examples 'using the file path' do |filename:, content_type:, sha256:, path_suffix:| + it { is_expected.not_to be_nil } + + it 'sets properly the attributes' do + expect(subject.original_filename).to eq(filename) + expect(subject.content_type).to eq(content_type) + expect(subject.sha256).to eq(sha256) + expect(subject.remote_id).to be_nil + expect(subject.path).to end_with(path_suffix) + end + + it 'handles a blank path' do + params['file.path'] = '' + + # Not a real file, so can't determine size itself + params['file.size'] = 1.byte - after do - FileUtils.rm_r(upload_path) if upload_path + expect { described_class.from_params(params, :file, upload_path) } + .not_to raise_error + end end - subject do - described_class.from_params(params, :file, upload_path, file_path_override) + RSpec.shared_examples 'using the remote id' do |filename:, content_type:, sha256:, size:, remote_id:| + it { is_expected.not_to be_nil } + + it 'sets properly the attributes' do + expect(subject.original_filename).to eq(filename) + expect(subject.content_type).to eq('application/octet-stream') + expect(subject.sha256).to eq('sha256') + expect(subject.path).to be_nil + expect(subject.size).to eq(123456) + expect(subject.remote_id).to eq('1234567890') + end end - context 'when valid file is specified' do - context 'only local path is specified' do - let(:params) do - { 'file.path' => temp_file.path } - end + describe '.from_params_without_field' do + let(:upload_path) { nil } - it { is_expected.not_to be_nil } + after do + FileUtils.rm_r(upload_path) if upload_path + end - it "generates filename from path" do - expect(subject.original_filename).to eq(::File.basename(temp_file.path)) - end + subject do + described_class.from_params_without_field(params, [upload_path, Dir.tmpdir]) end - context 'all parameters are specified' do - RSpec.shared_context 'filepath override' do - let(:temp_file_override) { Tempfile.new(%w[override override], temp_dir) } - let(:file_path_override) { temp_file_override.path } + context 'when valid file is specified' do + context 'only local path is specified' do + let(:params) { { 'path' => temp_file.path } } - before do - FileUtils.touch(temp_file_override) - end + it { is_expected.not_to be_nil } - after do - FileUtils.rm_f(temp_file_override) + it 'generates filename from path' do + expect(subject.original_filename).to eq(::File.basename(temp_file.path)) end end - RSpec.shared_examples 'using the file path' do |filename:, content_type:, sha256:, path_suffix:| - it 'sets properly the attributes' do - expect(subject.original_filename).to eq(filename) - expect(subject.content_type).to eq(content_type) - expect(subject.sha256).to eq(sha256) - expect(subject.remote_id).to be_nil - expect(subject.path).to end_with(path_suffix) + context 'all parameters are specified' do + context 'with a filepath' do + let(:params) do + { 'path' => temp_file.path, + 'name' => 'dir/my file&.txt', + 'type' => 'my/type', + 'sha256' => 'sha256' } + end + + it_behaves_like 'using the file path', + filename: 'my_file_.txt', + content_type: 'my/type', + sha256: 'sha256', + path_suffix: 'test' end - it 'handles a blank path' do - params['file.path'] = '' - - # Not a real file, so can't determine size itself - params['file.size'] = 1.byte + context 'with a remote id' do + let(:params) do + { + 'name' => 'dir/my file&.txt', + 'sha256' => 'sha256', + 'remote_url' => 'http://localhost/file', + 'remote_id' => '1234567890', + 'etag' => 'etag1234567890', + 'size' => '123456' + } + end + + it_behaves_like 'using the remote id', + filename: 'my_file_.txt', + content_type: 'application/octet-stream', + sha256: 'sha256', + size: 123456, + remote_id: '1234567890' + end - expect { described_class.from_params(params, :file, upload_path) } - .not_to raise_error + context 'with a path and a remote id' do + let(:params) do + { + 'path' => temp_file.path, + 'name' => 'dir/my file&.txt', + 'sha256' => 'sha256', + 'remote_url' => 'http://localhost/file', + 'remote_id' => '1234567890', + 'etag' => 'etag1234567890', + 'size' => '123456' + } + end + + it_behaves_like 'using the remote id', + filename: 'my_file_.txt', + content_type: 'application/octet-stream', + sha256: 'sha256', + size: 123456, + remote_id: '1234567890' end end + end - RSpec.shared_examples 'using the remote id' do |filename:, content_type:, sha256:, size:, remote_id:| - it 'sets properly the attributes' do - expect(subject.original_filename).to eq(filename) - expect(subject.content_type).to eq('application/octet-stream') - expect(subject.sha256).to eq('sha256') - expect(subject.path).to be_nil - expect(subject.size).to eq(123456) - expect(subject.remote_id).to eq('1234567890') - end + context 'when no params are specified' do + let(:params) { {} } + + it 'does not return an object' do + is_expected.to be_nil end + end - context 'with a filepath' do - let(:params) do - { 'file.path' => temp_file.path, - 'file.name' => 'dir/my file&.txt', - 'file.type' => 'my/type', - 'file.sha256' => 'sha256' } - end + context 'when verifying allowed paths' do + let(:params) { { 'path' => temp_file.path } } + + context 'when file is stored in system temporary folder' do + let(:temp_dir) { Dir.tmpdir } it { is_expected.not_to be_nil } + end + + context 'when file is stored in user provided upload path' do + let(:upload_path) { Dir.mktmpdir } + let(:temp_dir) { upload_path } - it_behaves_like 'using the file path', - filename: 'my_file_.txt', - content_type: 'my/type', - sha256: 'sha256', - path_suffix: 'test' + it { is_expected.not_to be_nil } end - context 'with a filepath override' do - include_context 'filepath override' + context 'when file is stored outside of user provided upload path' do + let!(:generated_dir) { Dir.mktmpdir } + let!(:temp_dir) { Dir.mktmpdir } - let(:params) do - { 'file.path' => temp_file.path, - 'file.name' => 'dir/my file&.txt', - 'file.type' => 'my/type', - 'file.sha256' => 'sha256' } + before do + # We overwrite default temporary path + allow(Dir).to receive(:tmpdir).and_return(generated_dir) end - it { is_expected.not_to be_nil } - - it_behaves_like 'using the file path', - filename: 'my_file_.txt', - content_type: 'my/type', - sha256: 'sha256', - path_suffix: 'override' + it 'raises an error' do + expect { subject }.to raise_error(UploadedFile::InvalidPathError, /insecure path used/) + end end + end + end - context 'with a remote id' do - let(:params) do - { - 'file.name' => 'dir/my file&.txt', - 'file.sha256' => 'sha256', - 'file.remote_url' => 'http://localhost/file', - 'file.remote_id' => '1234567890', - 'file.etag' => 'etag1234567890', - 'file.size' => '123456' - } - end + describe '.from_params' do + let(:upload_path) { nil } + let(:file_path_override) { nil } - it { is_expected.not_to be_nil } + after do + FileUtils.rm_r(upload_path) if upload_path + end + + subject do + described_class.from_params(params, :file, [upload_path, Dir.tmpdir], file_path_override) + end - it_behaves_like 'using the remote id', - filename: 'my_file_.txt', - content_type: 'application/octet-stream', - sha256: 'sha256', - size: 123456, - remote_id: '1234567890' + RSpec.shared_context 'filepath override' do + let(:temp_file_override) { Tempfile.new(%w[override override], temp_dir) } + let(:file_path_override) { temp_file_override.path } + + before do + FileUtils.touch(temp_file_override) end - context 'with a path and a remote id' do + after do + FileUtils.rm_f(temp_file_override) + end + end + + context 'when valid file is specified' do + context 'only local path is specified' do let(:params) do - { - 'file.path' => temp_file.path, - 'file.name' => 'dir/my file&.txt', - 'file.sha256' => 'sha256', - 'file.remote_url' => 'http://localhost/file', - 'file.remote_id' => '1234567890', - 'file.etag' => 'etag1234567890', - 'file.size' => '123456' - } + { 'file.path' => temp_file.path } end it { is_expected.not_to be_nil } - it_behaves_like 'using the remote id', - filename: 'my_file_.txt', - content_type: 'application/octet-stream', - sha256: 'sha256', - size: 123456, - remote_id: '1234567890' + it "generates filename from path" do + expect(subject.original_filename).to eq(::File.basename(temp_file.path)) + end end - context 'with a path override and a remote id' do - include_context 'filepath override' + context 'all parameters are specified' do + context 'with a filepath' do + let(:params) do + { 'file.path' => temp_file.path, + 'file.name' => 'dir/my file&.txt', + 'file.type' => 'my/type', + 'file.sha256' => 'sha256' } + end + + it_behaves_like 'using the file path', + filename: 'my_file_.txt', + content_type: 'my/type', + sha256: 'sha256', + path_suffix: 'test' + end - let(:params) do - { - 'file.name' => 'dir/my file&.txt', - 'file.sha256' => 'sha256', - 'file.remote_url' => 'http://localhost/file', - 'file.remote_id' => '1234567890', - 'file.etag' => 'etag1234567890', - 'file.size' => '123456' - } + context 'with a filepath override' do + include_context 'filepath override' + + let(:params) do + { 'file.path' => temp_file.path, + 'file.name' => 'dir/my file&.txt', + 'file.type' => 'my/type', + 'file.sha256' => 'sha256' } + end + + it_behaves_like 'using the file path', + filename: 'my_file_.txt', + content_type: 'my/type', + sha256: 'sha256', + path_suffix: 'override' end - it { is_expected.not_to be_nil } + context 'with a remote id' do + let(:params) do + { + 'file.name' => 'dir/my file&.txt', + 'file.sha256' => 'sha256', + 'file.remote_url' => 'http://localhost/file', + 'file.remote_id' => '1234567890', + 'file.etag' => 'etag1234567890', + 'file.size' => '123456' + } + end + + it_behaves_like 'using the remote id', + filename: 'my_file_.txt', + content_type: 'application/octet-stream', + sha256: 'sha256', + size: 123456, + remote_id: '1234567890' + end - it_behaves_like 'using the remote id', - filename: 'my_file_.txt', - content_type: 'application/octet-stream', - sha256: 'sha256', - size: 123456, - remote_id: '1234567890' + context 'with a path and a remote id' do + let(:params) do + { + 'file.path' => temp_file.path, + 'file.name' => 'dir/my file&.txt', + 'file.sha256' => 'sha256', + 'file.remote_url' => 'http://localhost/file', + 'file.remote_id' => '1234567890', + 'file.etag' => 'etag1234567890', + 'file.size' => '123456' + } + end + + it_behaves_like 'using the remote id', + filename: 'my_file_.txt', + content_type: 'application/octet-stream', + sha256: 'sha256', + size: 123456, + remote_id: '1234567890' + end + + context 'with a path override and a remote id' do + include_context 'filepath override' + + let(:params) do + { + 'file.name' => 'dir/my file&.txt', + 'file.sha256' => 'sha256', + 'file.remote_url' => 'http://localhost/file', + 'file.remote_id' => '1234567890', + 'file.etag' => 'etag1234567890', + 'file.size' => '123456' + } + end + + it_behaves_like 'using the remote id', + filename: 'my_file_.txt', + content_type: 'application/octet-stream', + sha256: 'sha256', + size: 123456, + remote_id: '1234567890' + end end end - end - context 'when no params are specified' do - let(:params) do - {} - end + context 'when no params are specified' do + let(:params) do + {} + end - it "does not return an object" do - is_expected.to be_nil + it "does not return an object" do + is_expected.to be_nil + end end - end - context 'when verifying allowed paths' do - let(:params) do - { 'file.path' => temp_file.path } - end + context 'when verifying allowed paths' do + let(:params) do + { 'file.path' => temp_file.path } + end - context 'when file is stored in system temporary folder' do - let(:temp_dir) { Dir.tmpdir } + context 'when file is stored in system temporary folder' do + let(:temp_dir) { Dir.tmpdir } - it "succeeds" do - is_expected.not_to be_nil + it "succeeds" do + is_expected.not_to be_nil + end end - end - context 'when file is stored in user provided upload path' do - let(:upload_path) { Dir.mktmpdir } - let(:temp_dir) { upload_path } + context 'when file is stored in user provided upload path' do + let(:upload_path) { Dir.mktmpdir } + let(:temp_dir) { upload_path } - it "succeeds" do - is_expected.not_to be_nil + it "succeeds" do + is_expected.not_to be_nil + end end - end - context 'when file is stored outside of user provided upload path' do - let!(:generated_dir) { Dir.mktmpdir } - let!(:temp_dir) { Dir.mktmpdir } + context 'when file is stored outside of user provided upload path' do + let!(:generated_dir) { Dir.mktmpdir } + let!(:temp_dir) { Dir.mktmpdir } - before do - # We overwrite default temporary path - allow(Dir).to receive(:tmpdir).and_return(generated_dir) - end + before do + # We overwrite default temporary path + allow(Dir).to receive(:tmpdir).and_return(generated_dir) + end - it "raises an error" do - expect { subject }.to raise_error(UploadedFile::InvalidPathError, /insecure path used/) + it "raises an error" do + expect { subject }.to raise_error(UploadedFile::InvalidPathError, /insecure path used/) + end end end end |