diff options
Diffstat (limited to 'spec/policies')
-rw-r--r-- | spec/policies/abuse_report_policy_spec.rb | 2 | ||||
-rw-r--r-- | spec/policies/ci/runner_manager_policy_spec.rb | 142 | ||||
-rw-r--r-- | spec/policies/ci/runner_policy_spec.rb | 162 | ||||
-rw-r--r-- | spec/policies/global_policy_spec.rb | 8 | ||||
-rw-r--r-- | spec/policies/group_policy_spec.rb | 159 | ||||
-rw-r--r-- | spec/policies/merge_request_policy_spec.rb | 31 | ||||
-rw-r--r-- | spec/policies/organizations/organization_policy_spec.rb | 5 | ||||
-rw-r--r-- | spec/policies/project_group_link_policy_spec.rb | 164 | ||||
-rw-r--r-- | spec/policies/project_policy_spec.rb | 129 | ||||
-rw-r--r-- | spec/policies/protected_branch_access_policy_spec.rb | 10 | ||||
-rw-r--r-- | spec/policies/protected_branch_policy_spec.rb | 40 |
11 files changed, 596 insertions, 256 deletions
diff --git a/spec/policies/abuse_report_policy_spec.rb b/spec/policies/abuse_report_policy_spec.rb index 01ab29d1cf1..3cc92749ab4 100644 --- a/spec/policies/abuse_report_policy_spec.rb +++ b/spec/policies/abuse_report_policy_spec.rb @@ -12,6 +12,7 @@ RSpec.describe AbuseReportPolicy, feature_category: :insider_threat do it 'cannot read_abuse_report' do expect(policy).to be_disallowed(:read_abuse_report) + expect(policy).to be_disallowed(:read_note) expect(policy).to be_disallowed(:create_note) end end @@ -21,6 +22,7 @@ RSpec.describe AbuseReportPolicy, feature_category: :insider_threat do it 'can read_abuse_report' do expect(policy).to be_allowed(:read_abuse_report) + expect(policy).to be_allowed(:read_note) expect(policy).to be_allowed(:create_note) end end diff --git a/spec/policies/ci/runner_manager_policy_spec.rb b/spec/policies/ci/runner_manager_policy_spec.rb index d7004033ceb..82894e729bf 100644 --- a/spec/policies/ci/runner_manager_policy_spec.rb +++ b/spec/policies/ci/runner_manager_policy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Ci::RunnerManagerPolicy, feature_category: :runner_fleet do +RSpec.describe Ci::RunnerManagerPolicy, feature_category: :fleet_visibility do let_it_be(:owner) { create(:user) } describe 'ability :read_runner_manager' do @@ -13,10 +13,15 @@ RSpec.describe Ci::RunnerManagerPolicy, feature_category: :runner_fleet do let_it_be_with_reload(:group) { create(:group, name: 'top-level', path: 'top-level') } let_it_be_with_reload(:subgroup) { create(:group, name: 'subgroup', path: 'subgroup', parent: group) } let_it_be_with_reload(:project) { create(:project, group: subgroup) } + let_it_be_with_reload(:group_without_project) { create(:group, name: 'top-level2', path: 'top-level2') } let_it_be(:instance_runner) { create(:ci_runner, :instance, :with_runner_manager) } let_it_be(:group_runner) { create(:ci_runner, :group, :with_runner_manager, groups: [group]) } + let_it_be(:subgroup_runner) { create(:ci_runner, :group, :with_runner_manager, groups: [subgroup]) } let_it_be(:project_runner) { create(:ci_runner, :project, :with_runner_manager, projects: [project]) } + let_it_be(:runner_on_group_without_project) do + create(:ci_runner, :group, :with_runner_manager, groups: [group_without_project]) + end let(:runner_manager) { runner.runner_managers.first } @@ -31,39 +36,116 @@ RSpec.describe Ci::RunnerManagerPolicy, feature_category: :runner_fleet do shared_examples 'a policy allowing reading instance runner manager depending on runner sharing' do context 'with instance runner' do - let(:runner) { instance_runner } + using RSpec::Parameterized::TableSyntax - it { expect_allowed :read_runner_manager } + where(:shared_runners_enabled_on_group, :shared_runners_enabled_on_project, :expect_can_read) do + false | false | false + false | true | true + true | false | true + true | true | true + end + + with_them do + let(:runner) { instance_runner } - context 'with shared runners disabled on projects' do before do - project.update!(shared_runners_enabled: false) + group.update!(shared_runners_enabled: shared_runners_enabled_on_group) + project.update!(shared_runners_enabled: shared_runners_enabled_on_project) + end + + specify do + if expect_can_read + expect_allowed :read_runner_manager + else + expect_disallowed :read_runner_manager + end end + end + end + end + + shared_examples 'a policy allowing reading group runner manager depending on runner sharing' do |user_role| + let(:group_runners_enabled_on_project) { true } + + before do + project.update!(group_runners_enabled: group_runners_enabled_on_project) + end + + context 'with group runner' do + let(:runner) { group_runner } + + # NOTE: The user is allowed to read the runner manager because: + # - the user is a developer+ in the runner's group + # - the user is a developer+ in `group/subgroup/project`, and the runner is shared to that project + it { expect_allowed :read_runner_manager } + + context 'with sharing of group runners disabled' do + let(:group_runners_enabled_on_project) { false } it { expect_allowed :read_runner_manager } end - context 'with shared runners disabled for groups and projects' do - before do - group.update!(shared_runners_enabled: false) - project.update!(shared_runners_enabled: false) + context 'when user belongs to subgroup only' do + let_it_be(:subgroup_member) { create(:user) } + + let(:user) { subgroup_member } + + context 'with runner visible to group project' do + # NOTE: The user is allowed to read the runner manager because the user is a developer+ + # in `group/subgroup/project`, and the runner is shared to that project + it { expect_allowed :read_runner_manager } + + before_all do + subgroup.add_member(subgroup_member, user_role) + end + + context 'with sharing of group runners disabled' do + let(:group_runners_enabled_on_project) { false } + + it { expect_disallowed :read_runner_manager } + end end + context 'without projects in group' do + let(:runner) { runner_on_group_without_project } + + before_all do + subgroup.add_member(subgroup_member, user_role) + end + + it { expect_disallowed :read_runner_manager } + end + end + + context "when user is not #{user_role} in associated group" do + let_it_be(:user_with_role) { create(:user) } + + let(:user) { user_with_role } + it { expect_disallowed :read_runner_manager } + + context "when user is #{user_role} in a group invited to group as #{user_role}" do + let_it_be(:invited_group) { create(:group, name: "#{user_role}s", path: "#{user_role}s") } + + before_all do + invited_group.add_developer(user_with_role) + create(:group_group_link, :developer, shared_group: group, shared_with_group: invited_group) + end + + it { expect_allowed :read_runner_manager } + end end end - end - shared_examples 'a policy allowing reading group runner manager depending on runner sharing' do - context 'with group runner' do - let(:runner) { group_runner } + context 'when runner is in subgroup' do + let(:runner) { subgroup_runner } + # NOTE: The user is allowed to read the runner manager because the user is a developer+ in + # `group/subgroup/project`, and the runner is shared to that project it { expect_allowed :read_runner_manager } context 'with sharing of group runners disabled' do - before do - project.update!(group_runners_enabled: false) - end + let(:group_runners_enabled_on_project) { false } it { expect_disallowed :read_runner_manager } end @@ -124,12 +206,34 @@ RSpec.describe Ci::RunnerManagerPolicy, feature_category: :runner_fleet do it_behaves_like 'a policy allowing reading instance runner manager depending on runner sharing' - it_behaves_like 'a policy allowing reading group runner manager depending on runner sharing' + it_behaves_like 'a policy allowing reading group runner manager depending on runner sharing', :developer context 'with project runner' do let(:runner) { project_runner } - it { expect_disallowed :read_runner_manager } + it { expect_allowed :read_runner_manager } + + context 'when user is not developer in parent group' do + let_it_be(:developers_group_developer) { create(:user) } + let_it_be_with_reload(:developers_group) { create(:group, name: 'developers', path: 'developers') } + + let(:user) { developers_group_developer } + + before_all do + create(:project_group_link, :developer, group: developers_group, project: project) + developers_group.add_reporter(developers_group_developer) + end + + it { expect_disallowed :read_runner_manager } + + context 'when user is developer in a group invited to project as developer' do + before_all do + developers_group.add_developer(developers_group_developer) + end + + it { expect_allowed :read_runner_manager } + end + end end end @@ -138,7 +242,7 @@ RSpec.describe Ci::RunnerManagerPolicy, feature_category: :runner_fleet do it_behaves_like 'a policy allowing reading instance runner manager depending on runner sharing' - it_behaves_like 'a policy allowing reading group runner manager depending on runner sharing' + it_behaves_like 'a policy allowing reading group runner manager depending on runner sharing', :maintainer context 'with project runner' do let(:runner) { project_runner } diff --git a/spec/policies/ci/runner_policy_spec.rb b/spec/policies/ci/runner_policy_spec.rb index e0a9e3c2870..6259cf6d247 100644 --- a/spec/policies/ci/runner_policy_spec.rb +++ b/spec/policies/ci/runner_policy_spec.rb @@ -7,21 +7,26 @@ RSpec.describe Ci::RunnerPolicy, feature_category: :runner do describe 'ability :read_runner' do let_it_be(:guest) { create(:user) } + let_it_be(:reporter) { create(:user) } let_it_be(:developer) { create(:user) } let_it_be(:maintainer) { create(:user) } let_it_be_with_reload(:group) { create(:group, name: 'top-level', path: 'top-level') } let_it_be_with_reload(:subgroup) { create(:group, name: 'subgroup', path: 'subgroup', parent: group) } let_it_be_with_reload(:project) { create(:project, group: subgroup) } + let_it_be_with_reload(:group_without_project) { create(:group, name: 'top-level2', path: 'top-level2') } let_it_be(:instance_runner) { create(:ci_runner, :instance) } let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) } + let_it_be(:subgroup_runner) { create(:ci_runner, :group, groups: [subgroup]) } let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project]) } + let_it_be(:runner_on_group_without_project) { create(:ci_runner, :group, groups: [group_without_project]) } subject(:policy) { described_class.new(user, runner) } before_all do group.add_guest(guest) + group.add_reporter(reporter) group.add_developer(developer) group.add_maintainer(maintainer) group.add_owner(owner) @@ -29,39 +34,121 @@ RSpec.describe Ci::RunnerPolicy, feature_category: :runner do shared_examples 'a policy allowing reading instance runner depending on runner sharing' do context 'with instance runner' do - let(:runner) { instance_runner } + using RSpec::Parameterized::TableSyntax - it { expect_allowed :read_runner } + where(:shared_runners_enabled_on_group, :shared_runners_enabled_on_project, :expect_can_read) do + false | false | false + false | true | true + true | false | true + true | true | true + end + + with_them do + let(:runner) { instance_runner } - context 'with shared runners disabled on projects' do before do - project.update!(shared_runners_enabled: false) + group.update!(shared_runners_enabled: shared_runners_enabled_on_group) + project.update!(shared_runners_enabled: shared_runners_enabled_on_project) end + specify do + if expect_can_read + expect_allowed :read_runner + else + expect_disallowed :read_runner + end + end + end + end + end + + shared_examples 'a policy allowing reading group runner depending on runner sharing' do |user_role| + let(:group_runners_enabled_on_project) { true } + + before do + project.update!(group_runners_enabled: group_runners_enabled_on_project) + end + + context 'with group runner' do + let(:runner) { group_runner } + + # NOTE: The user is allowed to read the runner because: + # - the user is a developer+ in the runner's group + # - the user is a developer+ in `group/subgroup/project`, and the runner is shared to that project + it { expect_allowed :read_runner } + + context 'with sharing of group runners disabled' do + let(:group_runners_enabled_on_project) { false } + it { expect_allowed :read_runner } end - context 'with shared runners disabled for groups and projects' do - before do - group.update!(shared_runners_enabled: false) - project.update!(shared_runners_enabled: false) + context 'when user belongs to subgroup only' do + let_it_be(:subgroup_member) do + create(:user).tap { |subgroup_member| subgroup.add_member(subgroup_member, user_role) } + end + + let(:user) { subgroup_member } + + context 'with runner visible to group project' do + # NOTE: The user is allowed to read the runner because the user is a developer+ in `group/subgroup/project`, + # and the runner is shared to that project + it { expect_allowed :read_runner } + + context 'with sharing of group runners disabled' do + let(:group_runners_enabled_on_project) { false } + + it { expect_disallowed :read_runner } + end end + context 'without projects in group' do + let(:runner) { runner_on_group_without_project } + + it { expect_disallowed :read_runner } + end + end + + context "when user is not #{user_role} in associated group" do + let_it_be(:user_with_role) { create(:user) } + + let(:user) { user_with_role } + it { expect_disallowed :read_runner } + + context "when user is #{user_role} in a group invited to group as #{user_role}" do + let_it_be(:invited_group) { create(:group, name: "#{user_role}s", path: "#{user_role}s") } + + before_all do + invited_group.add_member(user_with_role, user_role) + create(:group_group_link, :developer, shared_group: group, shared_with_group: invited_group) + end + + it { expect_allowed :read_runner } + end + + context "when user is a reporter in a group invited to group as #{user_role}" do + let_it_be(:invited_group) { create(:group, name: "#{user_role}s", path: "#{user_role}s") } + + before_all do + invited_group.add_reporter(user_with_role) + create(:group_group_link, user_role, shared_group: group, shared_with_group: invited_group) + end + + it { expect_disallowed :read_runner } + end end end - end - shared_examples 'a policy allowing reading group runner depending on runner sharing' do - context 'with group runner' do - let(:runner) { group_runner } + context 'when runner is in subgroup' do + let(:runner) { subgroup_runner } + # NOTE: The user is allowed to read the runner because the user is a developer+ in `group/subgroup/project`, + # and the runner is shared to that project it { expect_allowed :read_runner } context 'with sharing of group runners disabled' do - before do - project.update!(group_runners_enabled: false) - end + let(:group_runners_enabled_on_project) { false } it { expect_disallowed :read_runner } end @@ -89,6 +176,17 @@ RSpec.describe Ci::RunnerPolicy, feature_category: :runner do it { expect_disallowed :read_runner } + context 'with group invited as maintainer to group containing runner' do + let_it_be(:invited_group) { create(:group) } + let_it_be(:runner) { create(:ci_runner, :group, groups: [invited_group]) } + + before_all do + create(:group_group_link, :maintainer, shared_group: group, shared_with_group: invited_group) + end + + it { expect_disallowed :read_runner } + end + context 'with sharing of group runners disabled' do before do project.update!(group_runners_enabled: false) @@ -117,17 +215,45 @@ RSpec.describe Ci::RunnerPolicy, feature_category: :runner do it_behaves_like 'does not allow reading runners on any scope' end + context 'with reporter access' do + let(:user) { reporter } + + it_behaves_like 'does not allow reading runners on any scope' + end + context 'with developer access' do let(:user) { developer } it_behaves_like 'a policy allowing reading instance runner depending on runner sharing' - it_behaves_like 'a policy allowing reading group runner depending on runner sharing' + it_behaves_like 'a policy allowing reading group runner depending on runner sharing', :developer context 'with project runner' do let(:runner) { project_runner } - it { expect_disallowed :read_runner } + it { expect_allowed :read_runner } + + context 'when user is not developer in parent group' do + let_it_be(:developers_group_developer) { create(:user) } + let_it_be_with_reload(:developers_group) { create(:group, name: 'developers', path: 'developers') } + + let(:user) { developers_group_developer } + + before_all do + create(:project_group_link, :developer, group: developers_group, project: project) + developers_group.add_reporter(developers_group_developer) + end + + it { expect_disallowed :read_runner } + + context 'when user is developer in a group invited to project as developer' do + before_all do + developers_group.add_developer(developers_group_developer) + end + + it { expect_allowed :read_runner } + end + end end end @@ -136,7 +262,7 @@ RSpec.describe Ci::RunnerPolicy, feature_category: :runner do it_behaves_like 'a policy allowing reading instance runner depending on runner sharing' - it_behaves_like 'a policy allowing reading group runner depending on runner sharing' + it_behaves_like 'a policy allowing reading group runner depending on runner sharing', :maintainer context 'with project runner' do let(:runner) { project_runner } diff --git a/spec/policies/global_policy_spec.rb b/spec/policies/global_policy_spec.rb index 52fea8d782e..1d58b941d41 100644 --- a/spec/policies/global_policy_spec.rb +++ b/spec/policies/global_policy_spec.rb @@ -694,6 +694,14 @@ RSpec.describe GlobalPolicy, feature_category: :shared do let(:current_user) { user } it { is_expected.to be_allowed(:create_organization) } + + context 'when disallowed by admin' do + before do + stub_application_setting(can_create_organization: false) + end + + it { is_expected.to be_disallowed(:create_organization) } + end end context 'with anonymous' do diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb index cb7884b141e..4632fcca12a 100644 --- a/spec/policies/group_policy_spec.rb +++ b/spec/policies/group_policy_spec.rb @@ -18,7 +18,6 @@ RSpec.describe GroupPolicy, feature_category: :system_access do expect_disallowed(*developer_permissions) expect_disallowed(*maintainer_permissions) expect_disallowed(*owner_permissions) - expect_disallowed(:read_namespace) expect_disallowed(:read_namespace_via_membership) end end @@ -34,7 +33,6 @@ RSpec.describe GroupPolicy, feature_category: :system_access do expect_disallowed(*developer_permissions) expect_disallowed(*maintainer_permissions) expect_disallowed(*owner_permissions) - expect_disallowed(:read_namespace) expect_disallowed(:read_namespace_via_membership) end end @@ -1110,85 +1108,148 @@ RSpec.describe GroupPolicy, feature_category: :system_access do it { is_expected.to be_allowed(:admin_dependency_proxy) } end + shared_examples 'disallows all dependency proxy access' do + it { is_expected.to be_disallowed(:read_dependency_proxy) } + it { is_expected.to be_disallowed(:admin_dependency_proxy) } + end + + shared_examples 'allows dependency proxy read access but not admin' do + it { is_expected.to be_allowed(:read_dependency_proxy) } + it { is_expected.to be_disallowed(:admin_dependency_proxy) } + end + context 'feature disabled' do let(:current_user) { owner } - it { is_expected.to be_disallowed(:read_dependency_proxy) } - it { is_expected.to be_disallowed(:admin_dependency_proxy) } + before do + stub_config(dependency_proxy: { enabled: false }) + end + + it_behaves_like 'disallows all dependency proxy access' end context 'feature enabled' do before do - stub_config(dependency_proxy: { enabled: true }) + stub_config(dependency_proxy: { enabled: true }, registry: { enabled: true }) end - context 'reporter' do - let(:current_user) { reporter } + context 'human user' do + context 'reporter' do + let(:current_user) { reporter } - it { is_expected.to be_allowed(:read_dependency_proxy) } - it { is_expected.to be_disallowed(:admin_dependency_proxy) } - end + it_behaves_like 'allows dependency proxy read access but not admin' + end - context 'developer' do - let(:current_user) { developer } + context 'developer' do + let(:current_user) { developer } + + it_behaves_like 'allows dependency proxy read access but not admin' + end + + context 'maintainer' do + let(:current_user) { maintainer } + + it_behaves_like 'allows dependency proxy read access but not admin' + it_behaves_like 'disabling admin_package feature flag' + end + + context 'owner' do + let(:current_user) { owner } - it { is_expected.to be_allowed(:read_dependency_proxy) } - it { is_expected.to be_disallowed(:admin_dependency_proxy) } + it { is_expected.to be_allowed(:read_dependency_proxy) } + it { is_expected.to be_allowed(:admin_dependency_proxy) } + + it_behaves_like 'disabling admin_package feature flag' + end end - context 'maintainer' do - let(:current_user) { maintainer } + context 'deploy token user' do + let!(:group_deploy_token) do + create(:group_deploy_token, group: group, deploy_token: deploy_token) + end + + subject { described_class.new(deploy_token, group) } - it { is_expected.to be_allowed(:read_dependency_proxy) } - it { is_expected.to be_disallowed(:admin_dependency_proxy) } + context 'with insufficient scopes' do + let_it_be(:deploy_token) { create(:deploy_token, :group) } + + it_behaves_like 'disallows all dependency proxy access' + end - it_behaves_like 'disabling admin_package feature flag' + context 'with sufficient scopes' do + let_it_be(:deploy_token) { create(:deploy_token, :group, :dependency_proxy_scopes) } + + it_behaves_like 'allows dependency proxy read access but not admin' + end end - context 'owner' do - let(:current_user) { owner } + context 'group access token user' do + let_it_be(:bot_user) { create(:user, :project_bot) } + let_it_be(:token) { create(:personal_access_token, user: bot_user, scopes: [Gitlab::Auth::READ_API_SCOPE]) } + + subject { described_class.new(bot_user, group) } - it { is_expected.to be_allowed(:read_dependency_proxy) } - it { is_expected.to be_allowed(:admin_dependency_proxy) } + context 'not a member of the group' do + it_behaves_like 'disallows all dependency proxy access' + end + + context 'a member of the group' do + before do + group.add_guest(bot_user) + end - it_behaves_like 'disabling admin_package feature flag' + it_behaves_like 'allows dependency proxy read access but not admin' + end end - end - end - context 'deploy token access' do - let!(:group_deploy_token) do - create(:group_deploy_token, group: group, deploy_token: deploy_token) - end + context 'all other user types' do + User::USER_TYPES.except(:human, :project_bot).each_value do |user_type| + context "with user_type #{user_type}" do + before do + current_user.update!(user_type: user_type) + end - subject { described_class.new(deploy_token, group) } + context 'when the user has sufficient access' do + let(:current_user) { guest } - context 'a deploy token with read_package_registry scope' do - let(:deploy_token) { create(:deploy_token, :group, read_package_registry: true) } + it_behaves_like 'allows dependency proxy read access but not admin' + end - it { is_expected.to be_allowed(:read_package) } - it { is_expected.to be_allowed(:read_group) } - it { is_expected.to be_disallowed(:create_package) } + context 'when the user does not have sufficient access' do + let(:current_user) { non_group_member } + + it_behaves_like 'disallows all dependency proxy access' + end + end + end + end end + end - context 'a deploy token with write_package_registry scope' do - let(:deploy_token) { create(:deploy_token, :group, write_package_registry: true) } + context 'package registry' do + context 'deploy token user' do + let!(:group_deploy_token) do + create(:group_deploy_token, group: group, deploy_token: deploy_token) + end - it { is_expected.to be_allowed(:create_package) } - it { is_expected.to be_allowed(:read_package) } - it { is_expected.to be_allowed(:read_group) } - it { is_expected.to be_disallowed(:destroy_package) } - end + subject { described_class.new(deploy_token, group) } - context 'a deploy token with dependency proxy scopes' do - let_it_be(:deploy_token) { create(:deploy_token, :group, :dependency_proxy_scopes) } + context 'with read_package_registry scope' do + let(:deploy_token) { create(:deploy_token, :group, read_package_registry: true) } - before do - stub_config(dependency_proxy: { enabled: true }) + it { is_expected.to be_allowed(:read_package) } + it { is_expected.to be_allowed(:read_group) } + it { is_expected.to be_disallowed(:create_package) } end - it { is_expected.to be_allowed(:read_dependency_proxy) } - it { is_expected.to be_disallowed(:admin_dependency_proxy) } + context 'with write_package_registry scope' do + let(:deploy_token) { create(:deploy_token, :group, write_package_registry: true) } + + it { is_expected.to be_allowed(:create_package) } + it { is_expected.to be_allowed(:read_package) } + it { is_expected.to be_allowed(:read_group) } + it { is_expected.to be_disallowed(:destroy_package) } + end end end diff --git a/spec/policies/merge_request_policy_spec.rb b/spec/policies/merge_request_policy_spec.rb index 285f52956eb..c21e1244402 100644 --- a/spec/policies/merge_request_policy_spec.rb +++ b/spec/policies/merge_request_policy_spec.rb @@ -462,37 +462,6 @@ RSpec.describe MergeRequestPolicy do end end - context 'when enabling generate diff summary permission' do - let_it_be(:project) { create(:project) } - let_it_be(:mr) { create(:merge_request, target_project: project, source_project: project) } - let_it_be(:user) { create(:user) } - let(:policy) { permissions(user, mr) } - - context 'when can read_merge_request' do - before do - project.add_developer(user) - end - - it 'allows to generate_diff_summary' do - expect(policy).to be_allowed(:generate_diff_summary) - end - end - - context 'when can not read_merge_request' do - it 'does not allow to generate_diff_summary' do - expect(policy).not_to be_allowed(:generate_diff_summary) - end - - context 'and when is the LLM bot' do - let(:user) { create(:user, :llm_bot) } - - it 'allows to generate_diff_summary' do - expect(policy).to be_allowed(:generate_diff_summary) - end - end - end - end - context 'when the author of the merge request is banned', feature_category: :insider_threat do let_it_be(:user) { create(:user) } let_it_be(:admin) { create(:user, :admin) } diff --git a/spec/policies/organizations/organization_policy_spec.rb b/spec/policies/organizations/organization_policy_spec.rb index 3fcfa63b1b2..7eed497d644 100644 --- a/spec/policies/organizations/organization_policy_spec.rb +++ b/spec/policies/organizations/organization_policy_spec.rb @@ -12,6 +12,7 @@ RSpec.describe Organizations::OrganizationPolicy, feature_category: :cell do let_it_be(:current_user) { nil } it { is_expected.to be_allowed(:read_organization) } + it { is_expected.to be_disallowed(:admin_organization) } end context 'when the user is an admin' do @@ -34,11 +35,13 @@ RSpec.describe Organizations::OrganizationPolicy, feature_category: :cell do create :organization_user, organization: organization, user: current_user end - it { is_expected.to be_allowed(:read_organization_user) } + it { is_expected.to be_allowed(:admin_organization) } it { is_expected.to be_allowed(:read_organization) } + it { is_expected.to be_allowed(:read_organization_user) } end context 'when the user is not part of the organization' do + it { is_expected.to be_disallowed(:admin_organization) } it { is_expected.to be_disallowed(:read_organization_user) } # All organizations are currently public, and hence they are allowed to be read # even if the user is not a part of the organization. diff --git a/spec/policies/project_group_link_policy_spec.rb b/spec/policies/project_group_link_policy_spec.rb index 1047d3acb1e..9fcd6ead524 100644 --- a/spec/policies/project_group_link_policy_spec.rb +++ b/spec/policies/project_group_link_policy_spec.rb @@ -7,21 +7,75 @@ RSpec.describe ProjectGroupLinkPolicy, feature_category: :system_access do let_it_be(:group2) { create(:group, :private) } let_it_be(:project) { create(:project, :private) } - let(:project_group_link) do - create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::DEVELOPER) + subject(:policy) { described_class.new(user, project_group_link) } + + describe 'destroy_project_group_link' do + let_it_be(:project_group_link) do + create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::DEVELOPER) + end + + context 'when the user is a group owner' do + before_all do + group2.add_owner(user) + end + + it 'can destroy group_project_link' do + expect(policy).to be_allowed(:destroy_project_group_link) + end + + context 'when group link has owner access' do + it 'can destroy group_project_link' do + project_group_link.update!(group_access: Gitlab::Access::OWNER) + + expect(policy).to be_allowed(:destroy_project_group_link) + end + end + end + + context 'when user is a project maintainer' do + before do + project_group_link.project.add_maintainer(user) + end + + context 'when group link has owner access' do + it 'cannot destroy group_project_link' do + project_group_link.update!(group_access: Gitlab::Access::OWNER) + + expect(policy).to be_disallowed(:destroy_project_group_link) + end + end + + context 'when group link has maintainer access' do + it 'can destroy group_project_link' do + project_group_link.update!(group_access: Gitlab::Access::MAINTAINER) + + expect(policy).to be_allowed(:destroy_project_group_link) + end + end + end + + context 'when user is not a project maintainer' do + it 'cannot destroy group_project_link' do + project_group_link.project.add_developer(user) + + expect(policy).to be_disallowed(:destroy_project_group_link) + end + end end - subject(:policy) { described_class.new(user, project_group_link) } + describe 'manage_destroy' do + let_it_be(:project_group_link) do + create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::DEVELOPER) + end - describe 'admin_project_group_link' do context 'when the user is a group owner' do before_all do group2.add_owner(user) end context 'when user is not project maintainer' do - it 'can admin group_project_link' do - expect(policy).to be_allowed(:admin_project_group_link) + it 'can manage_destroy' do + expect(policy).to be_allowed(:manage_destroy) end end @@ -30,32 +84,50 @@ RSpec.describe ProjectGroupLinkPolicy, feature_category: :system_access do project_group_link.project.add_maintainer(user) end - it 'can admin group_project_link' do - expect(policy).to be_allowed(:admin_project_group_link) + it 'can admin manage_destroy' do + expect(policy).to be_allowed(:manage_destroy) end end end context 'when user is not a group owner' do context 'when user is a project maintainer' do - it 'can admin group_project_link' do + before do project_group_link.project.add_maintainer(user) + end + + context 'when group link has owner access' do + it 'can manage_destroy' do + project_group_link.update!(group_access: Gitlab::Access::OWNER) - expect(policy).to be_allowed(:admin_project_group_link) + expect(policy).to be_allowed(:manage_destroy) + end + end + + context 'when group link has maintainer access' do + it 'can manage_destroy' do + project_group_link.update!(group_access: Gitlab::Access::MAINTAINER) + + expect(policy).to be_allowed(:manage_destroy) + end end end context 'when user is not a project maintainer' do - it 'cannot admin group_project_link' do + it 'cannot manage_destroy' do project_group_link.project.add_developer(user) - expect(policy).to be_disallowed(:admin_project_group_link) + expect(policy).to be_disallowed(:manage_destroy) end end end end describe 'read_shared_with_group' do + let_it_be(:project_group_link) do + create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::MAINTAINER) + end + context 'when the user is a project member' do before_all do project.add_guest(user) @@ -83,9 +155,9 @@ RSpec.describe ProjectGroupLinkPolicy, feature_category: :system_access do end context 'when the group is public' do - let_it_be(:group2) { create(:group, :public) } - it 'can read_shared_with_group' do + group2.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + expect(policy).to be_allowed(:read_shared_with_group) end end @@ -102,4 +174,68 @@ RSpec.describe ProjectGroupLinkPolicy, feature_category: :system_access do end end end + + describe 'manage_owners' do + let_it_be(:project_group_link) do + create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::MAINTAINER) + end + + context 'when the user is a project owner' do + before_all do + project.add_owner(user) + end + + it 'can manage_owners' do + expect(policy).to be_allowed(:manage_owners) + end + end + + context 'when the user is a project maintainer' do + before_all do + project.add_maintainer(user) + end + + it 'cannot manage_owners' do + expect(policy).to be_disallowed(:manage_owners) + end + end + end + + describe 'manage_group_link_with_owner_access' do + context 'when group link has owner access' do + let_it_be(:project_group_link) do + create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::OWNER) + end + + context 'when the user is a project owner' do + before_all do + project.add_owner(user) + end + + it 'can manage_group_link_with_owner_access' do + expect(policy).to be_allowed(:manage_group_link_with_owner_access) + end + end + + context 'when the user is a project maintainer' do + before_all do + project.add_maintainer(user) + end + + it 'cannot manage_group_link_with_owner_access' do + expect(policy).to be_disallowed(:manage_group_link_with_owner_access) + end + end + end + + context 'when group link has maintainer access' do + let_it_be(:project_group_link) do + create(:project_group_link, project: project, group: group2, group_access: Gitlab::Access::MAINTAINER) + end + + it 'can manage_group_link_with_owner_access' do + expect(policy).to be_allowed(:manage_group_link_with_owner_access) + end + end + end end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index fda889ff422..a9a4575d747 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -2573,7 +2573,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do RSpec.shared_examples 'CI_JOB_TOKEN enforces the expected permissions' do with_them do let(:current_user) { public_send(user_role) } - let(:project) { public_send("#{project_visibility}_project") } + let(:project) { public_project } let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) } let(:scope_project) do @@ -2607,20 +2607,19 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - # Remove project_visibility on FF restrict_ci_job_token_for_public_and_internal_projects cleanup - where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do - :public | :reporter | false | :same | true | true - :public | :reporter | true | :same | true | true - :public | :reporter | false | :same | false | true - :public | :reporter | false | :different | true | false - :public | :reporter | true | :different | true | false - :public | :reporter | false | :different | false | true - :public | :guest | false | :same | true | true - :public | :guest | true | :same | true | true - :public | :guest | false | :same | false | true - :public | :guest | false | :different | true | false - :public | :guest | true | :different | true | false - :public | :guest | false | :different | false | true + where(:user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do + :reporter | false | :same | true | true + :reporter | true | :same | true | true + :reporter | false | :same | false | true + :reporter | false | :different | true | false + :reporter | true | :different | true | false + :reporter | false | :different | false | true + :guest | false | :same | true | true + :guest | true | :same | true | true + :guest | false | :same | false | true + :guest | false | :different | true | false + :guest | true | :different | true | false + :guest | false | :different | false | true end include_examples "CI_JOB_TOKEN enforces the expected permissions" @@ -2663,61 +2662,8 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do permissions.each { |p| expect_disallowed(p) } end - - context "with restrict_ci_job_token_for_public_and_internal_projects disabled" do - before do - stub_feature_flags(restrict_ci_job_token_for_public_and_internal_projects: false) - end - - it 'allows all permissions for private' do - project.project_feature.update!("#{feature}_access_level": ProjectFeature::PRIVATE) - - permissions.each { |p| expect_allowed(p) } - end - end end end - - context "with FF restrict_ci_job_token_for_public_and_internal_projects disabled" do - before do - stub_feature_flags(restrict_ci_job_token_for_public_and_internal_projects: false) - end - - where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do - :private | :reporter | false | :same | true | true - :private | :reporter | false | :same | false | true - :private | :reporter | false | :different | true | false - :private | :reporter | false | :different | false | true - :private | :guest | false | :same | true | true - :private | :guest | false | :same | false | true - :private | :guest | false | :different | true | false - :private | :guest | false | :different | false | true - - :internal | :reporter | false | :same | true | true - :internal | :reporter | true | :same | true | true - :internal | :reporter | false | :same | false | true - :internal | :reporter | false | :different | true | true - :internal | :reporter | true | :different | true | false - :internal | :reporter | false | :different | false | true - :internal | :guest | false | :same | true | true - :internal | :guest | true | :same | true | true - :internal | :guest | false | :same | false | true - :internal | :guest | false | :different | true | true - :internal | :guest | true | :different | true | false - :internal | :guest | false | :different | false | true - - :public | :reporter | false | :same | true | true - :public | :reporter | false | :same | false | true - :public | :reporter | false | :different | true | true - :public | :reporter | false | :different | false | true - :public | :guest | false | :same | true | true - :public | :guest | false | :same | false | true - :public | :guest | false | :different | true | true - :public | :guest | false | :different | false | true - end - - include_examples "CI_JOB_TOKEN enforces the expected permissions" - end end describe 'container_image policies' do @@ -3321,37 +3267,46 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end describe 'read_model_registry' do - let(:project_with_feature) { project } - let(:current_user) { owner } - - before do - stub_feature_flags(model_registry: false) - stub_feature_flags(model_registry: project_with_feature) if project_with_feature - end + using RSpec::Parameterized::TableSyntax - context 'feature flag is enabled' do - specify { is_expected.to be_allowed(:read_model_registry) } + where(:feature_flag_enabled, :current_user, :access_level, :allowed) do + false | ref(:owner) | Featurable::ENABLED | false + true | ref(:guest) | Featurable::ENABLED | true + true | ref(:guest) | Featurable::PRIVATE | true + true | ref(:guest) | Featurable::DISABLED | false + true | ref(:non_member) | Featurable::ENABLED | true + true | ref(:non_member) | Featurable::PRIVATE | false + true | ref(:non_member) | Featurable::DISABLED | false end + with_them do + before do + stub_feature_flags(model_registry: feature_flag_enabled) + project.project_feature.update!(model_registry_access_level: access_level) + end - context 'feature flag is disabled' do - let(:project_with_feature) { nil } - - specify { is_expected.not_to be_allowed(:read_model_registry) } + if params[:allowed] + it { expect_allowed(:read_model_registry) } + else + it { expect_disallowed(:read_model_registry) } + end end end describe 'write_model_registry' do using RSpec::Parameterized::TableSyntax - where(:ff_model_registry_enabled, :current_user, :allowed) do - true | ref(:reporter) | true - true | ref(:guest) | false - false | ref(:owner) | false + where(:feature_flag_enabled, :current_user, :access_level, :allowed) do + false | ref(:owner) | Featurable::ENABLED | false + true | ref(:reporter) | Featurable::ENABLED | true + true | ref(:reporter) | Featurable::PRIVATE | true + true | ref(:reporter) | Featurable::DISABLED | false + true | ref(:guest) | Featurable::ENABLED | false + true | ref(:non_member) | Featurable::ENABLED | false end with_them do before do - stub_feature_flags(model_registry: false) - stub_feature_flags(model_registry: project) if ff_model_registry_enabled + stub_feature_flags(model_registry: feature_flag_enabled) + project.project_feature.update!(model_registry_access_level: access_level) end if params[:allowed] diff --git a/spec/policies/protected_branch_access_policy_spec.rb b/spec/policies/protected_branch_access_policy_spec.rb index 68a130d666a..6725cde0cb1 100644 --- a/spec/policies/protected_branch_access_policy_spec.rb +++ b/spec/policies/protected_branch_access_policy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ProtectedBranchAccessPolicy do +RSpec.describe ProtectedBranchAccessPolicy, feature_category: :source_code_management do let(:user) { create(:user) } let(:protected_branch_access) { create(:protected_branch_merge_access_level) } let(:project) { protected_branch_access.protected_branch.project } @@ -14,9 +14,7 @@ RSpec.describe ProtectedBranchAccessPolicy do project.add_maintainer(user) end - it 'can be read' do - is_expected.to be_allowed(:read_protected_branch) - end + it_behaves_like 'allows protected branch crud' end context 'as guests' do @@ -24,8 +22,6 @@ RSpec.describe ProtectedBranchAccessPolicy do project.add_guest(user) end - it 'can not be read' do - is_expected.to be_disallowed(:read_protected_branch) - end + it_behaves_like 'disallows protected branch crud' end end diff --git a/spec/policies/protected_branch_policy_spec.rb b/spec/policies/protected_branch_policy_spec.rb index d676de14735..d2040a0d334 100644 --- a/spec/policies/protected_branch_policy_spec.rb +++ b/spec/policies/protected_branch_policy_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ProtectedBranchPolicy do +RSpec.describe ProtectedBranchPolicy, feature_category: :source_code_management do let(:user) { create(:user) } let(:name) { 'feature' } let(:protected_branch) { create(:protected_branch, name: name) } @@ -10,47 +10,27 @@ RSpec.describe ProtectedBranchPolicy do subject { described_class.new(user, protected_branch) } - context 'as maintainers' do + context 'as a maintainer' do before do project.add_maintainer(user) end - 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_behaves_like 'allows protected branch crud' + end - it 'can be updated' do - is_expected.to be_allowed(:update_protected_branch) + context 'as a developer' do + before do + project.add_developer(user) end - it 'can be destroyed' do - is_expected.to be_allowed(:destroy_protected_branch) - end + it_behaves_like 'disallows protected branch crud' end - context 'as guests' do + context 'as a guest' 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 - - it 'cannot be destroyed' do - is_expected.to be_disallowed(:destroy_protected_branch) - end + it_behaves_like 'disallows protected branch crud' end end |