2019-12-21 20:55:43 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
RSpec.shared_examples 'LFS http 200 response' do
|
2019-12-21 20:55:43 +05:30
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:response_code) { :ok }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
RSpec.shared_examples 'LFS http 200 blob response' do
|
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
|
|
|
let(:response_code) { :ok }
|
|
|
|
let(:content_type) { Repositories::LfsApiController::LFS_TRANSFER_CONTENT_TYPE }
|
|
|
|
let(:response_headers) { { 'X-Sendfile' => lfs_object.file.path } }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
RSpec.shared_examples 'LFS http 200 workhorse response' do
|
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
|
|
|
let(:response_code) { :ok }
|
|
|
|
let(:content_type) { Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE }
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
RSpec.shared_examples 'LFS http 401 response' do
|
2019-12-21 20:55:43 +05:30
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:response_code) { :unauthorized }
|
|
|
|
let(:content_type) { 'text/plain' }
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
RSpec.shared_examples 'LFS http 403 response' do
|
2019-12-21 20:55:43 +05:30
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:response_code) { :forbidden }
|
2019-12-21 20:55:43 +05:30
|
|
|
let(:message) { 'Access forbidden. Check your access level.' }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
RSpec.shared_examples 'LFS http 501 response' do
|
2019-12-21 20:55:43 +05:30
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:response_code) { :not_implemented }
|
2019-12-21 20:55:43 +05:30
|
|
|
let(:message) { 'Git LFS is not enabled on this GitLab server, contact your admin.' }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
RSpec.shared_examples 'LFS http 404 response' do
|
2019-12-21 20:55:43 +05:30
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:response_code) { :not_found }
|
2019-12-21 20:55:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-13 15:44:24 +05:30
|
|
|
RSpec.shared_examples 'LFS http expected response code and message' do
|
2019-12-21 20:55:43 +05:30
|
|
|
let(:response_code) { }
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:response_headers) { {} }
|
|
|
|
let(:content_type) { LfsRequest::CONTENT_TYPE }
|
|
|
|
let(:message) {}
|
2019-12-21 20:55:43 +05:30
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
specify do
|
2019-12-21 20:55:43 +05:30
|
|
|
expect(response).to have_gitlab_http_status(response_code)
|
2021-01-29 00:20:46 +05:30
|
|
|
expect(response.headers.to_hash).to include(response_headers)
|
|
|
|
expect(response.media_type).to match(content_type)
|
2019-12-21 20:55:43 +05:30
|
|
|
expect(json_response['message']).to eq(message) if message
|
|
|
|
end
|
|
|
|
end
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
RSpec.shared_examples 'LFS http requests' do
|
|
|
|
include LfsHttpHelpers
|
|
|
|
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:lfs_enabled) { true }
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:authorize_guest) {}
|
|
|
|
let(:authorize_download) {}
|
|
|
|
let(:authorize_upload) {}
|
|
|
|
|
|
|
|
let(:lfs_object) { create(:lfs_object, :with_file) }
|
|
|
|
let(:sample_oid) { lfs_object.oid }
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:sample_size) { lfs_object.size }
|
|
|
|
let(:sample_object) { { 'oid' => sample_oid, 'size' => sample_size } }
|
|
|
|
let(:non_existing_object_oid) { '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897' }
|
|
|
|
let(:non_existing_object_size) { 1575078 }
|
|
|
|
let(:non_existing_object) { { 'oid' => non_existing_object_oid, 'size' => non_existing_object_size } }
|
|
|
|
let(:multiple_objects) { [sample_object, non_existing_object] }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
let(:authorization) { authorize_user }
|
|
|
|
let(:headers) do
|
|
|
|
{
|
|
|
|
'Authorization' => authorization,
|
|
|
|
'X-Sendfile-Type' => 'X-Sendfile'
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:request_download) do
|
|
|
|
get objects_url(container, sample_oid), params: {}, headers: headers
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:request_upload) do
|
|
|
|
post_lfs_json batch_url(container), upload_body(multiple_objects), headers
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
2021-02-22 17:27:13 +05:30
|
|
|
stub_lfs_setting(enabled: lfs_enabled)
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context 'when LFS is disabled globally' do
|
2021-02-22 17:27:13 +05:30
|
|
|
let(:lfs_enabled) { false }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
describe 'download request' do
|
|
|
|
before do
|
|
|
|
request_download
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 501 response'
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'upload request' do
|
|
|
|
before do
|
|
|
|
request_upload
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 501 response'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'unauthenticated' do
|
|
|
|
let(:headers) { {} }
|
|
|
|
|
|
|
|
describe 'download request' do
|
|
|
|
before do
|
|
|
|
request_download
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 401 response'
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'upload request' do
|
|
|
|
before do
|
|
|
|
request_upload
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 401 response'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without access' do
|
|
|
|
describe 'download request' do
|
|
|
|
before do
|
|
|
|
request_download
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 404 response'
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'upload request' do
|
|
|
|
before do
|
|
|
|
request_upload
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 404 response'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with guest access' do
|
|
|
|
before do
|
|
|
|
authorize_guest
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'download request' do
|
|
|
|
before do
|
|
|
|
request_download
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 404 response'
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'upload request' do
|
|
|
|
before do
|
|
|
|
request_upload
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 404 response'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with download permission' do
|
|
|
|
before do
|
|
|
|
authorize_download
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'download request' do
|
|
|
|
before do
|
|
|
|
request_download
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 200 blob response'
|
|
|
|
|
|
|
|
context 'when container does not exist' do
|
|
|
|
def objects_url(*args)
|
|
|
|
super.sub(container.full_path, 'missing/path')
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 404 response'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'upload request' do
|
|
|
|
before do
|
|
|
|
request_upload
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 403 response'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with upload permission' do
|
|
|
|
before do
|
|
|
|
authorize_upload
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'upload request' do
|
|
|
|
before do
|
|
|
|
request_upload
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http 200 response'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'deprecated API' do
|
|
|
|
shared_examples 'deprecated request' do
|
|
|
|
before do
|
|
|
|
request
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'LFS http expected response code and message' do
|
|
|
|
let(:response_code) { 501 }
|
|
|
|
let(:message) { 'Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.' }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when fetching LFS object using deprecated API' do
|
|
|
|
subject(:request) do
|
|
|
|
get deprecated_objects_url(container, sample_oid), params: {}, headers: headers
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'deprecated request'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when handling LFS request using deprecated API' do
|
|
|
|
subject(:request) do
|
|
|
|
post_lfs_json deprecated_objects_url(container), nil, headers
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'deprecated request'
|
|
|
|
end
|
|
|
|
|
|
|
|
def deprecated_objects_url(container, oid = nil)
|
|
|
|
File.join(["#{container.http_url_to_repo}/info/lfs/objects/", oid].compact)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|