diff options
author | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2017-06-06 21:21:11 +0200 |
---|---|---|
committer | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2017-06-06 21:21:11 +0200 |
commit | 36ed05faf48bddd53f54971ec9b0f2c611c958d7 (patch) | |
tree | ca8282d1b3cccb89809b7096bd21bffaf26d629c /spec/lib/gitlab | |
parent | da8bd81fe7c1042c50d7c693fdf37ea5b7b78285 (diff) | |
parent | 6ac1caa01a4c059f5bcb7c9da2e83001e5469f73 (diff) | |
download | gitlab-ce-36ed05faf48bddd53f54971ec9b0f2c611c958d7.tar.gz |
Merge commit '6ac1caa01a4c059f5bcb7c9da2e83001e5469f73' into feature/gb/migrate-pipeline-stagesfeature/gb/migrate-pipeline-stages
* commit '6ac1caa01a4c059f5bcb7c9da2e83001e5469f73': (76 commits)
redesign caching of application settings
Fix binary encoding error on MR diffs
Fix missing tooltip and ARIA labels for accessibility
Add info on using self-signed certs with Registry
Actually clean gitlab-test path when TestEnv.set_repo_refs fails
Introduce optimistic locking support via optional parameter last_commit_id on File Update API
Move issuable bulk edit form into a new sidebar.
Add PowerShell to CI variable docs
Responsive environment tables
Accept a username for User-level Events API
Introduce an Events API
Update GitLab Pages to v0.4.3
Allow numeric pages domain
Remove references to old settings location
Resolve "API: Environment info missed"
Fix Projects API spec
Resolve "When changing project visibility setting, change other dropdowns automatically"
Update explanation of job-level variable override to fit example
change headings to improve SEO
backports changed import logic from pull mirroring feature into CE
...
Diffstat (limited to 'spec/lib/gitlab')
-rw-r--r-- | spec/lib/gitlab/checks/change_access_spec.rb | 57 | ||||
-rw-r--r-- | spec/lib/gitlab/ci_access_spec.rb | 15 | ||||
-rw-r--r-- | spec/lib/gitlab/current_settings_spec.rb | 7 | ||||
-rw-r--r-- | spec/lib/gitlab/git/diff_collection_spec.rb | 3 | ||||
-rw-r--r-- | spec/lib/gitlab/git/diff_spec.rb | 38 | ||||
-rw-r--r-- | spec/lib/gitlab/git_access_spec.rb | 290 | ||||
-rw-r--r-- | spec/lib/gitlab/git_access_wiki_spec.rb | 7 | ||||
-rw-r--r-- | spec/lib/gitlab/import_export/all_models.yml | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/otp_key_rotator_spec.rb | 70 |
9 files changed, 390 insertions, 99 deletions
diff --git a/spec/lib/gitlab/checks/change_access_spec.rb b/spec/lib/gitlab/checks/change_access_spec.rb index 8d81ed5856e..c0c309d8179 100644 --- a/spec/lib/gitlab/checks/change_access_spec.rb +++ b/spec/lib/gitlab/checks/change_access_spec.rb @@ -23,29 +23,27 @@ describe Gitlab::Checks::ChangeAccess, lib: true do before { project.add_developer(user) } context 'without failed checks' do - it "doesn't return any error" do - expect(subject.status).to be(true) + it "doesn't raise an error" do + expect { subject }.not_to raise_error end end context 'when the user is not allowed to push code' do - it 'returns an error' do + it 'raises an error' do expect(user_access).to receive(:can_do_action?).with(:push_code).and_return(false) - expect(subject.status).to be(false) - expect(subject.message).to eq('You are not allowed to push code to this project.') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to this project.') end end context 'tags check' do let(:ref) { 'refs/tags/v1.0.0' } - it 'returns an error if the user is not allowed to update tags' do + it 'raises an error if the user is not allowed to update tags' do allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true) expect(user_access).to receive(:can_do_action?).with(:admin_project).and_return(false) - expect(subject.status).to be(false) - expect(subject.message).to eq('You are not allowed to change existing tags on this project.') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to change existing tags on this project.') end context 'with protected tag' do @@ -59,8 +57,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do let(:newrev) { '0000000000000000000000000000000000000000' } it 'is prevented' do - expect(subject.status).to be(false) - expect(subject.message).to include('cannot be deleted') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be deleted/) end end @@ -69,8 +66,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' } it 'is prevented' do - expect(subject.status).to be(false) - expect(subject.message).to include('cannot be updated') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be updated/) end end end @@ -81,15 +77,14 @@ describe Gitlab::Checks::ChangeAccess, lib: true do let(:ref) { 'refs/tags/v9.1.0' } it 'prevents creation below access level' do - expect(subject.status).to be(false) - expect(subject.message).to include('allowed to create this tag as it is protected') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /allowed to create this tag as it is protected/) end context 'when user has access' do let!(:protected_tag) { create(:protected_tag, :developers_can_create, project: project, name: 'v*') } it 'allows tag creation' do - expect(subject.status).to be(true) + expect { subject }.not_to raise_error end end end @@ -101,9 +96,8 @@ describe Gitlab::Checks::ChangeAccess, lib: true do let(:newrev) { '0000000000000000000000000000000000000000' } let(:ref) { 'refs/heads/master' } - it 'returns an error' do - expect(subject.status).to be(false) - expect(subject.message).to eq('The default branch of a project cannot be deleted.') + it 'raises an error' do + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'The default branch of a project cannot be deleted.') end end @@ -113,27 +107,24 @@ describe Gitlab::Checks::ChangeAccess, lib: true do allow(ProtectedBranch).to receive(:protected?).with(project, 'feature').and_return(true) end - it 'returns an error if the user is not allowed to do forced pushes to protected branches' do + it 'raises an error if the user is not allowed to do forced pushes to protected branches' do expect(Gitlab::Checks::ForcePush).to receive(:force_push?).and_return(true) - expect(subject.status).to be(false) - expect(subject.message).to eq('You are not allowed to force push code to a protected branch on this project.') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to force push code to a protected branch on this project.') end - it 'returns an error if the user is not allowed to merge to protected branches' do + it 'raises an error if the user is not allowed to merge to protected branches' do expect_any_instance_of(Gitlab::Checks::MatchingMergeRequest).to receive(:match?).and_return(true) expect(user_access).to receive(:can_merge_to_branch?).and_return(false) expect(user_access).to receive(:can_push_to_branch?).and_return(false) - expect(subject.status).to be(false) - expect(subject.message).to eq('You are not allowed to merge code into protected branches on this project.') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to merge code into protected branches on this project.') end - it 'returns an error if the user is not allowed to push to protected branches' do + it 'raises an error if the user is not allowed to push to protected branches' do expect(user_access).to receive(:can_push_to_branch?).and_return(false) - expect(subject.status).to be(false) - expect(subject.message).to eq('You are not allowed to push code to protected branches on this project.') + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to protected branches on this project.') end context 'branch deletion' do @@ -141,9 +132,8 @@ describe Gitlab::Checks::ChangeAccess, lib: true do let(:ref) { 'refs/heads/feature' } context 'if the user is not allowed to delete protected branches' do - it 'returns an error' do - expect(subject.status).to be(false) - expect(subject.message).to eq('You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.') + it 'raises an error' do + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.') end end @@ -156,14 +146,13 @@ describe Gitlab::Checks::ChangeAccess, lib: true do let(:protocol) { 'web' } it 'allows branch deletion' do - expect(subject.status).to be(true) + expect { subject }.not_to raise_error end end context 'over SSH or HTTP' do - it 'returns an error' do - expect(subject.status).to be(false) - expect(subject.message).to eq('You can only delete protected branches using the web interface.') + it 'raises an error' do + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only delete protected branches using the web interface.') end end end diff --git a/spec/lib/gitlab/ci_access_spec.rb b/spec/lib/gitlab/ci_access_spec.rb new file mode 100644 index 00000000000..eaf8f1d0f1c --- /dev/null +++ b/spec/lib/gitlab/ci_access_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Gitlab::CiAccess, lib: true do + let(:access) { Gitlab::CiAccess.new } + + describe '#can_do_action?' do + context 'when action is :build_download_code' do + it { expect(access.can_do_action?(:build_download_code)).to be_truthy } + end + + context 'when action is not :build_download_code' do + it { expect(access.can_do_action?(:download_code)).to be_falsey } + end + end +end diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb index c796c98ec9f..fda39d78610 100644 --- a/spec/lib/gitlab/current_settings_spec.rb +++ b/spec/lib/gitlab/current_settings_spec.rb @@ -14,20 +14,20 @@ describe Gitlab::CurrentSettings do end it 'attempts to use cached values first' do - expect(ApplicationSetting).to receive(:current) - expect(ApplicationSetting).not_to receive(:last) + expect(ApplicationSetting).to receive(:cached) expect(current_application_settings).to be_a(ApplicationSetting) end it 'falls back to DB if Redis returns an empty value' do + expect(ApplicationSetting).to receive(:cached).and_return(nil) expect(ApplicationSetting).to receive(:last).and_call_original expect(current_application_settings).to be_a(ApplicationSetting) end it 'falls back to DB if Redis fails' do - expect(ApplicationSetting).to receive(:current).and_raise(::Redis::BaseError) + expect(ApplicationSetting).to receive(:cached).and_raise(::Redis::BaseError) expect(ApplicationSetting).to receive(:last).and_call_original expect(current_application_settings).to be_a(ApplicationSetting) @@ -37,6 +37,7 @@ describe Gitlab::CurrentSettings do context 'with DB unavailable' do before do allow_any_instance_of(described_class).to receive(:connect_to_db?).and_return(false) + allow_any_instance_of(described_class).to receive(:retrieve_settings_from_database_cache?).and_return(nil) end it 'returns an in-memory ApplicationSetting object' do diff --git a/spec/lib/gitlab/git/diff_collection_spec.rb b/spec/lib/gitlab/git/diff_collection_spec.rb index 3565e719ad3..a9a7bba2c05 100644 --- a/spec/lib/gitlab/git/diff_collection_spec.rb +++ b/spec/lib/gitlab/git/diff_collection_spec.rb @@ -341,7 +341,8 @@ describe Gitlab::Git::DiffCollection, seed_helper: true do end context 'when diff is quite large will collapse by default' do - let(:iterator) { [{ diff: 'a' * 20480 }] } + let(:iterator) { [{ diff: 'a' * (Gitlab::Git::Diff.collapse_limit + 1) }] } + let(:max_files) { 100 } context 'when no collapse is set' do let(:expanded) { true } diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb index 9c2e8a298c6..da213f617cc 100644 --- a/spec/lib/gitlab/git/diff_spec.rb +++ b/spec/lib/gitlab/git/diff_spec.rb @@ -31,6 +31,36 @@ EOT [".gitmodules"]).patches.first end + describe 'size limit feature toggles' do + context 'when the feature gitlab_git_diff_size_limit_increase is enabled' do + before do + Feature.enable('gitlab_git_diff_size_limit_increase') + end + + it 'returns 200 KB for size_limit' do + expect(described_class.size_limit).to eq(200.kilobytes) + end + + it 'returns 100 KB for collapse_limit' do + expect(described_class.collapse_limit).to eq(100.kilobytes) + end + end + + context 'when the feature gitlab_git_diff_size_limit_increase is disabled' do + before do + Feature.disable('gitlab_git_diff_size_limit_increase') + end + + it 'returns 100 KB for size_limit' do + expect(described_class.size_limit).to eq(100.kilobytes) + end + + it 'returns 10 KB for collapse_limit' do + expect(described_class.collapse_limit).to eq(10.kilobytes) + end + end + end + describe '.new' do context 'using a Hash' do context 'with a small diff' do @@ -47,7 +77,7 @@ EOT context 'using a diff that is too large' do it 'prunes the diff' do - diff = described_class.new(diff: 'a' * 204800) + diff = described_class.new(diff: 'a' * (described_class.size_limit + 1)) expect(diff.diff).to be_empty expect(diff).to be_too_large @@ -85,8 +115,8 @@ EOT # The patch total size is 200, with lines between 21 and 54. # This is a quick-and-dirty way to test this. Ideally, a new patch is # added to the test repo with a size that falls between the real limits. - stub_const("#{described_class}::SIZE_LIMIT", 150) - stub_const("#{described_class}::COLLAPSE_LIMIT", 100) + allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(150) + allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(100) end it 'prunes the diff as a large diff instead of as a collapsed diff' do @@ -299,7 +329,7 @@ EOT describe '#collapsed?' do it 'returns true for a diff that is quite large' do - diff = described_class.new({ diff: 'a' * 20480 }, expanded: false) + diff = described_class.new({ diff: 'a' * (described_class.collapse_limit + 1) }, expanded: false) expect(diff).to be_collapsed end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 25769977f24..36d1d777583 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -1,10 +1,13 @@ require 'spec_helper' describe Gitlab::GitAccess, lib: true do - let(:access) { Gitlab::GitAccess.new(actor, project, 'ssh', authentication_abilities: authentication_abilities) } + let(:pull_access_check) { access.check('git-upload-pack', '_any') } + let(:push_access_check) { access.check('git-receive-pack', '_any') } + let(:access) { Gitlab::GitAccess.new(actor, project, protocol, authentication_abilities: authentication_abilities) } let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:actor) { user } + let(:protocol) { 'ssh' } let(:authentication_abilities) do [ :read_project, @@ -15,49 +18,188 @@ describe Gitlab::GitAccess, lib: true do describe '#check with single protocols allowed' do def disable_protocol(protocol) - settings = ::ApplicationSetting.create_from_defaults - settings.update_attribute(:enabled_git_access_protocol, protocol) + allow(Gitlab::ProtocolAccess).to receive(:allowed?).with(protocol).and_return(false) end context 'ssh disabled' do before do disable_protocol('ssh') - @acc = Gitlab::GitAccess.new(actor, project, 'ssh', authentication_abilities: authentication_abilities) end it 'blocks ssh git push' do - expect(@acc.check('git-receive-pack', '_any').allowed?).to be_falsey + expect { push_access_check }.to raise_unauthorized('Git access over SSH is not allowed') end it 'blocks ssh git pull' do - expect(@acc.check('git-upload-pack', '_any').allowed?).to be_falsey + expect { pull_access_check }.to raise_unauthorized('Git access over SSH is not allowed') end end context 'http disabled' do + let(:protocol) { 'http' } + before do disable_protocol('http') - @acc = Gitlab::GitAccess.new(actor, project, 'http', authentication_abilities: authentication_abilities) end it 'blocks http push' do - expect(@acc.check('git-receive-pack', '_any').allowed?).to be_falsey + expect { push_access_check }.to raise_unauthorized('Git access over HTTP is not allowed') end it 'blocks http git pull' do - expect(@acc.check('git-upload-pack', '_any').allowed?).to be_falsey + expect { pull_access_check }.to raise_unauthorized('Git access over HTTP is not allowed') end end end - describe '#check_download_access!' do - subject { access.check('git-upload-pack', '_any') } + describe '#check_project_accessibility!' do + context 'when the project exists' do + context 'when actor exists' do + context 'when actor is a DeployKey' do + let(:deploy_key) { create(:deploy_key, user: user, can_push: true) } + let(:actor) { deploy_key } + + context 'when the DeployKey has access to the project' do + before { deploy_key.projects << project } + + it 'allows pull access' do + expect { pull_access_check }.not_to raise_error + end + + it 'allows push access' do + expect { push_access_check }.not_to raise_error + end + end + + context 'when the Deploykey does not have access to the project' do + it 'blocks pulls with "not found"' do + expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') + end + + it 'blocks pushes with "not found"' do + expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') + end + end + end + context 'when actor is a User' do + context 'when the User can read the project' do + before { project.team << [user, :master] } + + it 'allows pull access' do + expect { pull_access_check }.not_to raise_error + end + + it 'allows push access' do + expect { push_access_check }.not_to raise_error + end + end + + context 'when the User cannot read the project' do + it 'blocks pulls with "not found"' do + expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') + end + + it 'blocks pushes with "not found"' do + expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') + 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 + expect { pull_access_check }.not_to raise_error + end + + it 'does not block pushes with "not found"' do + expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') + end + end + 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 + expect { pull_access_check }.not_to raise_error + end + + it 'does not block pushes with "not found"' do + expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') + end + end + + context 'when guests cannot read the project' do + it 'blocks pulls with "not found"' do + expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') + end + + it 'blocks pushes with "not found"' do + expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') + end + end + end + end + + context 'when the project is nil' do + let(:project) { nil } + + it 'blocks any command with "not found"' do + expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') + expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') + end + end + end + + describe '#check_command_disabled!' do + before { project.team << [user, :master] } + + 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 + it { expect { pull_access_check }.to raise_unauthorized('Pulling over HTTP is not allowed.') } + end + + context 'when calling git-receive-pack' do + it { expect { push_access_check }.not_to raise_error } + 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 + it { expect { push_access_check }.to raise_unauthorized('Pushing over HTTP is not allowed.') } + end + + context 'when calling git-upload-pack' do + it { expect { pull_access_check }.not_to raise_error } + end + end + end + end + + describe '#check_download_access!' do describe 'master permissions' do before { project.team << [user, :master] } context 'pull code' do - it { expect(subject.allowed?).to be_truthy } + it { expect { pull_access_check }.not_to raise_error } end end @@ -65,8 +207,7 @@ describe Gitlab::GitAccess, lib: true do before { project.team << [user, :guest] } context 'pull code' do - it { expect(subject.allowed?).to be_falsey } - it { expect(subject.message).to match(/You are not allowed to download code/) } + it { expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.') } end end @@ -77,24 +218,22 @@ describe Gitlab::GitAccess, lib: true do end context 'pull code' do - it { expect(subject.allowed?).to be_falsey } - it { expect(subject.message).to match(/Your account has been blocked/) } + it { expect { pull_access_check }.to raise_unauthorized('Your account has been blocked.') } end end describe 'without access to project' do context 'pull code' do - it { expect(subject.allowed?).to be_falsey } + it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') } end context 'when project is public' do let(:public_project) { create(:project, :public, :repository) } - let(:guest_access) { Gitlab::GitAccess.new(nil, public_project, 'web', authentication_abilities: []) } - subject { guest_access.check('git-upload-pack', '_any') } + let(:access) { Gitlab::GitAccess.new(nil, public_project, 'web', authentication_abilities: []) } context 'when repository is enabled' do it 'give access to download code' do - expect(subject.allowed?).to be_truthy + expect { pull_access_check }.not_to raise_error end end @@ -102,8 +241,7 @@ describe Gitlab::GitAccess, lib: true do it 'does not give access to download code' do public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED) - expect(subject.allowed?).to be_falsey - expect(subject.message).to match(/You are not allowed to download code/) + expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.') end end end @@ -117,26 +255,26 @@ describe Gitlab::GitAccess, lib: true do context 'when project is authorized' do before { key.projects << project } - it { expect(subject).to be_allowed } + 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(subject).to be_allowed } + it { expect { pull_access_check }.not_to raise_error } end context 'from internal project' do let(:project) { create(:project, :internal, :repository) } - it { expect(subject).not_to be_allowed } + it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') } end context 'from private project' do let(:project) { create(:project, :private, :repository) } - it { expect(subject).not_to be_allowed } + it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') } end end end @@ -149,7 +287,7 @@ describe Gitlab::GitAccess, lib: true do let(:project) { create(:project, :repository, namespace: user.namespace) } context 'pull code' do - it { expect(subject).to be_allowed } + it { expect { pull_access_check }.not_to raise_error } end end @@ -157,7 +295,7 @@ describe Gitlab::GitAccess, lib: true do before { project.team << [user, :reporter] } context 'pull code' do - it { expect(subject).to be_allowed } + it { expect { pull_access_check }.not_to raise_error } end end @@ -168,16 +306,24 @@ describe Gitlab::GitAccess, lib: true do before { project.team << [user, :reporter] } context 'pull code' do - it { expect(subject).to be_allowed } + 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(subject).not_to be_allowed } + it { expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.') } end end end + + describe 'generic CI (build without a user)' do + let(:actor) { :ci } + + context 'pull code' do + it { expect { pull_access_check }.not_to raise_error } + end + end end end @@ -365,42 +511,32 @@ describe Gitlab::GitAccess, lib: true do end end - shared_examples 'pushing code' do |can| - subject { access.check('git-receive-pack', '_any') } + describe 'build authentication abilities' do + let(:authentication_abilities) { build_authentication_abilities } context 'when project is authorized' do - before { authorize } + before { project.team << [user, :reporter] } - it { expect(subject).public_send(can, be_allowed) } + it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') } end context 'when unauthorized' do context 'to public project' do let(:project) { create(:project, :public, :repository) } - it { expect(subject).not_to be_allowed } + it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') } end context 'to internal project' do let(:project) { create(:project, :internal, :repository) } - it { expect(subject).not_to be_allowed } + it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') } end context 'to private project' do let(:project) { create(:project, :private, :repository) } - it { expect(subject).not_to be_allowed } - end - end - end - - describe 'build authentication abilities' do - let(:authentication_abilities) { build_authentication_abilities } - - it_behaves_like 'pushing code', :not_to do - def authorize - project.team << [user, :reporter] + it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') } end end end @@ -412,9 +548,29 @@ describe Gitlab::GitAccess, lib: true do context 'when deploy_key can push' do let(:can_push) { true } - it_behaves_like 'pushing code', :to do - def authorize - key.projects << project + context 'when project is authorized' do + before { key.projects << project } + + 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) } + + it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') } + end + + context 'to internal project' do + let(:project) { create(:project, :internal, :repository) } + + it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') } + end + + context 'to private project' do + let(:project) { create(:project, :private, :repository) } + + it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') } end end end @@ -422,9 +578,29 @@ describe Gitlab::GitAccess, lib: true do context 'when deploy_key cannot push' do let(:can_push) { false } - it_behaves_like 'pushing code', :not_to do - def authorize - key.projects << project + context 'when project is authorized' do + before { key.projects << project } + + it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') } + end + + context 'when unauthorized' do + context 'to public project' do + let(:project) { create(:project, :public, :repository) } + + it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') } + end + + context 'to internal project' do + let(:project) { create(:project, :internal, :repository) } + + it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') } + end + + context 'to private project' do + let(:project) { create(:project, :private, :repository) } + + it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') } end end end @@ -432,6 +608,14 @@ describe Gitlab::GitAccess, lib: true do private + def raise_unauthorized(message) + raise_error(Gitlab::GitAccess::UnauthorizedError, message) + end + + def raise_not_found(message) + raise_error(Gitlab::GitAccess::NotFoundError, message) + end + def build_authentication_abilities [ :read_project, diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index 1ae293416e4..a1eb95750ba 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -20,7 +20,7 @@ describe Gitlab::GitAccessWiki, lib: true do subject { access.check('git-receive-pack', changes) } - it { expect(subject.allowed?).to be_truthy } + it { expect { subject }.not_to raise_error } end def changes @@ -36,7 +36,7 @@ describe Gitlab::GitAccessWiki, lib: true do context 'when wiki feature is enabled' do it 'give access to download wiki code' do - expect(subject.allowed?).to be_truthy + expect { subject }.not_to raise_error end end @@ -44,8 +44,7 @@ describe Gitlab::GitAccessWiki, lib: true do it 'does not give access to download wiki code' do project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED) - expect(subject.allowed?).to be_falsey - expect(subject.message).to match(/You are not allowed to download code/) + expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to download code from this project.') end end end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 2e9646286df..21296a36729 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -144,7 +144,9 @@ merge_access_levels: push_access_levels: - protected_branch create_access_levels: +- user - protected_tag +- group container_repositories: - project - name diff --git a/spec/lib/gitlab/otp_key_rotator_spec.rb b/spec/lib/gitlab/otp_key_rotator_spec.rb new file mode 100644 index 00000000000..6e6e9ce29ac --- /dev/null +++ b/spec/lib/gitlab/otp_key_rotator_spec.rb @@ -0,0 +1,70 @@ +require 'spec_helper' + +describe Gitlab::OtpKeyRotator do + let(:file) { Tempfile.new("otp-key-rotator-test") } + let(:filename) { file.path } + let(:old_key) { Gitlab::Application.secrets.otp_key_base } + let(:new_key) { "00" * 32 } + let!(:users) { create_list(:user, 5, :two_factor) } + + after do + file.close + file.unlink + end + + def data + CSV.read(filename) + end + + def build_row(user, applied = false) + [user.id.to_s, encrypt_otp(user, old_key), encrypt_otp(user, new_key)] + end + + def encrypt_otp(user, key) + opts = { + value: user.otp_secret, + iv: user.encrypted_otp_secret_iv.unpack("m").join, + salt: user.encrypted_otp_secret_salt.unpack("m").join, + algorithm: 'aes-256-cbc', + insecure_mode: true, + key: key + } + [Encryptor.encrypt(opts)].pack("m") + end + + subject(:rotator) { described_class.new(filename) } + + describe '#rotate!' do + subject(:rotation) { rotator.rotate!(old_key: old_key, new_key: new_key) } + + it 'stores the calculated values in a spreadsheet' do + rotation + + expect(data).to match_array(users.map {|u| build_row(u) }) + end + + context 'new key is too short' do + let(:new_key) { "00" * 31 } + + it { expect { rotation }.to raise_error(ArgumentError) } + end + + context 'new key is the same as the old key' do + let(:new_key) { old_key } + + it { expect { rotation }.to raise_error(ArgumentError) } + end + end + + describe '#rollback!' do + it 'updates rows to the old value' do + file.puts("#{users[0].id},old,new") + file.close + + rotator.rollback! + + expect(users[0].reload.encrypted_otp_secret).to eq('old') + expect(users[1].reload.encrypted_otp_secret).not_to eq('old') + end + end +end |