diff options
Diffstat (limited to 'spec/controllers/repositories/lfs_storage_controller_spec.rb')
-rw-r--r-- | spec/controllers/repositories/lfs_storage_controller_spec.rb | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/spec/controllers/repositories/lfs_storage_controller_spec.rb b/spec/controllers/repositories/lfs_storage_controller_spec.rb new file mode 100644 index 00000000000..0201e73728f --- /dev/null +++ b/spec/controllers/repositories/lfs_storage_controller_spec.rb @@ -0,0 +1,160 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Repositories::LfsStorageController do + using RSpec::Parameterized::TableSyntax + include GitHttpHelpers + + let_it_be(:project) { create(:project, :public) } + let_it_be(:user) { create(:user) } + let_it_be(:pat) { create(:personal_access_token, user: user, scopes: ['write_repository']) } + + let(:lfs_enabled) { true } + + before do + stub_config(lfs: { enabled: lfs_enabled }) + end + + describe 'PUT #upload_finalize' do + let(:headers) { workhorse_internal_api_request_header } + let(:extra_headers) { {} } + let(:uploaded_file) { temp_file } + + let(:params) do + { + namespace_id: project.namespace.path, + repository_id: "#{project.path}.git", + oid: '6b9765d3888aaec789e8c309eb05b05c3a87895d6ad70d2264bd7270fff665ac', + size: '6725030' + } + end + + before do + request.headers.merge!(extra_headers) + request.headers.merge!(headers) + + if uploaded_file + allow_next_instance_of(ActionController::Parameters) do |params| + allow(params).to receive(:[]).and_call_original + allow(params).to receive(:[]).with(:file).and_return(uploaded_file) + end + end + end + + after do + FileUtils.rm_r(temp_file) if temp_file + end + + subject do + put :upload_finalize, params: params + end + + context 'with lfs enabled' do + context 'with unauthorized roles' do + where(:user_role, :expected_status) do + :guest | :forbidden + :anonymous | :unauthorized + end + + with_them do + let(:extra_headers) do + if user_role == :anonymous + {} + else + { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user.username, pat.token) } + end + end + + before do + project.send("add_#{user_role}", user) unless user_role == :anonymous + end + + it_behaves_like 'returning response status', params[:expected_status] + end + end + + context 'with at least developer role' do + let(:extra_headers) { { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user.username, pat.token) } } + + before do + project.add_developer(user) + end + + it 'creates the objects' do + expect { subject } + .to change { LfsObject.count }.by(1) + .and change { LfsObjectsProject.count }.by(1) + + expect(response).to have_gitlab_http_status(:ok) + end + + context 'without the workhorse header' do + let(:headers) { {} } + + it { expect { subject }.to raise_error(JWT::DecodeError) } + end + + context 'without file' do + let(:uploaded_file) { nil } + + it_behaves_like 'returning response status', :unprocessable_entity + end + + context 'with an invalid file' do + let(:uploaded_file) { 'test' } + + it_behaves_like 'returning response status', :unprocessable_entity + end + + context 'when an expected error' do + [ + ActiveRecord::RecordInvalid, + UploadedFile::InvalidPathError, + ObjectStorage::RemoteStoreError + ].each do |exception_class| + context "#{exception_class} raised" do + it 'renders lfs forbidden' do + expect(LfsObjectsProject).to receive(:safe_find_or_create_by!).and_raise(exception_class) + + subject + + expect(response).to have_gitlab_http_status(:forbidden) + expect(json_response['documentation_url']).to be_present + expect(json_response['message']).to eq('Access forbidden. Check your access level.') + end + end + end + end + + context 'when file is not stored' do + it 'renders unprocessable entity' do + expect(controller).to receive(:store_file!).and_return(nil) + + subject + + expect(response).to have_gitlab_http_status(:unprocessable_entity) + expect(response.body).to eq('Unprocessable entity') + end + end + end + end + + context 'with lfs disabled' do + let(:lfs_enabled) { false } + let(:extra_headers) { { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user.username, pat.token) } } + + it_behaves_like 'returning response status', :not_implemented + end + + def temp_file + upload_path = LfsObjectUploader.workhorse_local_upload_path + file_path = "#{upload_path}/lfs" + + FileUtils.mkdir_p(upload_path) + File.write(file_path, 'test') + + UploadedFile.new(file_path, filename: File.basename(file_path)) + end + end +end |