Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/policies')
-rw-r--r--spec/policies/abuse_report_policy_spec.rb2
-rw-r--r--spec/policies/ci/runner_manager_policy_spec.rb142
-rw-r--r--spec/policies/ci/runner_policy_spec.rb162
-rw-r--r--spec/policies/global_policy_spec.rb8
-rw-r--r--spec/policies/group_policy_spec.rb159
-rw-r--r--spec/policies/merge_request_policy_spec.rb31
-rw-r--r--spec/policies/organizations/organization_policy_spec.rb5
-rw-r--r--spec/policies/project_group_link_policy_spec.rb164
-rw-r--r--spec/policies/project_policy_spec.rb129
-rw-r--r--spec/policies/protected_branch_access_policy_spec.rb10
-rw-r--r--spec/policies/protected_branch_policy_spec.rb40
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