summaryrefslogtreecommitdiff
path: root/spec/policies
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-19 23:18:09 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-19 23:18:09 +0000
commit6ed4ec3e0b1340f96b7c043ef51d1b33bbe85fde (patch)
treedc4d20fe6064752c0bd323187252c77e0a89144b /spec/policies
parent9868dae7fc0655bd7ce4a6887d4e6d487690eeed (diff)
downloadgitlab-ce-6ed4ec3e0b1340f96b7c043ef51d1b33bbe85fde.tar.gz
Add latest changes from gitlab-org/gitlab@15-4-stable-eev15.4.0-rc42
Diffstat (limited to 'spec/policies')
-rw-r--r--spec/policies/ci/pipeline_schedule_policy_spec.rb2
-rw-r--r--spec/policies/ci/runner_policy_spec.rb160
-rw-r--r--spec/policies/clusters/agent_policy_spec.rb2
-rw-r--r--spec/policies/commit_policy_spec.rb107
-rw-r--r--spec/policies/group_member_policy_spec.rb6
-rw-r--r--spec/policies/group_policy_spec.rb98
-rw-r--r--spec/policies/issuable_policy_spec.rb54
-rw-r--r--spec/policies/issue_policy_spec.rb2
-rw-r--r--spec/policies/merge_request_policy_spec.rb374
-rw-r--r--spec/policies/packages/policies/group_policy_spec.rb79
-rw-r--r--spec/policies/packages/policies/project_policy_spec.rb164
-rw-r--r--spec/policies/project_policy_spec.rb158
-rw-r--r--spec/policies/protected_branch_access_policy_spec.rb31
-rw-r--r--spec/policies/protected_branch_policy_spec.rb44
-rw-r--r--spec/policies/terraform/state_policy_spec.rb2
-rw-r--r--spec/policies/terraform/state_version_policy_spec.rb2
16 files changed, 1067 insertions, 218 deletions
diff --git a/spec/policies/ci/pipeline_schedule_policy_spec.rb b/spec/policies/ci/pipeline_schedule_policy_spec.rb
index f2c99e0de95..9aa50876b55 100644
--- a/spec/policies/ci/pipeline_schedule_policy_spec.rb
+++ b/spec/policies/ci/pipeline_schedule_policy_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Ci::PipelineSchedulePolicy, :models do
+RSpec.describe Ci::PipelineSchedulePolicy, :models, :clean_gitlab_redis_cache do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline_schedule, reload: true) { create(:ci_pipeline_schedule, :nightly, project: project) }
diff --git a/spec/policies/ci/runner_policy_spec.rb b/spec/policies/ci/runner_policy_spec.rb
new file mode 100644
index 00000000000..880ff0722fa
--- /dev/null
+++ b/spec/policies/ci/runner_policy_spec.rb
@@ -0,0 +1,160 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::RunnerPolicy do
+ describe 'ability :read_runner' do
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:owner) { create(:user) }
+
+ let_it_be(:group1) { create(:group, name: 'top-level', path: 'top-level') }
+ let_it_be(:subgroup1) { create(:group, name: 'subgroup1', path: 'subgroup1', parent: group1) }
+ let_it_be(:project1) { create(:project, group: subgroup1) }
+ let_it_be(:instance_runner) { create(:ci_runner, :instance) }
+ let_it_be(:group1_runner) { create(:ci_runner, :group, groups: [group1]) }
+ let_it_be(:project1_runner) { create(:ci_runner, :project, projects: [project1]) }
+
+ subject(:policy) { described_class.new(user, runner) }
+
+ before do
+ group1.add_guest(guest)
+ group1.add_developer(developer)
+ group1.add_owner(owner)
+ end
+
+ shared_context 'on hierarchy with shared runners disabled' do
+ around do |example|
+ group1.update!(shared_runners_enabled: false)
+ project1.update!(shared_runners_enabled: false)
+
+ example.run
+ ensure
+ project1.update!(shared_runners_enabled: true)
+ group1.update!(shared_runners_enabled: true)
+ end
+ end
+
+ shared_context 'on hierarchy with group runners disabled' do
+ around do |example|
+ project1.update!(group_runners_enabled: false)
+
+ example.run
+ ensure
+ project1.update!(group_runners_enabled: true)
+ end
+ end
+
+ shared_examples 'does not allow reading runners on any scope' do
+ context 'with instance runner' do
+ let(:runner) { instance_runner }
+
+ it { expect_disallowed :read_runner }
+
+ context 'with shared runners disabled' do
+ include_context 'on hierarchy with shared runners disabled' do
+ it { expect_disallowed :read_runner }
+ end
+ end
+ end
+
+ context 'with group runner' do
+ let(:runner) { group1_runner }
+
+ it { expect_disallowed :read_runner }
+
+ context 'with group runner disabled' do
+ include_context 'on hierarchy with group runners disabled' do
+ it { expect_disallowed :read_runner }
+ end
+ end
+ end
+
+ context 'with project runner' do
+ let(:runner) { project1_runner }
+
+ it { expect_disallowed :read_runner }
+ end
+ end
+
+ context 'without access' do
+ let_it_be(:user) { create(:user) }
+
+ it_behaves_like 'does not allow reading runners on any scope'
+ end
+
+ context 'with guest access' do
+ let(:user) { guest }
+
+ it_behaves_like 'does not allow reading runners on any scope'
+ end
+
+ context 'with developer access' do
+ let(:user) { developer }
+
+ context 'with instance runner' do
+ let(:runner) { instance_runner }
+
+ it { expect_allowed :read_runner }
+
+ context 'with shared runners disabled' do
+ include_context 'on hierarchy with shared runners disabled' do
+ it { expect_disallowed :read_runner }
+ end
+ end
+ end
+
+ context 'with group runner' do
+ let(:runner) { group1_runner }
+
+ it { expect_allowed :read_runner }
+
+ context 'with group runner disabled' do
+ include_context 'on hierarchy with group runners disabled' do
+ it { expect_disallowed :read_runner }
+ end
+ end
+ end
+
+ context 'with project runner' do
+ let(:runner) { project1_runner }
+
+ it { expect_disallowed :read_runner }
+ end
+ end
+
+ context 'with owner access' do
+ let(:user) { owner }
+
+ context 'with instance runner' do
+ let(:runner) { instance_runner }
+
+ context 'with shared runners disabled' do
+ include_context 'on hierarchy with shared runners disabled' do
+ it { expect_disallowed :read_runner }
+ end
+ end
+
+ it { expect_allowed :read_runner }
+ end
+
+ context 'with group runner' do
+ let(:runner) { group1_runner }
+
+ context 'with group runners disabled' do
+ include_context 'on hierarchy with group runners disabled' do
+ it { expect_allowed :read_runner }
+ end
+ end
+
+ it { expect_allowed :read_runner }
+ end
+
+ context 'with project runner' do
+ let(:runner) { project1_runner }
+
+ it { expect_allowed :read_runner }
+ end
+ end
+ end
+end
diff --git a/spec/policies/clusters/agent_policy_spec.rb b/spec/policies/clusters/agent_policy_spec.rb
index 307d751b78b..8f778d318ed 100644
--- a/spec/policies/clusters/agent_policy_spec.rb
+++ b/spec/policies/clusters/agent_policy_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Clusters::AgentPolicy do
- let(:cluster_agent) { create(:cluster_agent, name: 'agent' )}
+ let(:cluster_agent) { create(:cluster_agent, name: 'agent' ) }
let(:user) { create(:admin) }
let(:policy) { described_class.new(user, cluster_agent) }
let(:project) { cluster_agent.project }
diff --git a/spec/policies/commit_policy_spec.rb b/spec/policies/commit_policy_spec.rb
index 0d3dcc97565..cf2798b9ef3 100644
--- a/spec/policies/commit_policy_spec.rb
+++ b/spec/policies/commit_policy_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe CommitPolicy do
describe '#rules' do
+ let(:group) { create(:group, :public) }
let(:user) { create(:user) }
let(:commit) { project.repository.head_commit }
let(:policy) { described_class.new(user, commit) }
@@ -19,59 +20,119 @@ RSpec.describe CommitPolicy do
end
shared_examples 'cannot read commit nor create a note' do
- it 'can not read commit' do
+ it 'cannot read commit' do
expect(policy).to be_disallowed(:read_commit)
end
- it 'can not create a note' do
+ it 'cannot create a note' do
expect(policy).to be_disallowed(:create_note)
end
end
context 'when project is public' do
- let(:project) { create(:project, :public, :repository) }
+ let(:project) { create(:project, :public, :repository, group: group) }
- it_behaves_like 'can read commit and create a note'
+ context 'when the user is not a project member' do
+ it_behaves_like 'can read commit and create a note'
+ end
context 'when repository access level is private' do
- let(:project) { create(:project, :public, :repository, :repository_private) }
+ let(:project) { create(:project, :public, :repository, :repository_private, group: group) }
- it_behaves_like 'cannot read commit nor create a note'
+ context 'when the user is not a project member' do
+ it_behaves_like 'cannot read commit nor create a note'
+ end
- context 'when the user is a project member' do
- before do
- project.add_developer(user)
+ context 'when the user is a direct project member' do
+ context 'and the user is a developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'can read commit and create a note'
end
+ end
- it_behaves_like 'can read commit and create a note'
+ context 'when the user is an inherited member from the group' do
+ context 'and the user is a guest' do
+ before do
+ group.add_guest(user)
+ end
+
+ it_behaves_like 'can read commit and create a note'
+ end
+
+ context 'and the user is a reporter' do
+ before do
+ group.add_reporter(user)
+ end
+
+ it_behaves_like 'can read commit and create a note'
+ end
+
+ context 'and the user is a developer' do
+ before do
+ group.add_developer(user)
+ end
+
+ it_behaves_like 'can read commit and create a note'
+ end
end
end
end
context 'when project is private' do
- let(:project) { create(:project, :private, :repository) }
+ let(:project) { create(:project, :private, :repository, group: group) }
- it_behaves_like 'cannot read commit nor create a note'
+ context 'when the user is not a project member' do
+ it_behaves_like 'cannot read commit nor create a note'
+ end
- context 'when the user is a project member' do
- before do
- project.add_developer(user)
+ context 'when the user is a direct project member' do
+ context 'and the user is a developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'can read commit and create a note'
end
- it 'can read commit and create a note' do
- expect(policy).to be_allowed(:read_commit)
+ context 'and the user is a guest' do
+ before do
+ project.add_guest(user)
+ end
+
+ it_behaves_like 'cannot read commit nor create a note'
+
+ it 'cannot download code' do
+ expect(policy).to be_disallowed(:download_code)
+ end
end
end
- context 'when the user is a guest' do
- before do
- project.add_guest(user)
+ context 'when the user is an inherited member from the group' do
+ context 'and the user is a guest' do
+ before do
+ group.add_guest(user)
+ end
+
+ it_behaves_like 'cannot read commit nor create a note'
end
- it_behaves_like 'cannot read commit nor create a note'
+ context 'and the user is a reporter' do
+ before do
+ group.add_reporter(user)
+ end
+
+ it_behaves_like 'can read commit and create a note'
+ end
- it 'cannot download code' do
- expect(policy).to be_disallowed(:download_code)
+ context 'and the user is a developer' do
+ before do
+ group.add_developer(user)
+ end
+
+ it_behaves_like 'can read commit and create a note'
end
end
end
diff --git a/spec/policies/group_member_policy_spec.rb b/spec/policies/group_member_policy_spec.rb
index 50774313aae..27ce683861c 100644
--- a/spec/policies/group_member_policy_spec.rb
+++ b/spec/policies/group_member_policy_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe GroupMemberPolicy do
context 'with the group parent' do
let(:current_user) { create :user }
- let(:subgroup) { create(:group, :private, parent: group)}
+ let(:subgroup) { create(:group, :private, parent: group) }
before do
group.add_owner(owner)
@@ -143,7 +143,7 @@ RSpec.describe GroupMemberPolicy do
context 'without group parent' do
let(:current_user) { create :user }
- let(:subgroup) { create(:group, :private)}
+ let(:subgroup) { create(:group, :private) }
before do
subgroup.add_owner(current_user)
@@ -158,7 +158,7 @@ RSpec.describe GroupMemberPolicy do
context 'without group parent with two owners' do
let(:current_user) { create :user }
let(:other_user) { create :user }
- let(:subgroup) { create(:group, :private)}
+ let(:subgroup) { create(:group, :private) }
before do
subgroup.add_owner(current_user)
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 57923142648..da0270c15b9 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe GroupPolicy do
let(:group) { create(:group, :public, :crm_enabled) }
let(:current_user) { nil }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_disallowed(:upload_file)
expect_disallowed(*reporter_permissions)
@@ -24,7 +24,7 @@ RSpec.describe GroupPolicy do
let(:group) { create(:group, :public, :crm_enabled) }
let(:current_user) { create(:user) }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_disallowed(:upload_file)
expect_disallowed(*reporter_permissions)
@@ -43,7 +43,7 @@ RSpec.describe GroupPolicy do
create(:project_group_link, project: project, group: group)
end
- it do
+ specify do
expect_disallowed(*public_permissions)
expect_disallowed(*reporter_permissions)
expect_disallowed(*owner_permissions)
@@ -58,7 +58,7 @@ RSpec.describe GroupPolicy do
create(:project_group_link, project: project, group: group)
end
- it do
+ specify do
expect_disallowed(*public_permissions)
expect_disallowed(*reporter_permissions)
expect_disallowed(*owner_permissions)
@@ -91,7 +91,7 @@ RSpec.describe GroupPolicy do
let(:deploy_token) { create(:deploy_token) }
let(:current_user) { deploy_token }
- it do
+ specify do
expect_disallowed(*public_permissions)
expect_disallowed(*guest_permissions)
expect_disallowed(*reporter_permissions)
@@ -104,7 +104,7 @@ RSpec.describe GroupPolicy do
context 'guests' do
let(:current_user) { guest }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_disallowed(*reporter_permissions)
@@ -121,7 +121,7 @@ RSpec.describe GroupPolicy do
context 'reporter' do
let(:current_user) { reporter }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -138,7 +138,7 @@ RSpec.describe GroupPolicy do
context 'developer' do
let(:current_user) { developer }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -195,7 +195,7 @@ RSpec.describe GroupPolicy do
context 'owner' do
let(:current_user) { owner }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -282,7 +282,7 @@ RSpec.describe GroupPolicy do
context 'with no user' do
let(:current_user) { nil }
- it do
+ specify do
expect_disallowed(*public_permissions)
expect_disallowed(*guest_permissions)
expect_disallowed(*reporter_permissions)
@@ -295,7 +295,7 @@ RSpec.describe GroupPolicy do
context 'guests' do
let(:current_user) { guest }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_disallowed(*reporter_permissions)
@@ -308,7 +308,7 @@ RSpec.describe GroupPolicy do
context 'reporter' do
let(:current_user) { reporter }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -321,7 +321,7 @@ RSpec.describe GroupPolicy do
context 'developer' do
let(:current_user) { developer }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -334,7 +334,7 @@ RSpec.describe GroupPolicy do
context 'maintainer' do
let(:current_user) { maintainer }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -347,7 +347,7 @@ RSpec.describe GroupPolicy do
context 'owner' do
let(:current_user) { owner }
- it do
+ specify do
expect_allowed(*public_permissions)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -916,6 +916,74 @@ RSpec.describe GroupPolicy do
end
end
+ describe 'observability' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:allowed) { be_allowed(:read_observability) }
+ let(:disallowed) { be_disallowed(:read_observability) }
+
+ # rubocop:disable Layout/LineLength
+ where(:feature_enabled, :admin_matcher, :owner_matcher, :maintainer_matcher, :developer_matcher, :reporter_matcher, :guest_matcher, :non_member_matcher, :anonymous_matcher) do
+ false | ref(:disallowed) | ref(:disallowed) | ref(:disallowed) | ref(:disallowed) | ref(:disallowed) | ref(:disallowed) | ref(:disallowed) | ref(:disallowed)
+ true | ref(:allowed) | ref(:allowed) | ref(:allowed) | ref(:allowed) | ref(:disallowed) | ref(:disallowed) | ref(:disallowed) | ref(:disallowed)
+ end
+ # rubocop:enable Layout/LineLength
+
+ with_them do
+ before do
+ stub_feature_flags(observability_group_tab: feature_enabled)
+ end
+
+ context 'admin', :enable_admin_mode do
+ let(:current_user) { admin }
+
+ it { is_expected.to admin_matcher }
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to owner_matcher }
+ end
+
+ context 'maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to maintainer_matcher }
+ end
+
+ context 'developer' do
+ let(:current_user) { developer }
+
+ it { is_expected.to developer_matcher }
+ end
+
+ context 'reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to reporter_matcher }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to guest_matcher }
+ end
+
+ context 'with non member' do
+ let(:current_user) { create(:user) }
+
+ it { is_expected.to non_member_matcher }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.to anonymous_matcher }
+ end
+ end
+ end
+
describe 'dependency proxy' do
context 'feature disabled' do
let(:current_user) { owner }
diff --git a/spec/policies/issuable_policy_spec.rb b/spec/policies/issuable_policy_spec.rb
index 706570babd5..fd7ec5917d6 100644
--- a/spec/policies/issuable_policy_spec.rb
+++ b/spec/policies/issuable_policy_spec.rb
@@ -18,8 +18,8 @@ RSpec.describe IssuablePolicy, models: true do
project.add_reporter(reporter)
end
- def permissions(user, issue)
- described_class.new(user, issue)
+ def permissions(user, issuable)
+ described_class.new(user, issuable)
end
describe '#rules' do
@@ -153,5 +153,55 @@ RSpec.describe IssuablePolicy, models: true do
expect(permissions(reporter, issue)).to be_allowed(:create_timelog)
end
end
+
+ context 'when subject is a Merge Request' do
+ let(:issuable) { create(:merge_request) }
+ let(:policy) { permissions(user, issuable) }
+
+ before do
+ allow(policy).to receive(:can?).with(:read_merge_request).and_return(can_read_merge_request)
+ end
+
+ context 'when can_read_merge_request is false' do
+ let(:can_read_merge_request) { false }
+
+ it 'does not allow :read_issuable' do
+ expect(policy).not_to be_allowed(:read_issuable)
+ end
+ end
+
+ context 'when can_read_merge_request is true' do
+ let(:can_read_merge_request) { true }
+
+ it 'allows :read_issuable' do
+ expect(policy).to be_allowed(:read_issuable)
+ end
+ end
+ end
+
+ context 'when subject is an Issue' do
+ let(:issuable) { create(:issue) }
+ let(:policy) { permissions(user, issuable) }
+
+ before do
+ allow(policy).to receive(:can?).with(:read_issue).and_return(can_read_issue)
+ end
+
+ context 'when can_read_issue is false' do
+ let(:can_read_issue) { false }
+
+ it 'does not allow :read_issuable' do
+ expect(policy).not_to be_allowed(:read_issuable)
+ end
+ end
+
+ context 'when can_read_issue is true' do
+ let(:can_read_issue) { true }
+
+ it 'allows :read_issuable' do
+ expect(policy).to be_allowed(:read_issuable)
+ end
+ end
+ end
end
end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index 7ca4baddb79..4d492deb54c 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -398,7 +398,7 @@ RSpec.describe IssuePolicy do
context 'with a hidden issue' do
let(:user) { create(:user) }
let(:banned_user) { create(:user, :banned) }
- let(:admin) { create(:user, :admin)}
+ let(:admin) { create(:user, :admin) }
let(:hidden_issue) { create(:issue, project: project, author: banned_user) }
it 'does not allow non-admin user to read the issue' do
diff --git a/spec/policies/merge_request_policy_spec.rb b/spec/policies/merge_request_policy_spec.rb
index dd42e1b9313..7e1af132b1d 100644
--- a/spec/policies/merge_request_policy_spec.rb
+++ b/spec/policies/merge_request_policy_spec.rb
@@ -7,24 +7,18 @@ RSpec.describe MergeRequestPolicy do
let_it_be(:guest) { create(:user) }
let_it_be(:author) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:non_team_member) { create(:user) }
- let(:project) { create(:project, :public) }
-
def permissions(user, merge_request)
described_class.new(user, merge_request)
end
- before do
- project.add_guest(guest)
- project.add_guest(author)
- project.add_developer(developer)
- end
-
mr_perms = %i[create_merge_request_in
create_merge_request_from
read_merge_request
+ update_merge_request
create_todo
approve_merge_request
create_note
@@ -40,7 +34,28 @@ RSpec.describe MergeRequestPolicy do
end
end
- shared_examples_for 'a user with access' do
+ shared_examples_for 'a user with reporter access' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:policy, :is_allowed) do
+ :create_merge_request_in | true
+ :read_merge_request | true
+ :create_todo | true
+ :create_note | true
+ :update_subscription | true
+ :create_merge_request_from | false
+ :approve_merge_request | false
+ :update_merge_request | false
+ end
+
+ with_them do
+ specify do
+ is_allowed ? (is_expected.to be_allowed(policy)) : (is_expected.to be_disallowed(policy))
+ end
+ end
+ end
+
+ shared_examples_for 'a user with full access' do
let(:perms) { permissions(subject, merge_request) }
mr_perms.each do |thing|
@@ -50,199 +65,304 @@ RSpec.describe MergeRequestPolicy do
end
end
- context 'when merge request is public' do
- let(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: user) }
- let(:user) { author }
-
- context 'and user is anonymous' do
- subject { permissions(nil, merge_request) }
+ context 'when user is a direct project member' do
+ let(:project) { create(:project, :public) }
- it do
- is_expected.to be_disallowed(:create_todo, :update_subscription)
- end
+ before do
+ project.add_guest(guest)
+ project.add_guest(author)
+ project.add_developer(developer)
end
- context 'and user is author' do
- subject { permissions(user, merge_request) }
+ context 'when merge request is public' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: user) }
+ let(:user) { author }
- context 'and the user is a guest' do
- let(:user) { guest }
+ context 'and user is author' do
+ subject { permissions(user, merge_request) }
- it do
- is_expected.to be_allowed(:update_merge_request)
- end
+ context 'and the user is a guest' do
+ let(:user) { guest }
- it do
- is_expected.to be_allowed(:reopen_merge_request)
- end
+ it do
+ is_expected.to be_allowed(:update_merge_request)
+ end
- it do
- is_expected.to be_allowed(:approve_merge_request)
+ it do
+ is_expected.to be_allowed(:reopen_merge_request)
+ end
+
+ it do
+ is_expected.to be_allowed(:approve_merge_request)
+ end
end
end
+ end
- context 'and the user is a group member' do
- let(:project) { create(:project, :public, group: group) }
- let(:group) { create(:group) }
- let(:user) { non_team_member }
-
- before do
- group.add_guest(non_team_member)
- end
+ context 'when merge requests have been disabled' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
- it do
- is_expected.to be_allowed(:approve_merge_request)
- end
+ before do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
end
- context 'and the user is a member of a shared group' do
- let(:user) { non_team_member }
+ describe 'the author' do
+ subject { author }
- before do
- group = create(:group)
- project.project_group_links.create!(
- group: group,
- group_access: Gitlab::Access::DEVELOPER)
+ it_behaves_like 'a denied user'
+ end
- group.add_guest(non_team_member)
- end
+ describe 'a guest' do
+ subject { guest }
- it do
- is_expected.to be_allowed(:approve_merge_request)
- end
+ it_behaves_like 'a denied user'
end
- context 'and the user is not a project member' do
- let(:user) { non_team_member }
+ describe 'a developer' do
+ subject { developer }
- it do
- is_expected.not_to be_allowed(:approve_merge_request)
- end
+ it_behaves_like 'a denied user'
end
end
- end
- context 'when merge requests have been disabled' do
- let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
+ context 'when merge requests are private' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
- before do
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
- end
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
- describe 'the author' do
- subject { author }
+ describe 'the author' do
+ subject { author }
- it_behaves_like 'a denied user'
+ it_behaves_like 'a denied user'
+ end
+
+ describe 'a developer' do
+ subject { developer }
+
+ it_behaves_like 'a user with full access'
+ end
end
- describe 'a guest' do
- subject { guest }
+ context 'when merge request is unlocked' do
+ let(:merge_request) { create(:merge_request, :closed, source_project: project, target_project: project, author: author) }
- it_behaves_like 'a denied user'
+ it 'allows author to reopen merge request' do
+ expect(permissions(author, merge_request)).to be_allowed(:reopen_merge_request)
+ end
+
+ it 'allows developer to reopen merge request' do
+ expect(permissions(developer, merge_request)).to be_allowed(:reopen_merge_request)
+ end
+
+ it 'prevents guest from reopening merge request' do
+ expect(permissions(guest, merge_request)).to be_disallowed(:reopen_merge_request)
+ end
end
- describe 'a developer' do
- subject { developer }
+ context 'when merge request is locked' do
+ let(:merge_request_locked) { create(:merge_request, :closed, discussion_locked: true, source_project: project, target_project: project, author: author) }
- it_behaves_like 'a denied user'
+ it 'prevents author from reopening merge request' do
+ expect(permissions(author, merge_request_locked)).to be_disallowed(:reopen_merge_request)
+ end
+
+ it 'prevents developer from reopening merge request' do
+ expect(permissions(developer, merge_request_locked)).to be_disallowed(:reopen_merge_request)
+ end
+
+ it 'prevents guests from reopening merge request' do
+ expect(permissions(guest, merge_request_locked)).to be_disallowed(:reopen_merge_request)
+ end
+
+ context 'when the user is project member, with at least guest access' do
+ let(:user) { guest }
+
+ it 'can create a note' do
+ expect(permissions(user, merge_request_locked)).to be_allowed(:create_note)
+ end
+ end
end
- describe 'any other user' do
- subject { non_team_member }
+ context 'with external authorization enabled' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:policies) { described_class.new(user, merge_request) }
- it_behaves_like 'a denied user'
+ before do
+ enable_external_authorization_service_check
+ end
+
+ it 'can read the issue iid without accessing the external service' do
+ expect(::Gitlab::ExternalAuthorization).not_to receive(:access_allowed?)
+
+ expect(policies).to be_allowed(:read_merge_request_iid)
+ end
end
end
- context 'when merge requests are private' do
- let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
+ context 'when user is an inherited member from the parent group' do
+ let_it_be(:group) { create(:group, :public) }
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: author) }
+
+ before_all do
+ group.add_guest(guest)
+ group.add_guest(author)
+ group.add_reporter(reporter)
+ group.add_developer(developer)
end
- describe 'a non-team-member' do
- subject { non_team_member }
+ context 'when project is public' do
+ let(:project) { create(:project, :public, group: group) }
- it_behaves_like 'a denied user'
- end
+ describe 'the merge request author' do
+ subject { permissions(author, merge_request) }
- describe 'the author' do
- subject { author }
+ specify do
+ is_expected.to be_allowed(:approve_merge_request)
+ end
+ end
- it_behaves_like 'a denied user'
+ context 'and merge requests are private' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ describe 'a guest' do
+ subject { guest }
+
+ it_behaves_like 'a denied user'
+ end
+
+ describe 'a reporter' do
+ subject { permissions(reporter, merge_request) }
+
+ it_behaves_like 'a user with reporter access'
+ end
+
+ describe 'a developer' do
+ subject { developer }
+
+ it_behaves_like 'a user with full access'
+ end
+ end
end
- describe 'a developer' do
- subject { developer }
+ context 'when project is private' do
+ let(:project) { create(:project, :private, group: group) }
+
+ describe 'a guest' do
+ subject { guest }
- it_behaves_like 'a user with access'
+ it_behaves_like 'a denied user'
+ end
+
+ describe 'a reporter' do
+ subject { permissions(reporter, merge_request) }
+
+ it_behaves_like 'a user with reporter access'
+ end
+
+ describe 'a developer' do
+ subject { developer }
+
+ it_behaves_like 'a user with full access'
+ end
end
end
- context 'when merge request is unlocked' do
- let(:merge_request) { create(:merge_request, :closed, source_project: project, target_project: project, author: author) }
+ context 'when user is an inherited member from a shared group' do
+ let(:project) { create(:project, :public) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: user) }
+ let(:user) { author }
- it 'allows author to reopen merge request' do
- expect(permissions(author, merge_request)).to be_allowed(:reopen_merge_request)
+ before do
+ project.add_guest(author)
end
- it 'allows developer to reopen merge request' do
- expect(permissions(developer, merge_request)).to be_allowed(:reopen_merge_request)
- end
+ context 'and group is given developer access' do
+ let(:user) { non_team_member }
+
+ subject { permissions(user, merge_request) }
+
+ before do
+ group = create(:group)
+ project.project_group_links.create!(
+ group: group,
+ group_access: Gitlab::Access::DEVELOPER)
+
+ group.add_guest(non_team_member)
+ end
- it 'prevents guest from reopening merge request' do
- expect(permissions(guest, merge_request)).to be_disallowed(:reopen_merge_request)
+ specify do
+ is_expected.to be_allowed(:approve_merge_request)
+ end
end
end
- context 'when merge request is locked' do
- let(:merge_request_locked) { create(:merge_request, :closed, discussion_locked: true, source_project: project, target_project: project, author: author) }
+ context 'when user is not a project member' do
+ let(:project) { create(:project, :public) }
- it 'prevents author from reopening merge request' do
- expect(permissions(author, merge_request_locked)).to be_disallowed(:reopen_merge_request)
- end
+ context 'when merge request is public' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
- it 'prevents developer from reopening merge request' do
- expect(permissions(developer, merge_request_locked)).to be_disallowed(:reopen_merge_request)
+ subject { permissions(non_team_member, merge_request) }
+
+ specify do
+ is_expected.not_to be_allowed(:approve_merge_request)
+ end
end
- it 'prevents guests from reopening merge request' do
- expect(permissions(guest, merge_request_locked)).to be_disallowed(:reopen_merge_request)
+ context 'when merge requests are disabled' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ before do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
+ end
+
+ subject { non_team_member }
+
+ it_behaves_like 'a denied user'
end
- context 'when the user is not a project member' do
- let(:user) { create(:user) }
+ context 'when merge requests are private' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
- it 'cannot create a note' do
- expect(permissions(user, merge_request_locked)).to be_disallowed(:create_note)
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
end
+
+ subject { non_team_member }
+
+ it_behaves_like 'a denied user'
end
- context 'when the user is project member, with at least guest access' do
- let(:user) { guest }
+ context 'when merge request is locked' do
+ let(:merge_request) { create(:merge_request, :closed, discussion_locked: true, source_project: project, target_project: project) }
- it 'can create a note' do
- expect(permissions(user, merge_request_locked)).to be_allowed(:create_note)
+ it 'cannot create a note' do
+ expect(permissions(non_team_member, merge_request)).to be_disallowed(:create_note)
end
end
end
- context 'with external authorization enabled' do
- let(:user) { create(:user) }
+ context 'when user is anonymous' do
let(:project) { create(:project, :public) }
- let(:merge_request) { create(:merge_request, source_project: project) }
- let(:policies) { described_class.new(user, merge_request) }
- before do
- enable_external_authorization_service_check
- end
+ context 'when merge request is public' do
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
- it 'can read the issue iid without accessing the external service' do
- expect(::Gitlab::ExternalAuthorization).not_to receive(:access_allowed?)
+ subject { permissions(nil, merge_request) }
- expect(policies).to be_allowed(:read_merge_request_iid)
+ specify do
+ is_expected.to be_disallowed(:create_todo, :update_subscription)
+ end
end
end
end
diff --git a/spec/policies/packages/policies/group_policy_spec.rb b/spec/policies/packages/policies/group_policy_spec.rb
new file mode 100644
index 00000000000..d0d9a9a22f5
--- /dev/null
+++ b/spec/policies/packages/policies/group_policy_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Policies::GroupPolicy do
+ include_context 'GroupPolicy context'
+
+ subject { described_class.new(current_user, group.packages_policy_subject) }
+
+ describe 'read_package' do
+ context 'with admin' do
+ let(:current_user) { admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+ end
+
+ describe 'deploy token access' do
+ let!(:group_deploy_token) do
+ create(:group_deploy_token, group: group, deploy_token: deploy_token)
+ end
+
+ subject { described_class.new(deploy_token, group.packages_policy_subject) }
+
+ context 'when a deploy token with read_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, :group, read_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'when a deploy token with write_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, :group, write_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+ end
+end
diff --git a/spec/policies/packages/policies/project_policy_spec.rb b/spec/policies/packages/policies/project_policy_spec.rb
new file mode 100644
index 00000000000..5d54ee54572
--- /dev/null
+++ b/spec/policies/packages/policies/project_policy_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Policies::ProjectPolicy do
+ include_context 'ProjectPolicy context'
+
+ let(:project) { public_project }
+
+ subject { described_class.new(current_user, project.packages_policy_subject) }
+
+ describe 'deploy token access' do
+ let!(:project_deploy_token) do
+ create(:project_deploy_token, project: project, deploy_token: deploy_token)
+ end
+
+ subject { described_class.new(deploy_token, project.packages_policy_subject) }
+
+ context 'when a deploy token with read_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+
+ it_behaves_like 'package access with repository disabled'
+ end
+
+ context 'when a deploy token with write_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, write_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+
+ it_behaves_like 'package access with repository disabled'
+ end
+ end
+
+ describe 'read_package', :enable_admin_mode do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:project, :package_registry_access_level, :current_user, :expect_to_be_allowed) do
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:anonymous) | false
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:non_member) | false
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:guest) | false
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:reporter) | false
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:developer) | false
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:maintainer) | false
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:owner) | false
+ ref(:private_project) | ProjectFeature::DISABLED | ref(:admin) | false
+
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:anonymous) | false
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:non_member) | false
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:guest) | false
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:reporter) | true
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:developer) | true
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:maintainer) | true
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:owner) | true
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:admin) | true
+
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:anonymous) | true
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:non_member) | true
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:guest) | true
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:reporter) | true
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:developer) | true
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:maintainer) | true
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:owner) | true
+ ref(:private_project) | ProjectFeature::PUBLIC | ref(:admin) | true
+
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:anonymous) | false
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:non_member) | false
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:guest) | false
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:reporter) | false
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:developer) | false
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:maintainer) | false
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:owner) | false
+ ref(:internal_project) | ProjectFeature::DISABLED | ref(:admin) | false
+
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:anonymous) | false
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:non_member) | true
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:guest) | true
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:reporter) | true
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:developer) | true
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:maintainer) | true
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:owner) | true
+ ref(:internal_project) | ProjectFeature::ENABLED | ref(:admin) | true
+
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:anonymous) | true
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:non_member) | true
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:guest) | true
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:reporter) | true
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:developer) | true
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:maintainer) | true
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:owner) | true
+ ref(:internal_project) | ProjectFeature::PUBLIC | ref(:admin) | true
+
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:anonymous) | false
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:non_member) | false
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:guest) | false
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:reporter) | false
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:developer) | false
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:maintainer) | false
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:owner) | false
+ ref(:public_project) | ProjectFeature::DISABLED | ref(:admin) | false
+
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:anonymous) | true
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:non_member) | true
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:guest) | true
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:reporter) | true
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:developer) | true
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:maintainer) | true
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:owner) | true
+ ref(:public_project) | ProjectFeature::PUBLIC | ref(:admin) | true
+ end
+
+ with_them do
+ it do
+ project.project_feature.update!(package_registry_access_level: package_registry_access_level)
+
+ if expect_to_be_allowed
+ is_expected.to be_allowed(:read_package)
+ else
+ is_expected.to be_disallowed(:read_package)
+ end
+ end
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(package_registry_access_level: false)
+ end
+
+ where(:project, :current_user, :expect_to_be_allowed) do
+ ref(:private_project) | ref(:anonymous) | false
+ ref(:private_project) | ref(:non_member) | false
+ ref(:private_project) | ref(:guest) | false
+ ref(:internal_project) | ref(:anonymous) | false
+ ref(:public_project) | ref(:admin) | true
+ ref(:public_project) | ref(:owner) | true
+ ref(:public_project) | ref(:maintainer) | true
+ ref(:public_project) | ref(:developer) | true
+ ref(:public_project) | ref(:reporter) | true
+ ref(:public_project) | ref(:guest) | true
+ ref(:public_project) | ref(:non_member) | true
+ ref(:public_project) | ref(:anonymous) | true
+ end
+
+ with_them do
+ it do
+ project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
+
+ if expect_to_be_allowed
+ is_expected.to be_allowed(:read_package)
+ else
+ is_expected.to be_disallowed(:read_package)
+ end
+ end
+ end
+ end
+
+ context 'with admin' do
+ let(:current_user) { admin }
+
+ it_behaves_like 'package access with repository disabled'
+ end
+ end
+end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index e8fdf9a8e25..fefd9f71408 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -777,13 +777,13 @@ RSpec.describe ProjectPolicy do
project.add_developer(user)
end
- it { is_expected.not_to be_allowed(:project_bot_access)}
+ it { is_expected.not_to be_allowed(:project_bot_access) }
end
context "when project bot and not part of the project" do
let(:current_user) { project_bot }
- it { is_expected.not_to be_allowed(:project_bot_access)}
+ it { is_expected.not_to be_allowed(:project_bot_access) }
end
context "when project bot and part of the project" do
@@ -793,7 +793,7 @@ RSpec.describe ProjectPolicy do
project.add_developer(project_bot)
end
- it { is_expected.to be_allowed(:project_bot_access)}
+ it { is_expected.to be_allowed(:project_bot_access) }
end
end
@@ -804,7 +804,7 @@ RSpec.describe ProjectPolicy do
project.add_maintainer(project_bot)
end
- it { is_expected.not_to be_allowed(:create_resource_access_tokens)}
+ it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
end
end
@@ -946,7 +946,7 @@ RSpec.describe ProjectPolicy do
context 'with anonymous' do
let(:current_user) { anonymous }
- it { is_expected.to be_disallowed(:metrics_dashboard)}
+ it { is_expected.to be_disallowed(:metrics_dashboard) }
end
end
@@ -1930,14 +1930,10 @@ RSpec.describe ProjectPolicy do
describe 'operations feature' do
using RSpec::Parameterized::TableSyntax
- before do
- stub_feature_flags(split_operations_visibility_permissions: false)
- end
+ let(:guest_permissions) { [:read_environment, :read_deployment] }
- let(:guest_operations_permissions) { [:read_environment, :read_deployment] }
-
- let(:developer_operations_permissions) do
- guest_operations_permissions + [
+ let(:developer_permissions) do
+ guest_permissions + [
:read_feature_flag, :read_sentry_issue, :read_alert_management_alert, :read_terraform_state,
:metrics_dashboard, :read_pod_logs, :read_prometheus, :create_feature_flag,
:create_environment, :create_deployment, :update_feature_flag, :update_environment,
@@ -1946,13 +1942,17 @@ RSpec.describe ProjectPolicy do
]
end
- let(:maintainer_operations_permissions) do
- developer_operations_permissions + [
+ let(:maintainer_permissions) do
+ developer_permissions + [
:read_cluster, :create_cluster, :update_cluster, :admin_environment,
:admin_cluster, :admin_terraform_state, :admin_deployment
]
end
+ before do
+ stub_feature_flags(split_operations_visibility_permissions: false)
+ end
+
where(:project_visibility, :access_level, :role, :allowed) do
:public | ProjectFeature::ENABLED | :maintainer | true
:public | ProjectFeature::ENABLED | :developer | true
@@ -2005,33 +2005,22 @@ RSpec.describe ProjectPolicy do
expect_disallowed(*permissions_abilities(role))
end
end
-
- def permissions_abilities(role)
- case role
- when :maintainer
- maintainer_operations_permissions
- when :developer
- developer_operations_permissions
- else
- guest_operations_permissions
- end
- end
end
end
describe 'environments feature' do
using RSpec::Parameterized::TableSyntax
- let(:guest_environments_permissions) { [:read_environment, :read_deployment] }
+ let(:guest_permissions) { [:read_environment, :read_deployment] }
- let(:developer_environments_permissions) do
- guest_environments_permissions + [
+ let(:developer_permissions) do
+ guest_permissions + [
:create_environment, :create_deployment, :update_environment, :update_deployment, :destroy_environment
]
end
- let(:maintainer_environments_permissions) do
- developer_environments_permissions + [:admin_environment, :admin_deployment]
+ let(:maintainer_permissions) do
+ developer_permissions + [:admin_environment, :admin_deployment]
end
where(:project_visibility, :access_level, :role, :allowed) do
@@ -2086,15 +2075,73 @@ RSpec.describe ProjectPolicy do
expect_disallowed(*permissions_abilities(role))
end
end
+ end
+ end
- def permissions_abilities(role)
- case role
- when :maintainer
- maintainer_environments_permissions
- when :developer
- developer_environments_permissions
+ describe 'monitor feature' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:guest_permissions) { [] }
+
+ let(:developer_permissions) do
+ guest_permissions + [
+ :read_sentry_issue, :read_alert_management_alert, :metrics_dashboard,
+ :update_sentry_issue, :update_alert_management_alert
+ ]
+ end
+
+ let(:maintainer_permissions) { developer_permissions }
+
+ where(:project_visibility, :access_level, :role, :allowed) do
+ :public | ProjectFeature::ENABLED | :maintainer | true
+ :public | ProjectFeature::ENABLED | :developer | true
+ :public | ProjectFeature::ENABLED | :guest | true
+ :public | ProjectFeature::ENABLED | :anonymous | true
+ :public | ProjectFeature::PRIVATE | :maintainer | true
+ :public | ProjectFeature::PRIVATE | :developer | true
+ :public | ProjectFeature::PRIVATE | :guest | true
+ :public | ProjectFeature::PRIVATE | :anonymous | false
+ :public | ProjectFeature::DISABLED | :maintainer | false
+ :public | ProjectFeature::DISABLED | :developer | false
+ :public | ProjectFeature::DISABLED | :guest | false
+ :public | ProjectFeature::DISABLED | :anonymous | false
+ :internal | ProjectFeature::ENABLED | :maintainer | true
+ :internal | ProjectFeature::ENABLED | :developer | true
+ :internal | ProjectFeature::ENABLED | :guest | true
+ :internal | ProjectFeature::ENABLED | :anonymous | false
+ :internal | ProjectFeature::PRIVATE | :maintainer | true
+ :internal | ProjectFeature::PRIVATE | :developer | true
+ :internal | ProjectFeature::PRIVATE | :guest | true
+ :internal | ProjectFeature::PRIVATE | :anonymous | false
+ :internal | ProjectFeature::DISABLED | :maintainer | false
+ :internal | ProjectFeature::DISABLED | :developer | false
+ :internal | ProjectFeature::DISABLED | :guest | false
+ :internal | ProjectFeature::DISABLED | :anonymous | false
+ :private | ProjectFeature::ENABLED | :maintainer | true
+ :private | ProjectFeature::ENABLED | :developer | true
+ :private | ProjectFeature::ENABLED | :guest | false
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :guest | false
+ :private | ProjectFeature::PRIVATE | :anonymous | false
+ :private | ProjectFeature::DISABLED | :maintainer | false
+ :private | ProjectFeature::DISABLED | :developer | false
+ :private | ProjectFeature::DISABLED | :guest | false
+ :private | ProjectFeature::DISABLED | :anonymous | false
+ end
+
+ with_them do
+ let(:current_user) { user_subject(role) }
+ let(:project) { project_subject(project_visibility) }
+
+ it 'allows/disallows the abilities based on the monitor feature access level' do
+ project.project_feature.update!(monitor_access_level: access_level)
+
+ if allowed
+ expect_allowed(*permissions_abilities(role))
else
- guest_environments_permissions
+ expect_disallowed(*permissions_abilities(role))
end
end
end
@@ -2682,6 +2729,43 @@ RSpec.describe ProjectPolicy do
end
end
+ describe 'read_milestone' do
+ context 'when project is public' do
+ let(:project) { public_project_in_group }
+
+ context 'and issues and merge requests are private' do
+ before do
+ project.project_feature.update!(
+ issues_access_level: ProjectFeature::PRIVATE,
+ merge_requests_access_level: ProjectFeature::PRIVATE
+ )
+ end
+
+ context 'when user is an inherited member from the group' do
+ context 'and user is a guest' do
+ let(:current_user) { inherited_guest }
+
+ it { is_expected.to be_allowed(:read_milestone) }
+ end
+
+ context 'and user is a reporter' do
+ let(:current_user) { inherited_reporter }
+
+ it { is_expected.to be_allowed(:read_milestone) }
+ end
+
+ context 'and user is a developer' do
+ let(:current_user) { inherited_developer }
+
+ it { is_expected.to be_allowed(:read_milestone) }
+ end
+ end
+ end
+ end
+ end
+
+ private
+
def project_subject(project_type)
case project_type
when :public
diff --git a/spec/policies/protected_branch_access_policy_spec.rb b/spec/policies/protected_branch_access_policy_spec.rb
new file mode 100644
index 00000000000..68a130d666a
--- /dev/null
+++ b/spec/policies/protected_branch_access_policy_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProtectedBranchAccessPolicy do
+ let(:user) { create(:user) }
+ let(:protected_branch_access) { create(:protected_branch_merge_access_level) }
+ let(:project) { protected_branch_access.protected_branch.project }
+
+ subject { described_class.new(user, protected_branch_access) }
+
+ context 'as maintainers' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'can be read' do
+ is_expected.to be_allowed(:read_protected_branch)
+ end
+ end
+
+ context 'as guests' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'can not be read' do
+ is_expected.to be_disallowed(:read_protected_branch)
+ end
+ end
+end
diff --git a/spec/policies/protected_branch_policy_spec.rb b/spec/policies/protected_branch_policy_spec.rb
index bb6dbff18a0..d676de14735 100644
--- a/spec/policies/protected_branch_policy_spec.rb
+++ b/spec/policies/protected_branch_policy_spec.rb
@@ -10,15 +10,47 @@ RSpec.describe ProtectedBranchPolicy do
subject { described_class.new(user, protected_branch) }
- it 'branches can be updated via project maintainers' do
- project.add_maintainer(user)
+ context 'as maintainers' do
+ before do
+ project.add_maintainer(user)
+ end
- is_expected.to be_allowed(:update_protected_branch)
+ it 'can be read' do
+ is_expected.to be_allowed(:read_protected_branch)
+ end
+
+ it 'can be created' do
+ is_expected.to be_allowed(:create_protected_branch)
+ end
+
+ it 'can be updated' do
+ is_expected.to be_allowed(:update_protected_branch)
+ end
+
+ it 'can be destroyed' do
+ is_expected.to be_allowed(:destroy_protected_branch)
+ end
end
- it "branches can't be updated by guests" do
- project.add_guest(user)
+ context 'as guests' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'can be read' do
+ is_expected.to be_disallowed(:read_protected_branch)
+ end
+
+ it 'can be created' do
+ is_expected.to be_disallowed(:create_protected_branch)
+ end
+
+ it 'can be updated' do
+ is_expected.to be_disallowed(:update_protected_branch)
+ end
- is_expected.to be_disallowed(:update_protected_branch)
+ it 'cannot be destroyed' do
+ is_expected.to be_disallowed(:destroy_protected_branch)
+ end
end
end
diff --git a/spec/policies/terraform/state_policy_spec.rb b/spec/policies/terraform/state_policy_spec.rb
index 82152920997..d75e20a2c66 100644
--- a/spec/policies/terraform/state_policy_spec.rb
+++ b/spec/policies/terraform/state_policy_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Terraform::StatePolicy do
let_it_be(:project) { create(:project) }
- let_it_be(:terraform_state) { create(:terraform_state, project: project)}
+ let_it_be(:terraform_state) { create(:terraform_state, project: project) }
subject { described_class.new(user, terraform_state) }
diff --git a/spec/policies/terraform/state_version_policy_spec.rb b/spec/policies/terraform/state_version_policy_spec.rb
index 6614e073332..4d41dd44455 100644
--- a/spec/policies/terraform/state_version_policy_spec.rb
+++ b/spec/policies/terraform/state_version_policy_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Terraform::StateVersionPolicy do
let_it_be(:project) { create(:project) }
- let_it_be(:terraform_state) { create(:terraform_state, :with_version, project: project)}
+ let_it_be(:terraform_state) { create(:terraform_state, :with_version, project: project) }
subject { described_class.new(user, terraform_state.latest_version) }