172 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
require 'spec_helper'
 | 
						|
 | 
						|
RSpec.describe 'Git LFS File Locking API', feature_category: :source_code_management do
 | 
						|
  include LfsHttpHelpers
 | 
						|
  include WorkhorseHelpers
 | 
						|
 | 
						|
  let_it_be(:project) { create(:project) }
 | 
						|
  let_it_be(:maintainer) { create(:user) }
 | 
						|
  let_it_be(:developer) { create(:user) }
 | 
						|
  let_it_be(:reporter) { create(:user) }
 | 
						|
  let_it_be(:guest) { create(:user) }
 | 
						|
  let_it_be(:path) { 'README.md' }
 | 
						|
 | 
						|
  let(:user) { developer }
 | 
						|
  let(:headers) do
 | 
						|
    {
 | 
						|
      'Authorization' => authorize_user
 | 
						|
    }.compact
 | 
						|
  end
 | 
						|
 | 
						|
  shared_examples 'unauthorized request' do
 | 
						|
    context 'when user does not have download permission' do
 | 
						|
      let(:user) { guest }
 | 
						|
 | 
						|
      it 'returns a 404 response' do
 | 
						|
        post_lfs_json url, body, headers
 | 
						|
 | 
						|
        expect(response).to have_gitlab_http_status(:not_found)
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'when user does not have upload permission' do
 | 
						|
      let(:user) { reporter }
 | 
						|
 | 
						|
      it 'returns a 403 response' do
 | 
						|
        post_lfs_json url, body, headers
 | 
						|
 | 
						|
        expect(response).to have_gitlab_http_status(:forbidden)
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  before do
 | 
						|
    allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
 | 
						|
 | 
						|
    project.add_maintainer(maintainer)
 | 
						|
    project.add_developer(developer)
 | 
						|
    project.add_reporter(reporter)
 | 
						|
    project.add_guest(guest)
 | 
						|
  end
 | 
						|
 | 
						|
  describe 'Create File Lock endpoint' do
 | 
						|
    let(:url) { "#{project.http_url_to_repo}/info/lfs/locks" }
 | 
						|
    let(:body) { { path: path } }
 | 
						|
 | 
						|
    include_examples 'unauthorized request'
 | 
						|
 | 
						|
    context 'with an existent lock' do
 | 
						|
      before do
 | 
						|
        lock_file('README.md', developer)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'return an error message' do
 | 
						|
        post_lfs_json url, body, headers
 | 
						|
 | 
						|
        expect(response).to have_gitlab_http_status(:conflict)
 | 
						|
 | 
						|
        expect(json_response.keys).to match_array(%w[lock message documentation_url])
 | 
						|
        expect(json_response['message']).to match(/already locked/)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns the existen lock' do
 | 
						|
        post_lfs_json url, body, headers
 | 
						|
 | 
						|
        expect(json_response['lock']['path']).to eq('README.md')
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    context 'without an existent lock' do
 | 
						|
      it 'creates the lock' do
 | 
						|
        post_lfs_json url, body, headers
 | 
						|
 | 
						|
        expect(response).to have_gitlab_http_status(:created)
 | 
						|
 | 
						|
        expect(json_response['lock'].keys).to match_array(%w[id path locked_at owner])
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe 'Listing File Locks endpoint' do
 | 
						|
    let(:url) { "#{project.http_url_to_repo}/info/lfs/locks" }
 | 
						|
 | 
						|
    include_examples 'unauthorized request'
 | 
						|
 | 
						|
    it 'returns the list of locked files' do
 | 
						|
      lock_file('README.md', developer)
 | 
						|
      lock_file('README', developer)
 | 
						|
 | 
						|
      do_get url, nil, headers
 | 
						|
 | 
						|
      expect(response).to have_gitlab_http_status(:ok)
 | 
						|
 | 
						|
      expect(json_response['locks'].size).to eq(2)
 | 
						|
      expect(json_response['locks'].first.keys).to match_array(%w[id path locked_at owner])
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe 'List File Locks for verification endpoint' do
 | 
						|
    let(:url) { "#{project.http_url_to_repo}/info/lfs/locks/verify" }
 | 
						|
 | 
						|
    include_examples 'unauthorized request'
 | 
						|
 | 
						|
    it 'returns the list of locked files grouped by owner' do
 | 
						|
      lock_file('README.md', maintainer)
 | 
						|
      lock_file('README', developer)
 | 
						|
 | 
						|
      post_lfs_json url, nil, headers
 | 
						|
 | 
						|
      expect(response).to have_gitlab_http_status(:ok)
 | 
						|
 | 
						|
      expect(json_response['ours'].size).to eq(1)
 | 
						|
      expect(json_response['ours'].first['path']).to eq('README')
 | 
						|
      expect(json_response['theirs'].size).to eq(1)
 | 
						|
      expect(json_response['theirs'].first['path']).to eq('README.md')
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe 'Delete File Lock endpoint' do
 | 
						|
    let!(:lock) { lock_file('README.md', developer) }
 | 
						|
    let(:url) { "#{project.http_url_to_repo}/info/lfs/locks/#{lock[:id]}/unlock" }
 | 
						|
 | 
						|
    include_examples 'unauthorized request'
 | 
						|
 | 
						|
    context 'with an existent lock' do
 | 
						|
      it 'deletes the lock' do
 | 
						|
        post_lfs_json url, nil, headers
 | 
						|
 | 
						|
        expect(response).to have_gitlab_http_status(:ok)
 | 
						|
      end
 | 
						|
 | 
						|
      it 'returns the deleted lock' do
 | 
						|
        post_lfs_json url, nil, headers
 | 
						|
 | 
						|
        expect(json_response['lock'].keys).to match_array(%w[id path locked_at owner])
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when a maintainer uses force' do
 | 
						|
        let(:user) { maintainer }
 | 
						|
 | 
						|
        it 'deletes the lock' do
 | 
						|
          project.add_maintainer(maintainer)
 | 
						|
          post_lfs_json url, { force: true }, headers
 | 
						|
 | 
						|
          expect(response).to have_gitlab_http_status(:ok)
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def lock_file(path, author)
 | 
						|
    result = Lfs::LockFileService.new(project, author, { path: path }).execute
 | 
						|
 | 
						|
    result[:lock]
 | 
						|
  end
 | 
						|
 | 
						|
  def do_get(url, params = nil, headers = nil)
 | 
						|
    get(url, params: (params || {}), headers: (headers || {}).merge('Content-Type' => LfsRequest::CONTENT_TYPE))
 | 
						|
  end
 | 
						|
end
 |