1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ::Import::GitlabProjects::FileAcquisitionStrategies::RemoteFileS3, :aggregate_failures, feature_category: :importers do
let(:region_name) { 'region_name' }
let(:bucket_name) { 'bucket_name' }
let(:file_key) { 'file_key' }
let(:access_key_id) { 'access_key_id' }
let(:secret_access_key) { 'secret_access_key' }
let(:file_exists) { true }
let(:content_type) { 'application/x-tar' }
let(:content_length) { 2.gigabytes }
let(:presigned_url) { 'https://external.file.path/file.tar.gz?PRESIGNED=true&TOKEN=some-token' }
let(:s3_double) do
instance_double(
Aws::S3::Object,
exists?: file_exists,
content_type: content_type,
content_length: content_length,
presigned_url: presigned_url
)
end
let(:params) do
{
region: region_name,
bucket_name: bucket_name,
file_key: file_key,
access_key_id: access_key_id,
secret_access_key: secret_access_key
}
end
subject { described_class.new(params: params) }
before do
# Avoid network requests
expect(Aws::S3::Client).to receive(:new).and_return(double)
expect(Aws::S3::Object).to receive(:new).and_return(s3_double)
end
describe 'validation' do
it { expect(subject).to be_valid }
%i[region bucket_name file_key access_key_id secret_access_key].each do |key|
context "#{key} validation" do
before do
params[key] = nil
end
it "validates presence of #{key}" do
expect(subject).not_to be_valid
expect(subject.errors.full_messages)
.to include("#{key.to_s.humanize} can't be blank")
end
end
end
context 'content-length validation' do
let(:content_length) { 11.gigabytes }
it 'validates the remote content-length' do
expect(subject).not_to be_valid
expect(subject.errors.full_messages)
.to include('Content length is too big (should be at most 10 GB)')
end
end
context 'content-type validation' do
let(:content_type) { 'unknown' }
it 'validates the remote content-type' do
expect(subject).not_to be_valid
expect(subject.errors.full_messages)
.to include("Content type 'unknown' not allowed. (Allowed: application/gzip, application/x-tar, application/x-gzip)")
end
end
context 'file_url validation' do
let(:presigned_url) { 'ftp://invalid.url/file.tar.gz' }
it 'validates the file_url scheme' do
expect(subject).not_to be_valid
expect(subject.errors.full_messages)
.to include("File url is blocked: Only allowed schemes are https")
end
context 'when localhost urls are not allowed' do
let(:presigned_url) { 'https://localhost:3000/file.tar.gz' }
it 'validates the file_url' do
stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
expect(subject).not_to be_valid
expect(subject.errors.full_messages)
.to include("File url is blocked: Requests to localhost are not allowed")
end
end
end
context 'when the remote file does not exist' do
it 'foo' do
expect(s3_double).to receive(:exists?).and_return(false)
expect(subject).not_to be_valid
expect(subject.errors.full_messages)
.to include("File not found 'file_key' in 'bucket_name'")
end
end
context 'when it fails to build the s3 object' do
it 'foo' do
expect(s3_double).to receive(:exists?).and_raise(StandardError, "some error")
expect(subject).not_to be_valid
expect(subject.errors.full_messages)
.to include("Failed to open 'file_key' in 'bucket_name': some error")
end
end
end
describe '#project_params' do
it 'returns import_export_upload in the params' do
subject = described_class.new(params: { remote_import_url: presigned_url })
expect(subject.project_params).to match(
import_export_upload: an_instance_of(::ImportExportUpload)
)
expect(subject.project_params[:import_export_upload]).to have_attributes(
remote_import_url: presigned_url
)
end
end
end
|