summaryrefslogtreecommitdiff
path: root/spec/controllers/repositories/lfs_storage_controller_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/controllers/repositories/lfs_storage_controller_spec.rb')
-rw-r--r--spec/controllers/repositories/lfs_storage_controller_spec.rb160
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