2019-11-07 22:06:48 -05:00
# frozen_string_literal: true
2014-09-24 04:37:30 -04:00
require 'spec_helper'
2020-06-24 14:09:03 -04:00
RSpec . describe Gitlab :: GitAccess do
2018-05-08 09:07:55 -04:00
include TermsHelper
2018-10-01 23:21:46 -04:00
include GitHelpers
2020-12-17 13:10:14 -05:00
include AdminModeHelper
2018-05-08 09:07:55 -04:00
let ( :user ) { create ( :user ) }
2017-08-18 14:46:28 -04:00
2015-03-24 09:10:55 -04:00
let ( :actor ) { user }
2017-08-18 14:46:28 -04:00
let ( :project ) { create ( :project , :repository ) }
2020-12-01 07:09:17 -05:00
let ( :repository_path ) { " #{ project . full_path } .git " }
2017-05-16 12:02:52 -04:00
let ( :protocol ) { 'ssh' }
2017-08-18 14:46:28 -04:00
let ( :authentication_abilities ) { % i [ read_project download_code push_code ] }
2017-06-15 20:03:54 -04:00
let ( :redirected_path ) { nil }
2018-03-27 11:35:27 -04:00
let ( :auth_result_type ) { nil }
2018-12-20 11:25:48 -05:00
let ( :changes ) { Gitlab :: GitAccess :: ANY }
2018-02-13 14:33:13 -05:00
let ( :push_access_check ) { access . check ( 'git-receive-pack' , changes ) }
let ( :pull_access_check ) { access . check ( 'git-upload-pack' , changes ) }
2014-09-24 04:37:30 -04:00
2020-07-21 14:09:45 -04:00
let ( :access_class ) do
Class . new ( described_class ) do
def push_ability
:push_code
end
def download_ability
:download_code
end
end
end
2016-06-22 20:16:24 -04:00
describe '#check with single protocols allowed' do
def disable_protocol ( protocol )
2017-05-19 15:58:45 -04:00
allow ( Gitlab :: ProtocolAccess ) . to receive ( :allowed? ) . with ( protocol ) . and_return ( false )
2016-06-22 20:16:24 -04:00
end
context 'ssh disabled' do
before do
disable_protocol ( 'ssh' )
end
2017-08-18 14:46:28 -04:00
it 'blocks ssh git push and pull' do
aggregate_failures do
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( 'Git access over SSH is not allowed' )
expect { pull_access_check } . to raise_forbidden ( 'Git access over SSH is not allowed' )
2017-08-18 14:46:28 -04:00
end
2016-06-22 20:16:24 -04:00
end
end
context 'http disabled' do
2017-05-16 12:08:23 -04:00
let ( :protocol ) { 'http' }
2016-06-22 20:16:24 -04:00
before do
disable_protocol ( 'http' )
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2016-06-22 20:16:24 -04:00
end
2017-08-18 14:46:28 -04:00
it 'blocks http push and pull' do
aggregate_failures do
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( 'Git access over HTTP is not allowed' )
expect { pull_access_check } . to raise_forbidden ( 'Git access over HTTP is not allowed' )
2017-08-18 14:46:28 -04:00
end
2016-06-22 20:16:24 -04:00
end
2018-03-27 11:35:27 -04:00
context 'when request is made from CI' do
let ( :auth_result_type ) { :build }
it " doesn't block http pull " do
aggregate_failures do
2020-07-21 14:09:45 -04:00
expect { pull_access_check } . not_to raise_error
2018-03-27 11:35:27 -04:00
end
end
context 'when legacy CI credentials are used' do
let ( :auth_result_type ) { :ci }
it " doesn't block http pull " do
aggregate_failures do
2020-07-21 14:09:45 -04:00
expect { pull_access_check } . not_to raise_error
2018-03-27 11:35:27 -04:00
end
end
end
end
2016-06-22 20:16:24 -04:00
end
end
2017-05-16 15:58:46 -04:00
describe '#check_project_accessibility!' do
context 'when the project exists' do
context 'when actor exists' do
context 'when actor is a DeployKey' do
2018-01-05 10:23:44 -05:00
let ( :deploy_key ) { create ( :deploy_key , user : user ) }
2017-05-16 15:58:46 -04:00
let ( :actor ) { deploy_key }
context 'when the DeployKey has access to the project' do
2017-06-14 14:18:56 -04:00
before do
2018-01-05 10:23:44 -05:00
deploy_key . deploy_keys_projects . create ( project : project , can_push : true )
2017-06-14 14:18:56 -04:00
end
2017-05-16 15:58:46 -04:00
2017-08-18 14:46:28 -04:00
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
2017-05-16 15:58:46 -04:00
end
end
context 'when the Deploykey does not have access to the project' do
2017-08-18 14:46:28 -04:00
it 'blocks push and pull with "not found"' do
aggregate_failures do
2017-08-18 15:06:41 -04:00
expect { push_access_check } . to raise_not_found
expect { pull_access_check } . to raise_not_found
2017-08-18 14:46:28 -04:00
end
2017-05-16 15:58:46 -04:00
end
end
end
context 'when actor is a User' do
context 'when the User can read the project' do
2017-06-14 14:18:56 -04:00
before do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2017-06-14 14:18:56 -04:00
end
2017-05-16 15:58:46 -04:00
2017-08-18 14:46:28 -04:00
it 'allows push and pull access' do
aggregate_failures do
expect { pull_access_check } . not_to raise_error
expect { push_access_check } . not_to raise_error
end
2017-05-16 15:58:46 -04:00
end
end
context 'when the User cannot read the project' do
2017-08-18 14:46:28 -04:00
it 'blocks push and pull with "not found"' do
aggregate_failures do
2017-08-18 15:06:41 -04:00
expect { push_access_check } . to raise_not_found
expect { pull_access_check } . to raise_not_found
2017-08-18 14:46:28 -04:00
end
2017-05-16 15:58:46 -04:00
end
end
end
# For backwards compatibility
context 'when actor is :ci' do
let ( :actor ) { :ci }
let ( :authentication_abilities ) { build_authentication_abilities }
it 'allows pull access' do
2017-05-19 15:58:45 -04:00
expect { pull_access_check } . not_to raise_error
2017-05-16 15:58:46 -04:00
end
it 'does not block pushes with "not found"' do
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :auth_upload ] )
2017-05-16 15:58:46 -04:00
end
end
2018-03-29 18:56:35 -04:00
context 'when actor is DeployToken' do
2018-04-05 23:02:13 -04:00
let ( :actor ) { create ( :deploy_token , projects : [ project ] ) }
2018-03-29 18:56:35 -04:00
2018-04-05 13:22:34 -04:00
context 'when DeployToken is active and belongs to project' do
2018-03-29 18:56:35 -04:00
it 'allows pull access' do
expect { pull_access_check } . not_to raise_error
end
2018-04-05 23:02:13 -04:00
it 'blocks the push' do
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :upload ] )
2018-04-05 23:02:13 -04:00
end
2018-03-29 18:56:35 -04:00
end
context 'when DeployToken does not belong to project' do
2018-04-05 23:02:13 -04:00
let ( :another_project ) { create ( :project ) }
let ( :actor ) { create ( :deploy_token , projects : [ another_project ] ) }
2018-03-29 18:56:35 -04:00
it 'blocks pull access' do
expect { pull_access_check } . to raise_not_found
end
2018-04-05 23:02:13 -04:00
it 'blocks the push' do
expect { push_access_check } . to raise_not_found
end
2018-03-29 18:56:35 -04:00
end
end
2017-05-16 15:58:46 -04:00
end
context 'when actor is nil' do
let ( :actor ) { nil }
context 'when guests can read the project' do
let ( :project ) { create ( :project , :repository , :public ) }
it 'allows pull access' do
2017-05-19 15:58:45 -04:00
expect { pull_access_check } . not_to raise_error
2017-05-16 15:58:46 -04:00
end
it 'does not block pushes with "not found"' do
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :upload ] )
2017-05-16 15:58:46 -04:00
end
end
context 'when guests cannot read the project' do
it 'blocks pulls with "not found"' do
2017-08-18 15:06:41 -04:00
expect { pull_access_check } . to raise_not_found
2017-05-16 15:58:46 -04:00
end
it 'blocks pushes with "not found"' do
2017-08-18 15:06:41 -04:00
expect { push_access_check } . to raise_not_found
2017-05-16 15:58:46 -04:00
end
end
end
end
2020-12-01 07:09:17 -05:00
context 'when the project does not exist' do
2017-05-16 15:58:46 -04:00
let ( :project ) { nil }
2020-12-01 07:09:17 -05:00
let ( :repository_path ) { " #{ user . namespace . path } /new-project.git " }
2017-05-16 15:58:46 -04:00
2020-06-09 17:08:21 -04:00
it 'blocks push and pull with "not found"' do
aggregate_failures do
2018-01-22 13:10:56 -05:00
expect { pull_access_check } . to raise_not_found
2020-06-09 17:08:21 -04:00
expect { push_access_check } . to raise_not_found
2018-01-22 13:10:56 -05:00
end
end
2017-05-16 15:58:46 -04:00
end
end
2017-08-21 06:30:03 -04:00
shared_examples '#check with a key that is not valid' do
before do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2017-08-21 06:30:03 -04:00
end
context 'key is too small' do
before do
2017-08-25 09:08:48 -04:00
stub_application_setting ( rsa_key_restriction : 4096 )
2017-08-21 06:30:03 -04:00
end
2017-10-03 04:35:01 -04:00
it 'does not allow keys which are too small' , :aggregate_failures do
2017-08-28 16:33:35 -04:00
expect ( actor ) . not_to be_valid
2020-02-26 13:09:24 -05:00
expect { pull_access_check } . to raise_forbidden ( 'Your SSH key must be at least 4096 bits.' )
expect { push_access_check } . to raise_forbidden ( 'Your SSH key must be at least 4096 bits.' )
2017-08-21 06:30:03 -04:00
end
end
context 'key type is not allowed' do
before do
2017-08-25 09:08:48 -04:00
stub_application_setting ( rsa_key_restriction : ApplicationSetting :: FORBIDDEN_KEY_VALUE )
2017-08-21 06:30:03 -04:00
end
2017-10-03 04:35:01 -04:00
it 'does not allow keys which are too small' , :aggregate_failures do
2017-08-28 16:33:35 -04:00
expect ( actor ) . not_to be_valid
2020-02-26 13:09:24 -05:00
expect { pull_access_check } . to raise_forbidden ( / Your SSH key type is forbidden / )
expect { push_access_check } . to raise_forbidden ( / Your SSH key type is forbidden / )
2017-08-21 06:30:03 -04:00
end
end
end
it_behaves_like '#check with a key that is not valid' do
let ( :actor ) { build ( :rsa_key_2048 , user : user ) }
end
it_behaves_like '#check with a key that is not valid' do
let ( :actor ) { build ( :rsa_deploy_key_2048 , user : user ) }
end
2017-12-08 12:42:43 -05:00
shared_examples 'check_project_moved' do
2018-03-05 07:02:36 -05:00
it 'enqueues a redirected message for pushing' do
2017-12-08 12:42:43 -05:00
push_access_check
2018-01-26 09:28:08 -05:00
expect ( Gitlab :: Checks :: ProjectMoved . fetch_message ( user . id , project . id ) ) . not_to be_nil
2017-12-08 12:42:43 -05:00
end
2018-03-05 07:02:36 -05:00
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
end
2017-12-08 12:42:43 -05:00
end
2018-03-05 07:02:36 -05:00
describe '#add_project_moved_message!' , :clean_gitlab_redis_shared_state do
2017-06-15 20:03:54 -04:00
before do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2017-06-15 20:03:54 -04:00
end
context 'when a redirect was not followed to find the project' do
2017-08-18 14:46:28 -04:00
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
2017-06-15 20:03:54 -04:00
end
end
2018-03-05 07:02:36 -05:00
context 'with a redirect and ssh protocol' do
2017-12-08 12:42:43 -05:00
let ( :redirected_path ) { 'some/other-path' }
it_behaves_like 'check_project_moved'
end
2018-03-05 07:02:36 -05:00
context 'with a redirect and http protocol' do
2017-12-08 12:42:43 -05:00
let ( :redirected_path ) { 'some/other-path' }
let ( :protocol ) { 'http' }
it_behaves_like 'check_project_moved'
end
2017-06-15 20:03:54 -04:00
end
2018-02-02 10:27:30 -05:00
describe '#check_authentication_abilities!' do
before do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2018-02-02 10:27:30 -05:00
end
context 'when download' do
let ( :authentication_abilities ) { [ ] }
it 'raises unauthorized with download error' do
2020-02-26 13:09:24 -05:00
expect { pull_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :auth_download ] )
2018-02-02 10:27:30 -05:00
end
context 'when authentication abilities include download code' do
let ( :authentication_abilities ) { [ :download_code ] }
it 'does not raise any errors' do
expect { pull_access_check } . not_to raise_error
end
end
context 'when authentication abilities include build download code' do
let ( :authentication_abilities ) { [ :build_download_code ] }
it 'does not raise any errors' do
expect { pull_access_check } . not_to raise_error
end
end
end
context 'when upload' do
let ( :authentication_abilities ) { [ ] }
it 'raises unauthorized with push error' do
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :auth_upload ] )
2018-02-02 10:27:30 -05:00
end
context 'when authentication abilities include push code' do
let ( :authentication_abilities ) { [ :push_code ] }
it 'does not raise any errors' do
expect { push_access_check } . not_to raise_error
end
end
end
end
2017-05-16 15:58:46 -04:00
describe '#check_command_disabled!' do
2017-06-14 14:18:56 -04:00
before do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2017-06-14 14:18:56 -04:00
end
2017-05-16 12:02:52 -04:00
context 'over http' do
let ( :protocol ) { 'http' }
context 'when the git-upload-pack command is disabled in config' do
before do
allow ( Gitlab . config . gitlab_shell ) . to receive ( :upload_pack ) . and_return ( false )
end
context 'when calling git-upload-pack' do
2020-02-26 13:09:24 -05:00
it { expect { pull_access_check } . to raise_forbidden ( 'Pulling over HTTP is not allowed.' ) }
2017-05-16 12:02:52 -04:00
end
context 'when calling git-receive-pack' do
2017-05-19 15:58:45 -04:00
it { expect { push_access_check } . not_to raise_error }
2017-05-16 12:02:52 -04:00
end
end
context 'when the git-receive-pack command is disabled in config' do
before do
allow ( Gitlab . config . gitlab_shell ) . to receive ( :receive_pack ) . and_return ( false )
end
context 'when calling git-receive-pack' do
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( 'Pushing over HTTP is not allowed.' ) }
2017-05-16 12:02:52 -04:00
end
context 'when calling git-upload-pack' do
2017-05-19 15:58:45 -04:00
it { expect { pull_access_check } . not_to raise_error }
2017-05-16 12:02:52 -04:00
end
end
end
end
2020-12-10 01:09:47 -05:00
describe '#check_otp_session!' do
let_it_be ( :user ) { create ( :user , :two_factor_via_otp ) }
let_it_be ( :key ) { create ( :key , user : user ) }
let_it_be ( :actor ) { key }
before do
project . add_developer ( user )
stub_feature_flags ( two_factor_for_cli : true )
end
context 'with an OTP session' , :clean_gitlab_redis_shared_state do
before do
Gitlab :: Redis :: SharedState . with do | redis |
redis . set ( " #{ Gitlab :: Auth :: Otp :: SessionEnforcer :: OTP_SESSIONS_NAMESPACE } : #{ key . id } " , true )
end
end
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
end
end
context 'without OTP session' do
it 'does not allow push or pull access' do
user = 'jane.doe'
host = 'fridge.ssh'
port = 42
stub_config (
gitlab_shell : {
ssh_user : user ,
ssh_host : host ,
ssh_port : port
}
)
error_message = " OTP verification is required to access the repository. \n \n " \
" Use: ssh #{ user } @ #{ host } -p #{ port } 2fa_verify "
aggregate_failures do
expect { push_access_check } . to raise_forbidden ( error_message )
expect { pull_access_check } . to raise_forbidden ( error_message )
end
end
context 'when protocol is HTTP' do
let ( :protocol ) { 'http' }
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
end
end
context 'when actor is not an SSH key' do
let ( :deploy_key ) { create ( :deploy_key , user : user ) }
let ( :actor ) { deploy_key }
before do
deploy_key . deploy_keys_projects . create ( project : project , can_push : true )
end
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
end
end
context 'when 2FA is not enabled for the user' do
let ( :user ) { create ( :user ) }
let ( :actor ) { create ( :key , user : user ) }
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
end
end
context 'when feature flag is disabled' do
before do
stub_feature_flags ( two_factor_for_cli : false )
end
it 'allows push and pull access' do
aggregate_failures do
expect { push_access_check } . not_to raise_error
expect { pull_access_check } . not_to raise_error
end
end
end
end
end
2018-02-02 10:27:30 -05:00
describe '#check_db_accessibility!' do
context 'when in a read-only GitLab instance' do
before do
create ( :protected_branch , name : 'feature' , project : project )
allow ( Gitlab :: Database ) . to receive ( :read_only? ) { true }
end
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :cannot_push_to_read_only ] ) }
2018-02-02 10:27:30 -05:00
end
end
2016-12-20 08:19:07 -05:00
describe '#check_download_access!' do
2018-07-11 10:36:08 -04:00
it 'allows maintainers to pull' do
project . add_maintainer ( user )
2014-09-24 04:37:30 -04:00
2017-08-18 14:46:28 -04:00
expect { pull_access_check } . not_to raise_error
2014-09-24 04:37:30 -04:00
end
2017-08-18 14:46:28 -04:00
it 'disallows guests to pull' do
project . add_guest ( user )
2014-09-24 04:37:30 -04:00
2020-02-26 13:09:24 -05:00
expect { pull_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :download ] )
2014-09-24 04:37:30 -04:00
end
2017-08-18 14:46:28 -04:00
it 'disallows blocked users to pull' do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2017-08-18 14:46:28 -04:00
user . block
2014-09-24 04:37:30 -04:00
2020-02-26 13:09:24 -05:00
expect { pull_access_check } . to raise_forbidden ( 'Your account has been blocked.' )
2014-09-24 04:37:30 -04:00
end
2020-10-06 08:08:38 -04:00
it 'disallows users that are blocked pending approval to pull' do
project . add_maintainer ( user )
user . block_pending_approval
expect { pull_access_check } . to raise_forbidden ( 'Your account is pending approval from your administrator and hence blocked.' )
end
2019-10-09 20:06:44 -04:00
it 'disallows deactivated users to pull' do
project . add_maintainer ( user )
user . deactivate!
2020-02-26 13:09:24 -05:00
expect { pull_access_check } . to raise_forbidden ( " Your account has been deactivated by your administrator. Please log back in from a web browser to reactivate your account at #{ Gitlab . config . gitlab . url } " )
2019-10-09 20:06:44 -04:00
end
2018-02-22 13:51:00 -05:00
context 'when the project repository does not exist' do
2020-10-05 11:08:56 -04:00
before do
2018-02-22 13:51:00 -05:00
project . add_guest ( user )
2020-10-05 11:08:56 -04:00
allow ( project . repository ) . to receive ( :exists? ) . and_return ( false )
end
2018-02-22 13:51:00 -05:00
2020-10-05 11:08:56 -04:00
it 'returns not found' do
2018-02-22 13:51:00 -05:00
expect { pull_access_check } . to raise_error ( Gitlab :: GitAccess :: NotFoundError , 'A repository for this project does not exist yet.' )
end
end
2016-11-11 08:53:43 -05:00
describe 'without access to project' do
2014-09-24 04:37:30 -04:00
context 'pull code' do
2017-08-18 15:06:41 -04:00
it { expect { pull_access_check } . to raise_not_found }
2014-09-24 04:37:30 -04:00
end
2016-11-02 17:50:44 -04:00
context 'when project is public' do
2017-01-24 18:42:12 -05:00
let ( :public_project ) { create ( :project , :public , :repository ) }
2020-12-01 07:09:17 -05:00
let ( :repository_path ) { " #{ public_project . full_path } .git " }
let ( :access ) { access_class . new ( nil , public_project , 'web' , authentication_abilities : [ :download_code ] , repository_path : repository_path ) }
2016-11-02 17:50:44 -04:00
context 'when repository is enabled' do
it 'give access to download code' do
2017-05-19 15:58:45 -04:00
expect { pull_access_check } . not_to raise_error
2016-11-02 17:50:44 -04:00
end
end
context 'when repository is disabled' do
it 'does not give access to download code' do
public_project . project_feature . update_attribute ( :repository_access_level , ProjectFeature :: DISABLED )
2020-02-26 13:09:24 -05:00
expect { pull_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :download ] )
2016-11-02 17:50:44 -04:00
end
end
end
2014-09-24 04:37:30 -04:00
end
2014-12-01 09:25:10 -05:00
describe 'deploy key permissions' do
2016-11-16 09:07:04 -05:00
let ( :key ) { create ( :deploy_key , user : user ) }
2015-03-24 09:10:55 -04:00
let ( :actor ) { key }
2014-12-01 09:25:10 -05:00
context 'pull code' do
2020-09-02 11:10:54 -04:00
context 'when project is public' do
let ( :project ) { create ( :project , :public , :repository , * options ) }
context 'when deploy key exists in the project' do
before do
key . projects << project
end
context 'when the repository is public' do
let ( :options ) { % i [ repository_enabled ] }
it { expect { pull_access_check } . not_to raise_error }
end
context 'when the repository is private' do
let ( :options ) { % i [ repository_private ] }
it { expect { pull_access_check } . not_to raise_error }
end
context 'when the repository is disabled' do
let ( :options ) { % i [ repository_disabled ] }
it { expect { pull_access_check } . to raise_error ( 'You are not allowed to download code from this project.' ) }
end
2017-06-14 14:18:56 -04:00
end
2014-12-01 09:25:10 -05:00
2020-09-02 11:10:54 -04:00
context 'when deploy key does not exist in the project' do
context 'when the repository is public' do
let ( :options ) { % i [ repository_enabled ] }
it { expect { pull_access_check } . not_to raise_error }
end
context 'when the repository is private' do
let ( :options ) { % i [ repository_private ] }
it { expect { pull_access_check } . to raise_error ( 'You are not allowed to download code from this project.' ) }
end
context 'when the repository is disabled' do
let ( :options ) { % i [ repository_disabled ] }
it { expect { pull_access_check } . to raise_error ( 'You are not allowed to download code from this project.' ) }
end
end
2016-07-18 06:36:44 -04:00
end
2020-09-02 11:10:54 -04:00
context 'when project is internal' do
let ( :project ) { create ( :project , :internal , :repository , * options ) }
context 'when deploy key exists in the project' do
before do
key . projects << project
end
context 'when the repository is public' do
let ( :options ) { % i [ repository_enabled ] }
it { expect { pull_access_check } . not_to raise_error }
end
context 'when the repository is private' do
let ( :options ) { % i [ repository_private ] }
it { expect { pull_access_check } . not_to raise_error }
end
context 'when the repository is disabled' do
let ( :options ) { % i [ repository_disabled ] }
it { expect { pull_access_check } . to raise_error ( 'You are not allowed to download code from this project.' ) }
end
end
context 'when deploy key does not exist in the project' do
context 'when the repository is public' do
let ( :options ) { % i [ repository_enabled ] }
it { expect { pull_access_check } . to raise_error ( 'The project you were looking for could not be found.' ) }
end
context 'when the repository is private' do
let ( :options ) { % i [ repository_private ] }
it { expect { pull_access_check } . to raise_error ( 'The project you were looking for could not be found.' ) }
end
context 'when the repository is disabled' do
let ( :options ) { % i [ repository_disabled ] }
2016-07-18 06:36:44 -04:00
2020-09-02 11:10:54 -04:00
it { expect { pull_access_check } . to raise_error ( 'The project you were looking for could not be found.' ) }
end
2016-07-18 06:36:44 -04:00
end
2020-09-02 11:10:54 -04:00
end
context 'when project is private' do
let ( :project ) { create ( :project , :private , :repository , * options ) }
context 'when deploy key exists in the project' do
before do
key . projects << project
end
context 'when the repository is private' do
let ( :options ) { % i [ repository_private ] }
2016-07-18 06:36:44 -04:00
2020-09-02 11:10:54 -04:00
it { expect { pull_access_check } . not_to raise_error }
end
context 'when the repository is disabled' do
let ( :options ) { % i [ repository_disabled ] }
2018-04-05 23:02:13 -04:00
2020-09-02 11:10:54 -04:00
it { expect { pull_access_check } . to raise_error ( 'You are not allowed to download code from this project.' ) }
end
2018-04-05 23:02:13 -04:00
end
2020-09-02 11:10:54 -04:00
context 'when deploy key does not exist in the project' do
context 'when the repository is private' do
let ( :options ) { % i [ repository_private ] }
2018-04-05 23:02:13 -04:00
2020-09-02 11:10:54 -04:00
it { expect { pull_access_check } . to raise_error ( 'The project you were looking for could not be found.' ) }
end
context 'when the repository is disabled' do
let ( :options ) { % i [ repository_disabled ] }
it { expect { pull_access_check } . to raise_error ( 'The project you were looking for could not be found.' ) }
end
2018-04-05 23:02:13 -04:00
end
end
end
end
describe 'deploy token permissions' do
let ( :deploy_token ) { create ( :deploy_token ) }
let ( :actor ) { deploy_token }
context 'pull code' do
context 'when project is authorized' do
before do
deploy_token . projects << project
end
it { expect { pull_access_check } . not_to raise_error }
end
context 'when unauthorized' do
context 'from public project' do
let ( :project ) { create ( :project , :public , :repository ) }
it { expect { pull_access_check } . not_to raise_error }
end
context 'from internal project' do
let ( :project ) { create ( :project , :internal , :repository ) }
2016-07-18 06:36:44 -04:00
2017-08-18 15:06:41 -04:00
it { expect { pull_access_check } . to raise_not_found }
2016-07-18 06:36:44 -04:00
end
context 'from private project' do
2017-01-24 18:42:12 -05:00
let ( :project ) { create ( :project , :private , :repository ) }
2016-07-18 06:36:44 -04:00
2017-08-18 15:06:41 -04:00
it { expect { pull_access_check } . to raise_not_found }
2016-07-18 06:36:44 -04:00
end
end
2014-12-01 09:25:10 -05:00
end
end
2016-09-15 05:57:09 -04:00
2016-09-16 03:59:10 -04:00
describe 'build authentication_abilities permissions' do
let ( :authentication_abilities ) { build_authentication_abilities }
2016-09-15 05:57:09 -04:00
2016-10-17 11:23:51 -04:00
describe 'owner' do
2017-01-24 18:42:12 -05:00
let ( :project ) { create ( :project , :repository , namespace : user . namespace ) }
2016-10-17 11:23:51 -04:00
context 'pull code' do
2017-05-19 15:58:45 -04:00
it { expect { pull_access_check } . not_to raise_error }
2016-10-17 11:23:51 -04:00
end
end
2016-09-15 05:57:09 -04:00
describe 'reporter user' do
2017-06-14 14:18:56 -04:00
before do
2017-12-22 03:18:28 -05:00
project . add_reporter ( user )
2017-06-14 14:18:56 -04:00
end
2016-09-15 05:57:09 -04:00
context 'pull code' do
2017-05-19 15:58:45 -04:00
it { expect { pull_access_check } . not_to raise_error }
2016-09-15 05:57:09 -04:00
end
end
describe 'admin user' do
let ( :user ) { create ( :admin ) }
2020-12-17 13:10:14 -05:00
context 'when admin mode enabled' , :enable_admin_mode do
context 'when member of the project' do
before do
project . add_reporter ( user )
end
context 'pull code' do
it { expect { pull_access_check } . not_to raise_error }
end
2017-06-14 14:18:56 -04:00
end
2016-09-15 05:57:09 -04:00
2020-12-17 13:10:14 -05:00
context 'when is not member of the project' do
context 'pull code' do
it { expect { pull_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :download ] ) }
end
2016-09-15 05:57:09 -04:00
end
end
2020-12-17 13:10:14 -05:00
context 'when admin mode disabled' do
context 'when member of the project' do
before do
project . add_reporter ( user )
end
context 'pull code' do
it { expect { pull_access_check } . not_to raise_error }
end
end
context 'when is not member of the project' do
context 'pull code' do
it { expect { pull_access_check } . to raise_not_found }
end
2016-09-15 05:57:09 -04:00
end
end
end
2017-05-16 15:58:46 -04:00
describe 'generic CI (build without a user)' do
let ( :actor ) { :ci }
context 'pull code' do
2017-05-19 15:58:45 -04:00
it { expect { pull_access_check } . not_to raise_error }
2017-05-16 15:58:46 -04:00
end
end
2016-09-15 05:57:09 -04:00
end
2014-09-24 04:37:30 -04:00
end
2018-02-13 14:33:13 -05:00
describe 'check LFS integrity' do
let ( :changes ) { [ '6f6d7e7ed 570e7b2ab refs/heads/master' , '6f6d7e7ed 570e7b2ab refs/heads/feature' ] }
before do
project . add_developer ( user )
end
2018-12-28 05:44:25 -05:00
context 'when LFS is not enabled' do
it 'does not run LFSIntegrity check' do
expect ( Gitlab :: Checks :: LfsIntegrity ) . not_to receive ( :new )
2018-02-13 14:33:13 -05:00
2018-12-28 05:44:25 -05:00
push_access_check
end
end
context 'when LFS is enabled' do
it 'checks LFS integrity only for first change' do
allow ( project ) . to receive ( :lfs_enabled? ) . and_return ( true )
2019-12-06 19:07:51 -05:00
expect_next_instance_of ( Gitlab :: Checks :: LfsIntegrity ) do | instance |
2020-02-06 16:08:48 -05:00
expect ( instance ) . to receive ( :objects_missing? ) . once
2019-12-06 19:07:51 -05:00
end
2018-12-28 05:44:25 -05:00
push_access_check
end
2018-02-13 14:33:13 -05:00
end
end
2016-12-20 08:19:07 -05:00
describe '#check_push_access!' do
2018-07-06 16:56:41 -04:00
let ( :unprotected_branch ) { 'unprotected_branch' }
2017-06-14 14:18:56 -04:00
before do
merge_into_protected_branch
end
2014-09-24 04:37:30 -04:00
2016-07-18 04:16:56 -04:00
let ( :changes ) do
2018-12-20 11:40:56 -05:00
{ any : Gitlab :: GitAccess :: ANY ,
push_new_branch : " #{ Gitlab :: Git :: BLANK_SHA } 570e7b2ab refs/heads/wow " ,
2014-09-24 05:04:40 -04:00
push_master : '6f6d7e7ed 570e7b2ab refs/heads/master' ,
push_protected_branch : '6f6d7e7ed 570e7b2ab refs/heads/feature' ,
2014-11-03 14:02:12 -05:00
push_remove_protected_branch : " 570e7b2ab #{ Gitlab :: Git :: BLANK_SHA } " \
'refs/heads/feature' ,
2014-09-24 05:04:40 -04:00
push_tag : '6f6d7e7ed 570e7b2ab refs/tags/v1.0.0' ,
2014-11-03 14:02:12 -05:00
push_new_tag : " #{ Gitlab :: Git :: BLANK_SHA } 570e7b2ab refs/tags/v7.8.9 " ,
2016-07-18 04:16:56 -04:00
push_all : [ '6f6d7e7ed 570e7b2ab refs/heads/master' , '6f6d7e7ed 570e7b2ab refs/heads/feature' ] ,
merge_into_protected_branch : " 0b4bc9a #{ merge_into_protected_branch } refs/heads/feature " }
2014-09-24 05:04:40 -04:00
end
2014-09-24 04:37:30 -04:00
2016-07-18 04:16:56 -04:00
def merge_into_protected_branch
@protected_branch_merge_commit || = begin
2018-10-01 23:21:46 -04:00
project . repository . add_branch ( user , unprotected_branch , 'feature' )
rugged = rugged_repo ( project . repository )
target_branch = rugged . rev_parse ( 'feature' )
source_branch = project . repository . create_file (
user ,
'filename' ,
'This is the file content' ,
message : 'This is a good commit message' ,
branch_name : unprotected_branch )
author = { email : " email@example.com " , time : Time . now , name : " Example Git User " }
merge_index = rugged . merge_commits ( target_branch , source_branch )
Rugged :: Commit . create ( rugged , author : author , committer : author , message : " commit message " , parents : [ target_branch , source_branch ] , tree : merge_index . write_tree ( rugged ) )
2014-12-26 05:41:04 -05:00
end
end
2016-06-23 05:28:14 -04:00
2016-07-18 04:16:56 -04:00
def self . run_permission_checks ( permissions_matrix )
2017-08-18 14:46:28 -04:00
permissions_matrix . each_pair do | role , matrix |
# Run through the entire matrix for this role in one test to avoid
# repeated setup.
#
# Expectations are given a custom failure message proc so that it's
# easier to identify which check(s) failed.
it " has the correct permissions for #{ role } s " do
2020-12-17 13:10:14 -05:00
if [ :admin_with_admin_mode , :admin_without_admin_mode ] . include? ( role )
2017-08-18 14:46:28 -04:00
user . update_attribute ( :admin , true )
2020-12-17 13:10:14 -05:00
enable_admin_mode! ( user ) if role == :admin_with_admin_mode
2019-01-25 07:11:36 -05:00
project . add_guest ( user )
2017-08-18 14:46:28 -04:00
else
2017-12-22 03:18:28 -05:00
project . add_role ( user , role )
2017-02-23 10:09:11 -05:00
end
2019-01-25 07:11:36 -05:00
protected_branch . save
2017-08-18 14:46:28 -04:00
aggregate_failures do
2018-02-02 10:27:30 -05:00
matrix . each do | action , allowed |
2018-07-06 16:56:41 -04:00
check = - > { push_changes ( changes [ action ] ) }
2018-02-02 10:27:30 -05:00
if allowed
expect ( & check ) . not_to raise_error ,
- > { " expected #{ action } to be allowed " }
else
2020-02-26 13:09:24 -05:00
expect ( & check ) . to raise_error ( Gitlab :: GitAccess :: ForbiddenError ) ,
2018-02-02 10:27:30 -05:00
- > { " expected #{ action } to be disallowed " }
2016-10-18 12:28:57 -04:00
end
2016-06-23 05:28:14 -04:00
end
end
end
end
end
2016-07-18 04:16:56 -04:00
permissions_matrix = {
2020-12-17 13:10:14 -05:00
admin_with_admin_mode : {
2018-12-20 11:40:56 -05:00
any : true ,
2016-07-14 02:16:13 -04:00
push_new_branch : true ,
push_master : true ,
push_protected_branch : true ,
push_remove_protected_branch : false ,
push_tag : true ,
push_new_tag : true ,
push_all : true ,
merge_into_protected_branch : true
} ,
2020-12-17 13:10:14 -05:00
admin_without_admin_mode : {
any : false ,
push_new_branch : false ,
push_master : false ,
push_protected_branch : false ,
push_remove_protected_branch : false ,
push_tag : false ,
push_new_tag : false ,
push_all : false ,
merge_into_protected_branch : false
} ,
2018-07-11 10:36:08 -04:00
maintainer : {
2018-12-20 11:40:56 -05:00
any : true ,
2016-07-18 04:16:56 -04:00
push_new_branch : true ,
push_master : true ,
push_protected_branch : true ,
push_remove_protected_branch : false ,
push_tag : true ,
push_new_tag : true ,
push_all : true ,
merge_into_protected_branch : true
} ,
developer : {
2018-12-20 11:40:56 -05:00
any : true ,
2016-07-18 04:16:56 -04:00
push_new_branch : true ,
push_master : true ,
push_protected_branch : false ,
push_remove_protected_branch : false ,
2019-06-19 03:08:56 -04:00
push_tag : true ,
2016-07-18 04:16:56 -04:00
push_new_tag : true ,
push_all : false ,
merge_into_protected_branch : false
} ,
reporter : {
2018-12-20 11:40:56 -05:00
any : false ,
2016-07-18 04:16:56 -04:00
push_new_branch : false ,
push_master : false ,
push_protected_branch : false ,
push_remove_protected_branch : false ,
push_tag : false ,
push_new_tag : false ,
push_all : false ,
merge_into_protected_branch : false
} ,
guest : {
2018-12-20 11:40:56 -05:00
any : false ,
2016-07-18 04:16:56 -04:00
push_new_branch : false ,
push_master : false ,
push_protected_branch : false ,
push_remove_protected_branch : false ,
push_tag : false ,
push_new_tag : false ,
push_all : false ,
merge_into_protected_branch : false
}
}
2017-02-22 12:46:57 -05:00
[ %w( feature exact ) , [ 'feat*' , 'wildcard' ] ] . each do | protected_branch_name , protected_branch_type |
2016-07-18 04:16:56 -04:00
context do
2019-01-25 07:11:36 -05:00
let ( :protected_branch ) { create ( :protected_branch , :maintainers_can_push , name : protected_branch_name , project : project ) }
2016-07-18 04:16:56 -04:00
run_permission_checks ( permissions_matrix )
end
2016-07-08 02:15:02 -04:00
context " when developers are allowed to push into the #{ protected_branch_type } protected branch " do
2019-01-25 07:11:36 -05:00
let ( :protected_branch ) { create ( :protected_branch , :developers_can_push , name : protected_branch_name , project : project ) }
2016-07-18 04:16:56 -04:00
run_permission_checks ( permissions_matrix . deep_merge ( developer : { push_protected_branch : true , push_all : true , merge_into_protected_branch : true } ) )
end
2016-07-08 02:15:02 -04:00
context " developers are allowed to merge into the #{ protected_branch_type } protected branch " do
2019-01-25 07:11:36 -05:00
let ( :protected_branch ) { create ( :protected_branch , :developers_can_merge , name : protected_branch_name , project : project ) }
2016-07-18 04:16:56 -04:00
context " when a merge request exists for the given source/target branch " do
context " when the merge request is in progress " do
before do
2016-07-08 02:15:02 -04:00
create ( :merge_request , source_project : project , source_branch : unprotected_branch , target_branch : 'feature' ,
2016-07-08 05:16:13 -04:00
state : 'locked' , in_progress_merge_commit_sha : merge_into_protected_branch )
2016-07-18 04:16:56 -04:00
end
2016-07-25 05:29:05 -04:00
run_permission_checks ( permissions_matrix . deep_merge ( developer : { merge_into_protected_branch : true } ) )
end
2016-07-18 04:16:56 -04:00
2016-07-25 05:29:05 -04:00
context " when the merge request is not in progress " do
before do
create ( :merge_request , source_project : project , source_branch : unprotected_branch , target_branch : 'feature' , in_progress_merge_commit_sha : nil )
2016-07-18 04:16:56 -04:00
end
2016-07-25 05:29:05 -04:00
run_permission_checks ( permissions_matrix . deep_merge ( developer : { merge_into_protected_branch : false } ) )
2016-07-08 02:15:02 -04:00
end
2016-07-18 04:16:56 -04:00
2016-07-08 02:15:02 -04:00
context " when a merge request does not exist for the given source/target branch " do
2016-07-18 04:16:56 -04:00
run_permission_checks ( permissions_matrix . deep_merge ( developer : { merge_into_protected_branch : false } ) )
end
end
end
2016-07-08 02:15:02 -04:00
context " when developers are allowed to push and merge into the #{ protected_branch_type } protected branch " do
2019-01-25 07:11:36 -05:00
let ( :protected_branch ) { create ( :protected_branch , :developers_can_merge , :developers_can_push , name : protected_branch_name , project : project ) }
2016-07-18 04:16:56 -04:00
run_permission_checks ( permissions_matrix . deep_merge ( developer : { push_protected_branch : true , push_all : true , merge_into_protected_branch : true } ) )
end
2016-07-18 06:36:44 -04:00
2016-07-14 02:16:13 -04:00
context " when no one is allowed to push to the #{ protected_branch_name } protected branch " do
2019-01-25 07:11:36 -05:00
let ( :protected_branch ) { build ( :protected_branch , :no_one_can_push , name : protected_branch_name , project : project ) }
2016-07-18 06:36:44 -04:00
2016-07-14 02:16:13 -04:00
run_permission_checks ( permissions_matrix . deep_merge ( developer : { push_protected_branch : false , push_all : false , merge_into_protected_branch : false } ,
2018-07-11 10:36:08 -04:00
maintainer : { push_protected_branch : false , push_all : false , merge_into_protected_branch : false } ,
2020-12-17 13:10:14 -05:00
admin_with_admin_mode : { push_protected_branch : false , push_all : false , merge_into_protected_branch : false } ) )
2016-07-14 02:16:13 -04:00
end
2016-07-08 02:15:02 -04:00
end
2018-03-29 19:10:43 -04:00
context 'when pushing to a project' do
let ( :project ) { create ( :project , :public , :repository ) }
let ( :changes ) { " #{ Gitlab :: Git :: BLANK_SHA } 570e7b2ab refs/heads/wow " }
before do
project . add_developer ( user )
end
2020-10-06 08:08:38 -04:00
it 'disallows users that are blocked pending approval to push' do
user . block_pending_approval
expect { push_access_check } . to raise_forbidden ( 'Your account is pending approval from your administrator and hence blocked.' )
end
2019-10-09 20:06:44 -04:00
it 'does not allow deactivated users to push' do
user . deactivate!
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( " Your account has been deactivated by your administrator. Please log back in from a web browser to reactivate your account at #{ Gitlab . config . gitlab . url } " )
2019-10-09 20:06:44 -04:00
end
2018-03-29 19:10:43 -04:00
it 'cleans up the files' do
expect ( project . repository ) . to receive ( :clean_stale_repository_files ) . and_call_original
expect { push_access_check } . not_to raise_error
end
2018-06-18 19:38:34 -04:00
it 'avoids N+1 queries' , :request_store do
# Run this once to establish a baseline. Cached queries should get
# cached, so that when we introduce another change we shouldn't see
# additional queries.
access . check ( 'git-receive-pack' , changes )
control_count = ActiveRecord :: QueryRecorder . new do
access . check ( 'git-receive-pack' , changes )
end
changes = [ '6f6d7e7ed 570e7b2ab refs/heads/master' , '6f6d7e7ed 570e7b2ab refs/heads/feature' ]
# There is still an N+1 query with protected branches
2019-09-13 09:26:31 -04:00
expect { access . check ( 'git-receive-pack' , changes ) } . not_to exceed_query_limit ( control_count ) . with_threshold ( 2 )
2018-06-18 19:38:34 -04:00
end
2018-10-22 10:49:20 -04:00
it 'raises TimeoutError when #check_single_change_access raises a timeout error' do
message = " Push operation timed out \n \n Timing information for debugging purposes: \n Running checks for ref: wow "
expect_next_instance_of ( Gitlab :: Checks :: ChangeAccess ) do | check |
2020-07-21 14:09:45 -04:00
expect ( check ) . to receive ( :validate! ) . and_raise ( Gitlab :: Checks :: TimedLogger :: TimeoutError )
2018-10-22 10:49:20 -04:00
end
expect { access . check ( 'git-receive-pack' , changes ) } . to raise_error ( described_class :: TimeoutError , message )
end
2018-03-29 19:10:43 -04:00
end
2016-07-08 02:15:02 -04:00
end
2016-07-18 06:36:44 -04:00
2017-05-19 15:58:45 -04:00
describe 'build authentication abilities' do
let ( :authentication_abilities ) { build_authentication_abilities }
2016-07-18 06:36:44 -04:00
2016-09-15 05:57:09 -04:00
context 'when project is authorized' do
2017-06-14 14:18:56 -04:00
before do
2017-12-22 03:18:28 -05:00
project . add_reporter ( user )
2017-06-14 14:18:56 -04:00
end
2016-07-18 06:36:44 -04:00
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :auth_upload ] ) }
2016-09-15 05:57:09 -04:00
end
context 'when unauthorized' do
context 'to public project' do
2017-01-24 18:42:12 -05:00
let ( :project ) { create ( :project , :public , :repository ) }
2016-07-18 06:36:44 -04:00
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :auth_upload ] ) }
2016-07-08 02:15:02 -04:00
end
2016-07-18 06:36:44 -04:00
2016-09-15 05:57:09 -04:00
context 'to internal project' do
2017-01-24 18:42:12 -05:00
let ( :project ) { create ( :project , :internal , :repository ) }
2016-07-18 06:36:44 -04:00
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :auth_upload ] ) }
2016-09-15 05:57:09 -04:00
end
2016-07-08 02:15:02 -04:00
2016-09-15 05:57:09 -04:00
context 'to private project' do
2017-01-24 18:42:12 -05:00
let ( :project ) { create ( :project , :private , :repository ) }
2016-07-08 02:15:02 -04:00
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :auth_upload ] ) }
2016-09-15 09:40:53 -04:00
end
end
2016-09-15 05:57:09 -04:00
end
2017-09-19 03:44:58 -04:00
context 'when the repository is read only' do
let ( :project ) { create ( :project , :repository , :read_only ) }
it 'denies push access' do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2017-09-19 03:44:58 -04:00
2020-02-26 13:09:24 -05:00
expect { push_access_check } . to raise_forbidden ( 'The repository is temporarily read-only. Please try again later.' )
2017-09-19 03:44:58 -04:00
end
end
2016-09-15 05:57:09 -04:00
describe 'deploy key permissions' do
2018-01-05 10:23:44 -05:00
let ( :key ) { create ( :deploy_key , user : user ) }
2016-09-15 05:57:09 -04:00
let ( :actor ) { key }
2016-11-11 08:44:33 -05:00
context 'when deploy_key can push' do
2017-05-19 15:58:45 -04:00
context 'when project is authorized' do
2017-06-14 14:18:56 -04:00
before do
2018-01-05 10:23:44 -05:00
key . deploy_keys_projects . create ( project : project , can_push : true )
2017-06-14 14:18:56 -04:00
end
2017-05-19 15:58:45 -04:00
it { expect { push_access_check } . not_to raise_error }
end
context 'when unauthorized' do
context 'to public project' do
let ( :project ) { create ( :project , :public , :repository ) }
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :deploy_key_upload ] ) }
2017-05-19 15:58:45 -04:00
end
context 'to internal project' do
let ( :project ) { create ( :project , :internal , :repository ) }
2017-08-18 15:06:41 -04:00
it { expect { push_access_check } . to raise_not_found }
2017-05-19 15:58:45 -04:00
end
context 'to private project' do
let ( :project ) { create ( :project , :private , :repository ) }
2017-08-18 15:06:41 -04:00
it { expect { push_access_check } . to raise_not_found }
2016-11-11 08:44:33 -05:00
end
end
end
context 'when deploy_key cannot push' do
2017-05-19 15:58:45 -04:00
context 'when project is authorized' do
2017-06-14 14:18:56 -04:00
before do
2018-01-05 10:23:44 -05:00
key . deploy_keys_projects . create ( project : project , can_push : false )
2017-06-14 14:18:56 -04:00
end
2017-05-19 15:58:45 -04:00
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :deploy_key_upload ] ) }
2017-05-19 15:58:45 -04:00
end
context 'when unauthorized' do
context 'to public project' do
let ( :project ) { create ( :project , :public , :repository ) }
2020-02-26 13:09:24 -05:00
it { expect { push_access_check } . to raise_forbidden ( described_class :: ERROR_MESSAGES [ :deploy_key_upload ] ) }
2017-05-19 15:58:45 -04:00
end
context 'to internal project' do
let ( :project ) { create ( :project , :internal , :repository ) }
2017-08-18 15:06:41 -04:00
it { expect { push_access_check } . to raise_not_found }
2017-05-19 15:58:45 -04:00
end
context 'to private project' do
let ( :project ) { create ( :project , :private , :repository ) }
2017-08-18 15:06:41 -04:00
it { expect { push_access_check } . to raise_not_found }
2016-11-11 08:44:33 -05:00
end
2016-09-15 09:40:53 -04:00
end
end
2016-09-15 05:57:09 -04:00
end
2018-05-08 09:07:55 -04:00
context 'terms are enforced' do
before do
enforce_terms
end
shared_examples 'access after accepting terms' do
let ( :actions ) do
[ - > { pull_access_check } ,
- > { push_access_check } ]
end
it 'blocks access when the user did not accept terms' , :aggregate_failures do
actions . each do | action |
2020-02-26 13:09:24 -05:00
expect { action . call } . to raise_forbidden ( / must accept the Terms of Service in order to perform this action / )
2018-05-08 09:07:55 -04:00
end
end
it 'allows access when the user accepted the terms' , :aggregate_failures do
accept_terms ( user )
actions . each do | action |
expect { action . call } . not_to raise_error
end
end
end
describe 'as an anonymous user to a public project' do
let ( :actor ) { nil }
let ( :project ) { create ( :project , :public , :repository ) }
it { expect { pull_access_check } . not_to raise_error }
end
describe 'as a guest to a public project' do
let ( :project ) { create ( :project , :public , :repository ) }
it_behaves_like 'access after accepting terms' do
let ( :actions ) { [ - > { pull_access_check } ] }
end
end
describe 'as a reporter to the project' do
before do
project . add_reporter ( user )
end
it_behaves_like 'access after accepting terms' do
let ( :actions ) { [ - > { pull_access_check } ] }
end
end
describe 'as a developer of the project' do
before do
project . add_developer ( user )
end
it_behaves_like 'access after accepting terms'
end
2018-07-11 10:36:08 -04:00
describe 'as a maintainer of the project' do
2018-05-08 09:07:55 -04:00
before do
2018-07-11 10:36:08 -04:00
project . add_maintainer ( user )
2018-05-08 09:07:55 -04:00
end
it_behaves_like 'access after accepting terms'
end
describe 'as an owner of the project' do
let ( :project ) { create ( :project , :repository , namespace : user . namespace ) }
it_behaves_like 'access after accepting terms'
end
2018-05-10 10:13:05 -04:00
describe 'when a ci build clones the project' do
let ( :protocol ) { 'http' }
let ( :authentication_abilities ) { [ :build_download_code ] }
let ( :auth_result_type ) { :build }
before do
project . add_developer ( user )
end
it " doesn't block http pull " do
aggregate_failures do
expect { pull_access_check } . not_to raise_error
end
end
end
2018-05-08 09:07:55 -04:00
end
2016-09-15 05:57:09 -04:00
private
2018-07-06 16:56:41 -04:00
def access
2020-07-21 14:09:45 -04:00
access_class . new ( actor , project , protocol ,
2018-07-06 16:56:41 -04:00
authentication_abilities : authentication_abilities ,
2020-12-01 07:09:17 -05:00
repository_path : repository_path ,
2018-07-06 16:56:41 -04:00
redirected_path : redirected_path , auth_result_type : auth_result_type )
end
def push_changes ( changes )
access . check ( 'git-receive-pack' , changes )
end
2020-02-26 13:09:24 -05:00
def raise_forbidden ( message )
2020-07-21 14:09:45 -04:00
raise_error ( described_class :: ForbiddenError , message )
2017-05-19 15:58:45 -04:00
end
2017-08-18 15:06:41 -04:00
def raise_not_found
2020-07-21 14:09:45 -04:00
raise_error ( described_class :: NotFoundError , described_class :: ERROR_MESSAGES [ :project_not_found ] )
2020-05-28 11:08:02 -04:00
end
2016-09-16 03:59:10 -04:00
def build_authentication_abilities
2016-09-15 05:57:09 -04:00
[
:read_project ,
:build_download_code
]
end
2016-09-15 07:49:11 -04:00
2016-09-16 03:59:10 -04:00
def full_authentication_abilities
2016-09-15 07:49:11 -04:00
[
:read_project ,
:download_code ,
:push_code
]
end
2014-09-24 04:37:30 -04:00
end