diff --git a/ee/spec/policies/ci/build_policy_spec.rb b/ee/spec/policies/ci/build_policy_spec.rb index c893f4fed16ec832fb5a5860f71ddfe816c21e28..cb1f576dfa789eeb564c5359d0063e43c873d4b8 100644 --- a/ee/spec/policies/ci/build_policy_spec.rb +++ b/ee/spec/policies/ci/build_policy_spec.rb @@ -148,15 +148,5 @@ describe Ci::BuildPolicy do it_behaves_like 'forbidden access' end end - - def expect_allowed(*permissions) - permissions.each { |p| is_expected.to be_allowed(p) } - end - - def expect_disallowed(*permissions) - permissions.each do |p| - is_expected.not_to be_allowed(p) - end - end end end diff --git a/ee/spec/policies/group_policy_spec.rb b/ee/spec/policies/group_policy_spec.rb index bc5aae8f6e03556074fe9b257cf936a014523e24..18340c8a9059f81ddc030f4853a6a6e962923b5b 100644 --- a/ee/spec/policies/group_policy_spec.rb +++ b/ee/spec/policies/group_policy_spec.rb @@ -1,24 +1,7 @@ require 'spec_helper' describe GroupPolicy do - let(:guest) { create(:user) } - let(:reporter) { create(:user) } - let(:developer) { create(:user) } - let(:maintainer) { create(:user) } - let(:owner) { create(:user) } - let(:auditor) { create(:user, :auditor) } - let(:admin) { create(:admin) } - let(:group) { create(:group) } - - before do - group.add_guest(guest) - group.add_reporter(reporter) - group.add_developer(developer) - group.add_maintainer(maintainer) - group.add_owner(owner) - end - - subject { described_class.new(current_user, group) } + include_context 'GroupPolicy context' context 'when epics feature is disabled' do let(:current_user) { owner } @@ -406,8 +389,6 @@ describe GroupPolicy do stub_licensed_features(security_dashboard: true) end - subject { described_class.new(current_user, group) } - context 'with admin' do let(:current_user) { admin } @@ -465,9 +446,39 @@ describe GroupPolicy do end end + describe 'private nested group use the highest access level from the group and inherited permissions', :nested_groups do + let(:nested_group) { create(:group, :private, parent: group) } + + before do + nested_group.add_guest(guest) + nested_group.add_guest(reporter) + nested_group.add_guest(developer) + nested_group.add_guest(maintainer) + + group.owners.destroy_all # rubocop: disable DestroyAll + + group.add_guest(owner) + nested_group.add_owner(owner) + end + + subject { described_class.new(current_user, nested_group) } + + context 'auditor' do + let(:current_user) { create(:user, :auditor) } + + it do + expect_allowed(:read_group) + expect_disallowed(:upload_file) + expect_disallowed(*reporter_permissions) + expect_disallowed(*developer_permissions) + expect_disallowed(*maintainer_permissions) + expect_disallowed(*owner_permissions) + end + end + end + it_behaves_like 'ee clusterable policies' do let(:clusterable) { create(:group) } - let(:cluster) do create(:cluster, :provided_by_gcp, diff --git a/ee/spec/policies/namespace_policy_spec.rb b/ee/spec/policies/namespace_policy_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..686f357dbb3346d4d023c17fe6876db872f1f172 --- /dev/null +++ b/ee/spec/policies/namespace_policy_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe NamespacePolicy do + let(:owner) { create(:user) } + let(:namespace) { create(:namespace, owner: owner) } + let(:owner_permissions) { [:create_projects, :admin_namespace, :read_namespace] } + + subject { described_class.new(current_user, namespace) } + + context 'auditor' do + let(:current_user) { create(:user, :auditor) } + + context 'owner' do + let(:namespace) { create(:namespace, owner: current_user) } + + it { is_expected.to be_allowed(*owner_permissions) } + end + + context 'non-owner' do + it { is_expected.to be_disallowed(*owner_permissions) } + end + end +end diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb index f4d70355afdf724d8ea32297611499bd8a5cceb5..6279741a675eef11e9916170884e018af801957e 100644 --- a/ee/spec/policies/project_policy_spec.rb +++ b/ee/spec/policies/project_policy_spec.rb @@ -11,19 +11,94 @@ describe ProjectPolicy do set(:guest) { create(:user) } let(:project) { create(:project, :public, namespace: owner.namespace) } + subject { described_class.new(current_user, project) } + before do project.add_maintainer(maintainer) project.add_developer(developer) project.add_reporter(reporter) project.add_guest(guest) + stub_licensed_features(license_management: true) + end + + context 'basic permissions' do + include_context 'ProjectPolicy context' + + let(:additional_guest_permissions) do + %i[read_issue_link read_vulnerability_feedback read_software_license_policy] + end + let(:additional_reporter_permissions) { [:admin_issue_link] } + let(:additional_developer_permissions) { %i[admin_vulnerability_feedback read_project_security_dashboard read_feature_flag] } + let(:additional_maintainer_permissions) { %i[push_code_to_protected_branches] } + let(:auditor_permissions) do + %i[ + download_code download_wiki_code read_project read_board read_list + read_project_for_iids read_issue_iid read_merge_request_iid read_wiki + read_issue read_label read_issue_link read_milestone read_release + read_project_snippet read_project_member read_note read_cycle_analytics + read_pipeline read_build read_commit_status read_container_image + read_environment read_deployment read_merge_request read_pages + create_merge_request_in award_emoji + read_vulnerability_feedback read_software_license_policy + ] + end + + it_behaves_like 'project policies as anonymous' + it_behaves_like 'project policies as guest' + it_behaves_like 'project policies as reporter' + it_behaves_like 'project policies as developer' + it_behaves_like 'project policies as maintainer' + it_behaves_like 'project policies as owner' + it_behaves_like 'project policies as admin' + + context 'auditor' do + let(:current_user) { create(:user, :auditor) } + + context 'who is not a team member' do + it do + is_expected.to be_disallowed(*developer_permissions) + is_expected.to be_disallowed(*maintainer_permissions) + is_expected.to be_disallowed(*owner_permissions) + is_expected.to be_disallowed(*(guest_permissions - auditor_permissions)) + is_expected.to be_allowed(*auditor_permissions) + end + end + + context 'who is a team member' do + before do + project.add_guest(current_user) + end + + it do + is_expected.to be_disallowed(*developer_permissions) + is_expected.to be_disallowed(*maintainer_permissions) + is_expected.to be_disallowed(*owner_permissions) + is_expected.to be_allowed(*(guest_permissions - auditor_permissions)) + is_expected.to be_allowed(*auditor_permissions) + end + end + end + end + + context 'issues feature' do + subject { described_class.new(owner, project) } + + context 'when the feature is disabled' do + before do + project.issues_enabled = false + project.save! + end + + it 'disables boards permissions' do + expect_disallowed :admin_board + end + end end context 'admin_mirror' do context 'with remote mirror setting enabled' do context 'with admin' do - subject do - described_class.new(admin, project) - end + let(:current_user) { admin } it do is_expected.to be_allowed(:admin_mirror) @@ -31,9 +106,7 @@ describe ProjectPolicy do end context 'with owner' do - subject do - described_class.new(owner, project) - end + let(:current_user) { owner } it do is_expected.to be_allowed(:admin_mirror) @@ -41,9 +114,7 @@ describe ProjectPolicy do end context 'with developer' do - subject do - described_class.new(developer, project) - end + let(:current_user) { developer } it do is_expected.to be_disallowed(:admin_mirror) @@ -57,9 +128,7 @@ describe ProjectPolicy do end context 'with admin' do - subject do - described_class.new(admin, project) - end + let(:current_user) { admin } it do is_expected.to be_allowed(:admin_mirror) @@ -67,9 +136,7 @@ describe ProjectPolicy do end context 'with owner' do - subject do - described_class.new(owner, project) - end + let(:current_user) { owner } it do is_expected.to be_disallowed(:admin_mirror) @@ -83,9 +150,7 @@ describe ProjectPolicy do end context 'with admin' do - subject do - described_class.new(admin, project) - end + let(:current_user) { admin } it do is_expected.to be_disallowed(:admin_mirror) @@ -93,9 +158,7 @@ describe ProjectPolicy do end context 'with owner' do - subject do - described_class.new(owner, project) - end + let(:current_user) { owner } it do is_expected.to be_disallowed(:admin_mirror) @@ -109,9 +172,7 @@ describe ProjectPolicy do end context 'with admin' do - subject do - described_class.new(admin, project) - end + let(:current_user) { admin } it do is_expected.to be_allowed(:admin_mirror) @@ -119,9 +180,7 @@ describe ProjectPolicy do end context 'with owner' do - subject do - described_class.new(owner, project) - end + let(:current_user) { owner } it do is_expected.to be_allowed(:admin_mirror) @@ -190,14 +249,6 @@ describe ProjectPolicy do end describe 'read_vulnerability_feedback' do - subject { described_class.new(current_user, project) } - - context 'with public project' do - let(:current_user) { nil } - - it { is_expected.to be_allowed(:read_vulnerability_feedback) } - end - context 'with private project' do let(:current_user) { admin } let(:project) { create(:project, :private, namespace: owner.namespace) } @@ -252,88 +303,10 @@ describe ProjectPolicy do end end - describe 'admin_vulnerability_feedback' do - subject { described_class.new(current_user, project) } - - context 'with admin' do - let(:current_user) { admin } - - it { is_expected.to be_allowed(:admin_vulnerability_feedback) } - end - - context 'with owner' do - let(:current_user) { owner } - - it { is_expected.to be_allowed(:admin_vulnerability_feedback) } - end - - context 'with maintainer' do - let(:current_user) { maintainer } - - it { is_expected.to be_allowed(:admin_vulnerability_feedback) } - end - - context 'with developer' do - let(:current_user) { developer } - - it { is_expected.to be_allowed(:admin_vulnerability_feedback) } - end - - context 'with reporter' do - let(:current_user) { reporter } - - it { is_expected.to be_disallowed(:admin_vulnerability_feedback) } - end - - context 'with guest' do - let(:current_user) { guest } - - it { is_expected.to be_disallowed(:admin_vulnerability_feedback) } - end - - context 'with non member' do - let(:current_user) { create(:user) } - - it { is_expected.to be_disallowed(:admin_vulnerability_feedback) } - end - - context 'with anonymous' do - let(:current_user) { nil } - - it { is_expected.to be_disallowed(:admin_vulnerability_feedback) } - end - end - describe 'read_project_security_dashboard' do - before do - stub_licensed_features(security_dashboard: true) - end - - subject { described_class.new(current_user, project) } - - context 'with admin' do - let(:current_user) { admin } - - it { is_expected.to be_allowed(:read_project_security_dashboard) } - end - - context 'with owner' do - let(:current_user) { owner } - - it { is_expected.to be_allowed(:read_project_security_dashboard) } - end - - context 'with maintainer' do - let(:current_user) { maintainer } - - it { is_expected.to be_allowed(:read_project_security_dashboard) } - end - context 'with developer' do let(:current_user) { developer } - it { is_expected.to be_allowed(:read_project_security_dashboard) } - context 'when security dashboard features is not available' do before do stub_licensed_features(security_dashboard: false) @@ -342,35 +315,9 @@ describe ProjectPolicy do it { is_expected.to be_disallowed(:read_project_security_dashboard) } end end - - context 'with reporter' do - let(:current_user) { reporter } - - it { is_expected.to be_disallowed(:read_project_security_dashboard) } - end - - context 'with guest' do - let(:current_user) { guest } - - it { is_expected.to be_disallowed(:read_project_security_dashboard) } - end - - context 'with non member' do - let(:current_user) { create(:user) } - - it { is_expected.to be_disallowed(:read_project_security_dashboard) } - end - - context 'with anonymous' do - let(:current_user) { nil } - - it { is_expected.to be_disallowed(:read_project_security_dashboard) } - end end describe 'read_package' do - subject { described_class.new(current_user, project) } - context 'with admin' do let(:current_user) { admin } @@ -429,17 +376,9 @@ describe ProjectPolicy do end describe 'read_feature_flag' do - before do - stub_licensed_features(feature_flags: true) - end - - subject { described_class.new(current_user, project) } - context 'with admin' do let(:current_user) { admin } - it { is_expected.to be_allowed(:read_feature_flag) } - context 'when repository is disabled' do before do project.project_feature.update(repository_access_level: ProjectFeature::DISABLED) @@ -449,23 +388,9 @@ describe ProjectPolicy do end end - context 'with owner' do - let(:current_user) { owner } - - it { is_expected.to be_allowed(:read_feature_flag) } - end - - context 'with maintainer' do - let(:current_user) { maintainer } - - it { is_expected.to be_allowed(:read_feature_flag) } - end - context 'with developer' do let(:current_user) { developer } - it { is_expected.to be_allowed(:read_feature_flag) } - context 'when feature flags features is not available' do before do stub_licensed_features(feature_flags: false) @@ -474,39 +399,9 @@ describe ProjectPolicy do it { is_expected.to be_disallowed(:read_feature_flag) } end end - - context 'with reporter' do - let(:current_user) { reporter } - - it { is_expected.to be_disallowed(:read_feature_flag) } - end - - context 'with guest' do - let(:current_user) { guest } - - it { is_expected.to be_disallowed(:read_feature_flag) } - end - - context 'with non member' do - let(:current_user) { create(:user) } - - it { is_expected.to be_disallowed(:read_feature_flag) } - end - - context 'with anonymous' do - let(:current_user) { nil } - - it { is_expected.to be_disallowed(:read_feature_flag) } - end end describe 'admin_license_management' do - before do - stub_licensed_features(license_management: true) - end - - subject { described_class.new(current_user, project) } - context 'without license management feature available' do before do stub_licensed_features(license_management: false) @@ -567,12 +462,6 @@ describe ProjectPolicy do end describe 'read_license_management' do - before do - stub_licensed_features(license_management: true) - end - - subject { described_class.new(current_user, project) } - context 'without license management feature available' do before do stub_licensed_features(license_management: false) @@ -582,54 +471,6 @@ describe ProjectPolicy do it { is_expected.to be_disallowed(:read_software_license_policy) } end - - context 'with admin' do - let(:current_user) { admin } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end - - context 'with owner' do - let(:current_user) { owner } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end - - context 'with maintainer' do - let(:current_user) { maintainer } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end - - context 'with developer' do - let(:current_user) { developer } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end - - context 'with reporter' do - let(:current_user) { reporter } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end - - context 'with guest' do - let(:current_user) { guest } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end - - context 'with non member' do - let(:current_user) { create(:user) } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end - - context 'with anonymous' do - let(:current_user) { nil } - - it { is_expected.to be_allowed(:read_software_license_policy) } - end end describe 'create_web_ide_terminal' do @@ -637,8 +478,6 @@ describe ProjectPolicy do stub_licensed_features(web_ide_terminal: true) end - subject { described_class.new(current_user, project) } - context 'without ide terminal feature available' do before do stub_licensed_features(web_ide_terminal: false) diff --git a/ee/spec/policies/project_snippet_policy_spec.rb b/ee/spec/policies/project_snippet_policy_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f20e391ec44b0f92a41e4c57b09f0190bb5ffe67 --- /dev/null +++ b/ee/spec/policies/project_snippet_policy_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# Snippet visibility scenarios are included in more details in spec/support/snippet_visibility.rb +describe ProjectSnippetPolicy do + let(:project) { create(:project, :public) } + let(:snippet) { create(:project_snippet, snippet_visibility, project: project) } + let(:author_permissions) do + [ + :update_project_snippet, + :admin_project_snippet + ] + end + + subject { described_class.new(current_user, snippet) } + + context 'private snippet' do + let(:snippet_visibility) { :private } + + context 'auditor user' do + let(:current_user) { create(:user, :auditor) } + + it do + is_expected.to be_allowed(:read_project_snippet) + is_expected.to be_disallowed(*author_permissions) + end + end + end +end diff --git a/spec/policies/board_policy_spec.rb b/spec/policies/board_policy_spec.rb index 4b76d65ef690f7bd7398441a009aa8cd38c38cd4..52c23951e37ba76a075adca9f8da7f5cc275cefe 100644 --- a/spec/policies/board_policy_spec.rb +++ b/spec/policies/board_policy_spec.rb @@ -17,14 +17,6 @@ describe BoardPolicy do ] end - def expect_allowed(*permissions) - permissions.each { |p| is_expected.to be_allowed(p) } - end - - def expect_disallowed(*permissions) - permissions.each { |p| is_expected.not_to be_allowed(p) } - end - context 'group board' do subject { described_class.new(user, group_board) } diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb index 74da8e500745ed98cb069a88a51372a0f92ba367..dc98baca6dc8fbc62360eec9061bd9811027a5d5 100644 --- a/spec/policies/group_policy_spec.rb +++ b/spec/policies/group_policy_spec.rb @@ -1,64 +1,7 @@ require 'spec_helper' describe GroupPolicy do - let(:guest) { create(:user) } - let(:reporter) { create(:user) } - let(:developer) { create(:user) } - let(:maintainer) { create(:user) } - let(:owner) { create(:user) } - let(:auditor) { create(:user, :auditor) } - let(:admin) { create(:admin) } - let(:group) { create(:group, :private) } - - let(:guest_permissions) do - [:read_label, :read_group, :upload_file, :read_namespace, :read_group_activity, - :read_group_issues, :read_group_boards, :read_group_labels, :read_group_milestones, - :read_group_merge_requests] - end - - let(:reporter_permissions) { [:admin_label] } - - let(:developer_permissions) { [:admin_milestone] } - - let(:maintainer_permissions) do - [ - :create_projects, - :read_cluster, - :create_cluster, - :update_cluster, - :admin_cluster, - :add_cluster - ] - end - - let(:owner_permissions) do - [ - :admin_group, - :admin_namespace, - :admin_group_member, - :change_visibility_level, - :set_note_created_at, - (Gitlab::Database.postgresql? ? :create_subgroup : nil) - ].compact - end - - before do - group.add_guest(guest) - group.add_reporter(reporter) - group.add_developer(developer) - group.add_maintainer(maintainer) - group.add_owner(owner) - end - - subject { described_class.new(current_user, group) } - - def expect_allowed(*permissions) - permissions.each { |p| is_expected.to be_allowed(p) } - end - - def expect_disallowed(*permissions) - permissions.each { |p| is_expected.not_to be_allowed(p) } - end + include_context 'GroupPolicy context' context 'with no user' do let(:group) { create(:group, :public) } @@ -312,107 +255,6 @@ describe GroupPolicy do expect_allowed(*owner_permissions) end end - - context 'auditor' do - let(:current_user) { auditor } - - it do - expect_allowed(:read_group) - expect_disallowed(:upload_file) - is_expected.to be_disallowed(*maintainer_permissions) - is_expected.to be_disallowed(*owner_permissions) - end - end - end - - describe 'change_share_with_group_lock' do - context 'when the current_user owns the group' do - let(:current_user) { owner } - - context 'when the group share_with_group_lock is enabled' do - let(:group) { create(:group, share_with_group_lock: true, parent: parent) } - - context 'when the parent group share_with_group_lock is enabled' do - context 'when the group has a grandparent' do - let(:parent) { create(:group, share_with_group_lock: true, parent: grandparent) } - - context 'when the grandparent share_with_group_lock is enabled' do - let(:grandparent) { create(:group, share_with_group_lock: true) } - - context 'when the current_user owns the parent' do - before do - parent.add_owner(current_user) - end - - context 'when the current_user owns the grandparent' do - before do - grandparent.add_owner(current_user) - end - - it { expect_allowed(:change_share_with_group_lock) } - end - - context 'when the current_user does not own the grandparent' do - it { expect_disallowed(:change_share_with_group_lock) } - end - end - - context 'when the current_user does not own the parent' do - it { expect_disallowed(:change_share_with_group_lock) } - end - end - - context 'when the grandparent share_with_group_lock is disabled' do - let(:grandparent) { create(:group) } - - context 'when the current_user owns the parent' do - before do - parent.add_owner(current_user) - end - - it { expect_allowed(:change_share_with_group_lock) } - end - - context 'when the current_user does not own the parent' do - it { expect_disallowed(:change_share_with_group_lock) } - end - end - end - - context 'when the group does not have a grandparent' do - let(:parent) { create(:group, share_with_group_lock: true) } - - context 'when the current_user owns the parent' do - before do - parent.add_owner(current_user) - end - - it { expect_allowed(:change_share_with_group_lock) } - end - - context 'when the current_user does not own the parent' do - it { expect_disallowed(:change_share_with_group_lock) } - end - end - end - - context 'when the parent group share_with_group_lock is disabled' do - let(:parent) { create(:group) } - - it { expect_allowed(:change_share_with_group_lock) } - end - end - - context 'when the group share_with_group_lock is disabled' do - it { expect_allowed(:change_share_with_group_lock) } - end - end - - context 'when the current_user does not own the group' do - let(:current_user) { create(:user) } - - it { expect_disallowed(:change_share_with_group_lock) } - end end describe 'change_share_with_group_lock' do diff --git a/spec/policies/namespace_policy_spec.rb b/spec/policies/namespace_policy_spec.rb index a7aaeed9ac870d7f559ad9b766992d9bdf55341d..99fa8b1fe440ec2dc6eb67cb66d278e16cd95246 100644 --- a/spec/policies/namespace_policy_spec.rb +++ b/spec/policies/namespace_policy_spec.rb @@ -3,7 +3,6 @@ require 'spec_helper' describe NamespacePolicy do let(:user) { create(:user) } let(:owner) { create(:user) } - let(:auditor) { create(:user, :auditor) } let(:admin) { create(:admin) } let(:namespace) { create(:namespace, owner: owner) } @@ -35,20 +34,6 @@ describe NamespacePolicy do end end - context 'auditor' do - let(:current_user) { auditor } - - context 'owner' do - let(:namespace) { create(:namespace, owner: auditor) } - - it { is_expected.to be_allowed(*owner_permissions) } - end - - context 'non-owner' do - it { is_expected.to be_disallowed(*owner_permissions) } - end - end - context 'admin' do let(:current_user) { admin } diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index f1cc9694bb3cf6ff2436542788f531da042cbd11..726ccba8807b7719a23c4dcbf58d6c5a1b550fd5 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -1,96 +1,7 @@ require 'spec_helper' describe ProjectPolicy do - set(:guest) { create(:user) } - set(:reporter) { create(:user) } - set(:developer) { create(:user) } - set(:maintainer) { create(:user) } - set(:owner) { create(:user) } - set(:admin) { create(:admin) } - let(:project) { create(:project, :public, namespace: owner.namespace) } - - let(:base_guest_permissions) do - %i[ - read_project read_board read_list read_wiki read_issue - read_project_for_iids read_issue_iid read_label - read_milestone read_project_snippet read_project_member read_note - create_project create_issue create_note upload_file create_merge_request_in - award_emoji read_release - ] - end - - let(:base_reporter_permissions) do - %i[ - download_code fork_project create_project_snippet update_issue - admin_issue admin_label admin_list read_commit_status read_build - read_container_image read_pipeline read_environment read_deployment - read_merge_request download_wiki_code read_sentry_issue - ] - end - - let(:team_member_reporter_permissions) do - %i[build_download_code build_read_container_image] - end - - let(:developer_permissions) do - %i[ - admin_milestone admin_merge_request update_merge_request create_commit_status - update_commit_status create_build update_build create_pipeline - update_pipeline create_merge_request_from create_wiki push_code - resolve_note create_container_image update_container_image - create_environment create_deployment create_release update_release - ] - end - - let(:base_maintainer_permissions) do - %i[ - push_to_delete_protected_branch update_project_snippet update_environment - update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project - admin_commit_status admin_build admin_container_image - admin_pipeline admin_environment admin_deployment destroy_release add_cluster - daily_statistics - ] - end - - let(:public_permissions) do - %i[ - download_code fork_project read_commit_status read_pipeline - read_container_image build_download_code build_read_container_image - download_wiki_code read_release - ] - end - - let(:owner_permissions) do - %i[ - change_namespace change_visibility_level rename_project remove_project - archive_project remove_fork_project destroy_merge_request destroy_issue - set_issue_iid set_issue_created_at set_note_created_at - ] - end - - # Used in EE specs - let(:additional_guest_permissions) { [] } - let(:additional_reporter_permissions) { [] } - let(:additional_maintainer_permissions) { [] } - - let(:guest_permissions) { base_guest_permissions + additional_guest_permissions } - let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions } - let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions } - - before do - project.add_guest(guest) - project.add_maintainer(maintainer) - project.add_developer(developer) - project.add_reporter(reporter) - end - - def expect_allowed(*permissions) - permissions.each { |p| is_expected.to be_allowed(p) } - end - - def expect_disallowed(*permissions) - permissions.each { |p| is_expected.not_to be_allowed(p) } - end + include_context 'ProjectPolicy context' it 'does not include the read_issue permission when the issue author is not a member of the private project' do project = create(:project, :private) @@ -140,7 +51,7 @@ describe ProjectPolicy do end it 'disables boards and lists permissions' do - expect_disallowed :read_board, :create_board, :update_board, :admin_board + expect_disallowed :read_board, :create_board, :update_board expect_disallowed :read_list, :create_list, :update_list, :admin_list end @@ -237,236 +148,6 @@ describe ProjectPolicy do end end - shared_examples 'archived project policies' do - let(:feature_write_abilities) do - described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature| - described_class.create_update_admin_destroy(feature) - end + additional_reporter_permissions + additional_maintainer_permissions - end - - let(:other_write_abilities) do - %i[ - create_merge_request_in - create_merge_request_from - push_to_delete_protected_branch - push_code - request_access - upload_file - resolve_note - award_emoji - ] - end - - context 'when the project is archived' do - before do - project.archived = true - end - - it 'disables write actions on all relevant project features' do - expect_disallowed(*feature_write_abilities) - end - - it 'disables some other important write actions' do - expect_disallowed(*other_write_abilities) - end - - it 'does not disable other abilities' do - expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities)) - end - end - end - - shared_examples 'project policies as anonymous' do - context 'abilities for public projects' do - context 'when a project has pending invites' do - let(:group) { create(:group, :public) } - let(:project) { create(:project, :public, namespace: group) } - let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] } - let(:anonymous_permissions) { guest_permissions - user_permissions } - - subject { described_class.new(nil, project) } - - before do - create(:group_member, :invited, group: group) - end - - it 'does not grant owner access' do - expect_allowed(*anonymous_permissions) - expect_disallowed(*user_permissions) - end - - it_behaves_like 'archived project policies' do - let(:regular_abilities) { anonymous_permissions } - end - end - end - - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } - - subject { described_class.new(nil, project) } - - it { is_expected.to be_banned } - end - end - - shared_examples 'project policies as guest' do - subject { described_class.new(guest, project) } - - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } - let(:reporter_public_build_permissions) do - reporter_permissions - [:read_build, :read_pipeline] - end - - it do - expect_allowed(*guest_permissions) - expect_disallowed(*reporter_public_build_permissions) - expect_disallowed(*team_member_reporter_permissions) - expect_disallowed(*developer_permissions) - expect_disallowed(*maintainer_permissions) - expect_disallowed(*owner_permissions) - end - - it_behaves_like 'archived project policies' do - let(:regular_abilities) { guest_permissions } - end - - context 'public builds enabled' do - it do - expect_allowed(*guest_permissions) - expect_allowed(:read_build, :read_pipeline) - end - end - - context 'when public builds disabled' do - before do - project.update(public_builds: false) - end - - it do - expect_allowed(*guest_permissions) - expect_disallowed(:read_build, :read_pipeline) - end - end - - context 'when builds are disabled' do - before do - project.project_feature.update(builds_access_level: ProjectFeature::DISABLED) - end - - it do - expect_disallowed(:read_build) - expect_allowed(:read_pipeline) - end - end - end - end - - shared_examples 'project policies as reporter' do - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } - - subject { described_class.new(reporter, project) } - - it do - expect_allowed(*guest_permissions) - expect_allowed(*reporter_permissions) - expect_allowed(*team_member_reporter_permissions) - expect_disallowed(*developer_permissions) - expect_disallowed(*maintainer_permissions) - expect_disallowed(*owner_permissions) - end - - it_behaves_like 'archived project policies' do - let(:regular_abilities) { reporter_permissions } - end - end - end - - shared_examples 'project policies as developer' do - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } - subject { described_class.new(developer, project) } - - it do - expect_allowed(*guest_permissions) - expect_allowed(*reporter_permissions) - expect_allowed(*team_member_reporter_permissions) - expect_allowed(*developer_permissions) - expect_disallowed(*maintainer_permissions) - expect_disallowed(*owner_permissions) - end - - it_behaves_like 'archived project policies' do - let(:regular_abilities) { developer_permissions } - end - end - end - - shared_examples 'project policies as maintainer' do - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } - - subject { described_class.new(maintainer, project) } - - it do - expect_allowed(*guest_permissions) - expect_allowed(*reporter_permissions) - expect_allowed(*team_member_reporter_permissions) - expect_allowed(*developer_permissions) - expect_allowed(*maintainer_permissions) - expect_disallowed(*owner_permissions) - end - - it_behaves_like 'archived project policies' do - let(:regular_abilities) { maintainer_permissions } - end - end - end - - shared_examples 'project policies as owner' do - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } - - subject { described_class.new(owner, project) } - - it do - expect_allowed(*guest_permissions) - expect_allowed(*reporter_permissions) - expect_allowed(*team_member_reporter_permissions) - expect_allowed(*developer_permissions) - expect_allowed(*maintainer_permissions) - expect_allowed(*owner_permissions) - end - - it_behaves_like 'archived project policies' do - let(:regular_abilities) { owner_permissions } - end - end - end - - shared_examples 'project policies as admin' do - context 'abilities for non-public projects' do - let(:project) { create(:project, namespace: owner.namespace) } - - subject { described_class.new(admin, project) } - - it do - expect_allowed(*guest_permissions) - expect_allowed(*reporter_permissions) - expect_disallowed(*team_member_reporter_permissions) - expect_allowed(*developer_permissions) - expect_allowed(*maintainer_permissions) - expect_allowed(*owner_permissions) - end - - it_behaves_like 'archived project policies' do - let(:regular_abilities) { owner_permissions } - end - end - end - it_behaves_like 'project policies as anonymous' it_behaves_like 'project policies as guest' it_behaves_like 'project policies as reporter' @@ -475,61 +156,6 @@ describe ProjectPolicy do it_behaves_like 'project policies as owner' it_behaves_like 'project policies as admin' - context 'EE' do - let(:additional_guest_permissions) { [:read_issue_link] } - let(:additional_reporter_permissions) { [:admin_issue_link]} - let(:additional_maintainer_permissions) { [:push_code_to_protected_branches] } - let(:auditor_permissions) do - %i[ - download_code download_wiki_code read_project read_board read_list - read_project_for_iids read_issue_iid read_merge_request_iid read_wiki - read_issue read_label read_issue_link read_milestone read_release - read_project_snippet read_project_member read_note read_cycle_analytics - read_pipeline read_build read_commit_status read_container_image - read_environment read_deployment read_merge_request read_pages - create_merge_request_in award_emoji - ] - end - - it_behaves_like 'project policies as anonymous' - it_behaves_like 'project policies as guest' - it_behaves_like 'project policies as reporter' - it_behaves_like 'project policies as developer' - it_behaves_like 'project policies as maintainer' - it_behaves_like 'project policies as owner' - it_behaves_like 'project policies as admin' - - context 'auditor' do - let(:auditor) { create(:user, :auditor) } - - subject { described_class.new(auditor, project) } - - context 'who is not a team member' do - it do - is_expected.to be_disallowed(*developer_permissions) - is_expected.to be_disallowed(*maintainer_permissions) - is_expected.to be_disallowed(*owner_permissions) - is_expected.to be_disallowed(*(guest_permissions - auditor_permissions)) - is_expected.to be_allowed(*auditor_permissions) - end - end - - context 'who is a team member' do - before do - project.add_guest(auditor) - end - - it do - is_expected.to be_disallowed(*developer_permissions) - is_expected.to be_disallowed(*maintainer_permissions) - is_expected.to be_disallowed(*owner_permissions) - is_expected.to be_allowed(*(guest_permissions - auditor_permissions)) - is_expected.to be_allowed(*auditor_permissions) - end - end - end - end - context 'when a public project has merge requests allowing access' do include ProjectForksHelper let(:user) { create(:user) } diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb index 05dba1413f2bf9b02dfbf38f48fac11b4bc5676c..2e9ef1e89fde986eab79623dcdf60f23f254af14 100644 --- a/spec/policies/project_snippet_policy_spec.rb +++ b/spec/policies/project_snippet_policy_spec.rb @@ -5,7 +5,7 @@ describe ProjectSnippetPolicy do let(:regular_user) { create(:user) } let(:external_user) { create(:user, :external) } let(:project) { create(:project, :public) } - + let(:snippet) { create(:project_snippet, snippet_visibility, project: project) } let(:author_permissions) do [ :update_project_snippet, @@ -13,23 +13,13 @@ describe ProjectSnippetPolicy do ] end - def abilities(user, snippet_visibility) - snippet = create(:project_snippet, snippet_visibility, project: project) - - described_class.new(user, snippet) - end - - def expect_allowed(*permissions) - permissions.each { |p| is_expected.to be_allowed(p) } - end - - def expect_disallowed(*permissions) - permissions.each { |p| is_expected.not_to be_allowed(p) } - end + subject { described_class.new(current_user, snippet) } context 'public snippet' do + let(:snippet_visibility) { :public } + context 'no user' do - subject { abilities(nil, :public) } + let(:current_user) { nil } it do expect_allowed(:read_project_snippet) @@ -38,7 +28,7 @@ describe ProjectSnippetPolicy do end context 'regular user' do - subject { abilities(regular_user, :public) } + let(:current_user) { regular_user } it do expect_allowed(:read_project_snippet, :create_note) @@ -47,7 +37,7 @@ describe ProjectSnippetPolicy do end context 'external user' do - subject { abilities(external_user, :public) } + let(:current_user) { external_user } it do expect_allowed(:read_project_snippet, :create_note) @@ -57,8 +47,10 @@ describe ProjectSnippetPolicy do end context 'internal snippet' do + let(:snippet_visibility) { :internal } + context 'no user' do - subject { abilities(nil, :internal) } + let(:current_user) { nil } it do expect_disallowed(:read_project_snippet) @@ -67,7 +59,7 @@ describe ProjectSnippetPolicy do end context 'regular user' do - subject { abilities(regular_user, :internal) } + let(:current_user) { regular_user } it do expect_allowed(:read_project_snippet, :create_note) @@ -76,41 +68,31 @@ describe ProjectSnippetPolicy do end context 'external user' do - subject { abilities(external_user, :internal) } + let(:current_user) { external_user } it do expect_disallowed(:read_project_snippet, :create_note) expect_disallowed(*author_permissions) end - end - - context 'project team member external user' do - subject { abilities(external_user, :internal) } - - before do - project.add_developer(external_user) - end - - it do - expect_allowed(:read_project_snippet, :create_note) - expect_disallowed(*author_permissions) - end - end - context 'external user' do - let(:current_user) { create(:user, :external) } - subject { abilities(current_user, :private) } + context 'project team member' do + before do + project.add_developer(external_user) + end - it do - is_expected.to be_disallowed(:read_project_snippet) - is_expected.to be_disallowed(*author_permissions) + it do + expect_allowed(:read_project_snippet, :create_note) + expect_disallowed(*author_permissions) + end end end end context 'private snippet' do + let(:snippet_visibility) { :private } + context 'no user' do - subject { abilities(nil, :private) } + let(:current_user) { nil } it do expect_disallowed(:read_project_snippet) @@ -119,63 +101,52 @@ describe ProjectSnippetPolicy do end context 'regular user' do - subject { abilities(regular_user, :private) } + let(:current_user) { regular_user } it do expect_disallowed(:read_project_snippet, :create_note) expect_disallowed(*author_permissions) end - end - - context 'snippet author' do - let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) } - subject { described_class.new(regular_user, snippet) } + context 'snippet author' do + let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) } - it do - expect_allowed(:read_project_snippet, :create_note) - expect_allowed(*author_permissions) + it do + expect_allowed(:read_project_snippet, :create_note) + expect_allowed(*author_permissions) + end end - end - context 'project team member normal user' do - subject { abilities(regular_user, :private) } + context 'project team member normal user' do + before do + project.add_developer(regular_user) + end - before do - project.add_developer(regular_user) - end - - it do - expect_allowed(:read_project_snippet, :create_note) - expect_disallowed(*author_permissions) + it do + expect_allowed(:read_project_snippet, :create_note) + expect_disallowed(*author_permissions) + end end end - context 'project team member external user' do - subject { abilities(external_user, :private) } - - before do - project.add_developer(external_user) - end - - it do - expect_allowed(:read_project_snippet, :create_note) - expect_disallowed(*author_permissions) - end - end + context 'external user' do + context 'project team member' do + let(:current_user) { external_user } - context 'auditor user' do - let(:current_user) { create(:user, :auditor) } - subject { abilities(current_user, :private) } + before do + project.add_developer(external_user) + end - it do - is_expected.to be_allowed(:read_project_snippet) - is_expected.to be_disallowed(*author_permissions) + it do + expect_allowed(:read_project_snippet, :create_note) + expect_disallowed(*author_permissions) + end end end context 'admin user' do - subject { abilities(create(:admin), :private) } + let(:snippet_visibility) { :private } + let(:current_user) { create(:admin) } it do expect_allowed(:read_project_snippet, :create_note) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 25d1327fcb9a5549da9668238217a51be65da518..0e121727a4fa21b977064c1e228619609a40506e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -98,6 +98,7 @@ RSpec.configure do |config| config.include MigrationsHelpers, :migration config.include RedisHelpers config.include Rails.application.routes.url_helpers, type: :routing + config.include PolicyHelpers, type: :policy if ENV['CI'] # This includes the first try, i.e. tests will be run 4 times before failing. diff --git a/spec/support/helpers/policy_helpers.rb b/spec/support/helpers/policy_helpers.rb new file mode 100644 index 0000000000000000000000000000000000000000..3d780eb5fb1c1a85512daa7b30e0a28510ddf75d --- /dev/null +++ b/spec/support/helpers/policy_helpers.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module PolicyHelpers + def expect_allowed(*permissions) + permissions.each { |p| is_expected.to be_allowed(p) } + end + + def expect_disallowed(*permissions) + permissions.each { |p| is_expected.not_to be_allowed(p) } + end +end diff --git a/spec/support/shared_context/policies/project_policy_shared_context.rb b/spec/support/shared_context/policies/project_policy_shared_context.rb new file mode 100644 index 0000000000000000000000000000000000000000..8bcd26ec0cd9def9a10989996c0e787879e73497 --- /dev/null +++ b/spec/support/shared_context/policies/project_policy_shared_context.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +RSpec.shared_context 'ProjectPolicy context' do + set(:guest) { create(:user) } + set(:reporter) { create(:user) } + set(:developer) { create(:user) } + set(:maintainer) { create(:user) } + set(:owner) { create(:user) } + set(:admin) { create(:admin) } + let(:project) { create(:project, :public, namespace: owner.namespace) } + + let(:base_guest_permissions) do + %i[ + read_project read_board read_list read_wiki read_issue + read_project_for_iids read_issue_iid read_label + read_milestone read_project_snippet read_project_member read_note + create_project create_issue create_note upload_file create_merge_request_in + award_emoji read_release + ] + end + + let(:base_reporter_permissions) do + %i[ + download_code fork_project create_project_snippet update_issue + admin_issue admin_label admin_list read_commit_status read_build + read_container_image read_pipeline read_environment read_deployment + read_merge_request download_wiki_code read_sentry_issue + ] + end + + let(:team_member_reporter_permissions) do + %i[build_download_code build_read_container_image] + end + + let(:developer_permissions) do + %i[ + admin_milestone admin_merge_request update_merge_request create_commit_status + update_commit_status create_build update_build create_pipeline + update_pipeline create_merge_request_from create_wiki push_code + resolve_note create_container_image update_container_image + create_environment create_deployment create_release update_release + ] + end + + let(:base_maintainer_permissions) do + %i[ + push_to_delete_protected_branch update_project_snippet update_environment + update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project + admin_commit_status admin_build admin_container_image + admin_pipeline admin_environment admin_deployment destroy_release add_cluster + daily_statistics + ] + end + + let(:public_permissions) do + %i[ + download_code fork_project read_commit_status read_pipeline + read_container_image build_download_code build_read_container_image + download_wiki_code read_release + ] + end + + let(:base_owner_permissions) do + %i[ + change_namespace change_visibility_level rename_project remove_project + archive_project remove_fork_project destroy_merge_request destroy_issue + set_issue_iid set_issue_created_at set_note_created_at + ] + end + + # Used in EE specs + let(:additional_guest_permissions) { [] } + let(:additional_reporter_permissions) { [] } + let(:additional_maintainer_permissions) { [] } + let(:additional_owner_permissions) { [] } + + let(:guest_permissions) { base_guest_permissions + additional_guest_permissions } + let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions } + let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions } + let(:owner_permissions) { base_owner_permissions + additional_owner_permissions } + + before do + project.add_guest(guest) + project.add_maintainer(maintainer) + project.add_developer(developer) + project.add_reporter(reporter) + end +end diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb new file mode 100644 index 0000000000000000000000000000000000000000..b4808ac006883567bdff2ea82e3474150c051483 --- /dev/null +++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +RSpec.shared_context 'GroupPolicy context' do + let(:guest) { create(:user) } + let(:reporter) { create(:user) } + let(:developer) { create(:user) } + let(:maintainer) { create(:user) } + let(:owner) { create(:user) } + let(:admin) { create(:admin) } + let(:group) { create(:group, :private) } + + let(:guest_permissions) do + %i[ + read_label read_group upload_file read_namespace read_group_activity + read_group_issues read_group_boards read_group_labels read_group_milestones + read_group_merge_requests + ] + end + let(:reporter_permissions) { [:admin_label] } + let(:developer_permissions) { [:admin_milestone] } + let(:maintainer_permissions) do + %i[ + create_projects + read_cluster create_cluster update_cluster admin_cluster add_cluster + ] + end + let(:owner_permissions) do + [ + :admin_group, + :admin_namespace, + :admin_group_member, + :change_visibility_level, + :set_note_created_at, + (Gitlab::Database.postgresql? ? :create_subgroup : nil) + ].compact + end + + before do + group.add_guest(guest) + group.add_reporter(reporter) + group.add_developer(developer) + group.add_maintainer(maintainer) + group.add_owner(owner) + end + + subject { described_class.new(current_user, group) } +end diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb new file mode 100644 index 0000000000000000000000000000000000000000..7a71e2ee370e0d57a014302d10091583333abad8 --- /dev/null +++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb @@ -0,0 +1,231 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'archived project policies' do + let(:feature_write_abilities) do + described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature| + described_class.create_update_admin_destroy(feature) + end + additional_reporter_permissions + additional_maintainer_permissions + end + + let(:other_write_abilities) do + %i[ + create_merge_request_in + create_merge_request_from + push_to_delete_protected_branch + push_code + request_access + upload_file + resolve_note + award_emoji + ] + end + + context 'when the project is archived' do + before do + project.archived = true + end + + it 'disables write actions on all relevant project features' do + expect_disallowed(*feature_write_abilities) + end + + it 'disables some other important write actions' do + expect_disallowed(*other_write_abilities) + end + + it 'does not disable other abilities' do + expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities)) + end + end +end + +RSpec.shared_examples 'project policies as anonymous' do + context 'abilities for public projects' do + context 'when a project has pending invites' do + let(:group) { create(:group, :public) } + let(:project) { create(:project, :public, namespace: group) } + let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] } + let(:anonymous_permissions) { guest_permissions - user_permissions } + + subject { described_class.new(nil, project) } + + before do + create(:group_member, :invited, group: group) + end + + it 'does not grant owner access' do + expect_allowed(*anonymous_permissions) + expect_disallowed(*user_permissions) + end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { anonymous_permissions } + end + end + end + + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(nil, project) } + + it { is_expected.to be_banned } + end +end + +RSpec.shared_examples 'project policies as guest' do + subject { described_class.new(guest, project) } + + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + let(:reporter_public_build_permissions) do + reporter_permissions - [:read_build, :read_pipeline] + end + + it do + expect_allowed(*guest_permissions) + expect_disallowed(*reporter_public_build_permissions) + expect_disallowed(*team_member_reporter_permissions) + expect_disallowed(*developer_permissions) + expect_disallowed(*maintainer_permissions) + expect_disallowed(*owner_permissions) + end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { guest_permissions } + end + + context 'public builds enabled' do + it do + expect_allowed(*guest_permissions) + expect_allowed(:read_build, :read_pipeline) + end + end + + context 'when public builds disabled' do + before do + project.update(public_builds: false) + end + + it do + expect_allowed(*guest_permissions) + expect_disallowed(:read_build, :read_pipeline) + end + end + + context 'when builds are disabled' do + before do + project.project_feature.update(builds_access_level: ProjectFeature::DISABLED) + end + + it do + expect_disallowed(:read_build) + expect_allowed(:read_pipeline) + end + end + end +end + +RSpec.shared_examples 'project policies as reporter' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(reporter, project) } + + it do + expect_allowed(*guest_permissions) + expect_allowed(*reporter_permissions) + expect_allowed(*team_member_reporter_permissions) + expect_disallowed(*developer_permissions) + expect_disallowed(*maintainer_permissions) + expect_disallowed(*owner_permissions) + end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { reporter_permissions } + end + end +end + +RSpec.shared_examples 'project policies as developer' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + subject { described_class.new(developer, project) } + + it do + expect_allowed(*guest_permissions) + expect_allowed(*reporter_permissions) + expect_allowed(*team_member_reporter_permissions) + expect_allowed(*developer_permissions) + expect_disallowed(*maintainer_permissions) + expect_disallowed(*owner_permissions) + end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { developer_permissions } + end + end +end + +RSpec.shared_examples 'project policies as maintainer' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(maintainer, project) } + + it do + expect_allowed(*guest_permissions) + expect_allowed(*reporter_permissions) + expect_allowed(*team_member_reporter_permissions) + expect_allowed(*developer_permissions) + expect_allowed(*maintainer_permissions) + expect_disallowed(*owner_permissions) + end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { maintainer_permissions } + end + end +end + +RSpec.shared_examples 'project policies as owner' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(owner, project) } + + it do + expect_allowed(*guest_permissions) + expect_allowed(*reporter_permissions) + expect_allowed(*team_member_reporter_permissions) + expect_allowed(*developer_permissions) + expect_allowed(*maintainer_permissions) + expect_allowed(*owner_permissions) + end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { owner_permissions } + end + end +end + +RSpec.shared_examples 'project policies as admin' do + context 'abilities for non-public projects' do + let(:project) { create(:project, namespace: owner.namespace) } + + subject { described_class.new(admin, project) } + + it do + expect_allowed(*guest_permissions) + expect_allowed(*reporter_permissions) + expect_disallowed(*team_member_reporter_permissions) + expect_allowed(*developer_permissions) + expect_allowed(*maintainer_permissions) + expect_allowed(*owner_permissions) + end + + it_behaves_like 'archived project policies' do + let(:regular_abilities) { owner_permissions } + end + end +end