From aee6491badb11b1b18fc55ae4c02bc3a014d940b Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 2 Aug 2023 14:52:29 -0600 Subject: [PATCH 01/18] Add `admin_merge_request` to `member_roles` table Changelog: added --- ...add_admin_merge_request_to_member_roles.rb | 7 +++ db/schema_migrations/20230802205051 | 1 + db/structure.sql | 1 + ee/app/models/members/member_role.rb | 5 ++ ee/app/policies/ee/merge_request_policy.rb | 15 ++++++ ee/app/policies/ee/project_policy.rb | 14 +++++ .../development/admin_merge_request.yml | 8 +++ .../user_sees_approve_via_custom_role_spec.rb | 45 ++++++++++++++++ ee/spec/policies/merge_request_policy_spec.rb | 51 +++++++++++++++++++ ee/spec/policies/project_policy_spec.rb | 23 +++++++++ ee/spec/requests/api/member_roles_spec.rb | 3 ++ 11 files changed, 173 insertions(+) create mode 100644 db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb create mode 100644 db/schema_migrations/20230802205051 create mode 100644 ee/config/feature_flags/development/admin_merge_request.yml create mode 100644 ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb diff --git a/db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb b/db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb new file mode 100644 index 00000000000000..90a540a46d81f3 --- /dev/null +++ b/db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddAdminMergeRequestToMemberRoles < Gitlab::Database::Migration[2.1] + def change + add_column :member_roles, :admin_merge_request, :boolean, default: false, null: false + end +end diff --git a/db/schema_migrations/20230802205051 b/db/schema_migrations/20230802205051 new file mode 100644 index 00000000000000..3f09a569f68f4d --- /dev/null +++ b/db/schema_migrations/20230802205051 @@ -0,0 +1 @@ +f682f6c1dd19fa508282bfcd30e61197652bf14b4f0717ef2313a920f0eb3516 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 1c2e81950c4489..740d4fdde4e6d5 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -18143,6 +18143,7 @@ CREATE TABLE member_roles ( read_dependency boolean DEFAULT false NOT NULL, name text DEFAULT 'Custom'::text NOT NULL, description text, + admin_merge_request boolean DEFAULT false NOT NULL, CONSTRAINT check_4364846f58 CHECK ((char_length(description) <= 255)), CONSTRAINT check_9907916995 CHECK ((char_length(name) <= 255)) ); diff --git a/ee/app/models/members/member_role.rb b/ee/app/models/members/member_role.rb index e615766cae4917..7047bcb5a14b05 100644 --- a/ee/app/models/members/member_role.rb +++ b/ee/app/models/members/member_role.rb @@ -3,6 +3,10 @@ class MemberRole < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass MAX_COUNT_PER_GROUP_HIERARCHY = 10 ALL_CUSTOMIZABLE_PERMISSIONS = { + admin_merge_request: { + descripition: 'Permission to admin merge requests', + minimal_level: Gitlab::Access::GUEST + }, admin_vulnerability: { description: 'Permission to admin vulnerability', minimal_level: Gitlab::Access::GUEST, @@ -25,6 +29,7 @@ class MemberRole < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass :read_code, :read_dependency, :read_vulnerability, + :admin_merge_request, :admin_vulnerability ].freeze ALL_CUSTOMIZABLE_GROUP_PERMISSIONS = [ diff --git a/ee/app/policies/ee/merge_request_policy.rb b/ee/app/policies/ee/merge_request_policy.rb index d96ce648cc02b3..f3e78531454f77 100644 --- a/ee/app/policies/ee/merge_request_policy.rb +++ b/ee/app/policies/ee/merge_request_policy.rb @@ -58,6 +58,17 @@ module MergeRequestPolicy ::Gitlab::Llm::StageCheck.available?(subject.project.root_ancestor, :summarize_submitted_review) end + with_scope :subject + condition(:role_enables_admin_merge_request) do + ::Feature.enabled?(:admin_merge_request, subject&.project) && + @user.custom_permission_for?(subject.project, :admin_merge_request) + end + + with_scope :subject + condition(:custom_roles_allowed) do + subject&.project&.group&.root_ancestor&.custom_roles_enabled? + end + def read_only? @subject.target_project&.namespace&.read_only? end @@ -99,6 +110,10 @@ def group_access?(protected_branch) rule do ai_features_enabled & summarize_submitted_review_enabled & can?(:read_merge_request) end.enable :summarize_submitted_review + + rule { custom_roles_allowed & role_enables_admin_merge_request }.policy do + enable :approve_merge_request + end end private diff --git a/ee/app/policies/ee/project_policy.rb b/ee/app/policies/ee/project_policy.rb index 11d2cfc65458e5..9304ccb78b444c 100644 --- a/ee/app/policies/ee/project_policy.rb +++ b/ee/app/policies/ee/project_policy.rb @@ -226,6 +226,14 @@ module ProjectPolicy @user.custom_permission_for?(@subject, :read_vulnerability) end + desc "Custom role on project that enables admin merge request" + condition(:role_enables_admin_merge_request) do + next unless @user.is_a?(User) + + ::Feature.enabled?(:admin_merge_request, subject) && + @user.custom_permission_for?(project, :admin_merge_request) + end + desc "Custom role on project that enables admin vulnerability" condition(:role_enables_admin_vulnerability) do next unless @user.is_a?(User) @@ -626,6 +634,12 @@ module ProjectPolicy enable :create_vulnerability_export end + rule { custom_roles_allowed & role_enables_admin_merge_request }.policy do + enable :admin_merge_request + enable :create_merge_request_from + enable :download_code + end + rule { custom_roles_allowed & role_enables_admin_vulnerability }.policy do enable :admin_vulnerability end diff --git a/ee/config/feature_flags/development/admin_merge_request.yml b/ee/config/feature_flags/development/admin_merge_request.yml new file mode 100644 index 00000000000000..92416e49e9ddb3 --- /dev/null +++ b/ee/config/feature_flags/development/admin_merge_request.yml @@ -0,0 +1,8 @@ +--- +name: admin_merge_request +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128302 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/421478 +milestone: '16.3' +type: development +group: group::threat insights +default_enabled: false diff --git a/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb b/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb new file mode 100644 index 00000000000000..49be61ddac28d7 --- /dev/null +++ b/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Merge request > User approves via custom role', :js, feature_category: :code_review_workflow do + before do + stub_licensed_features(custom_roles: true) + end + + context 'when the user has `admin_merge_request` enabled at the project level' do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :public, :repository, :in_group) } + let_it_be(:merge_request) { create(:merge_request, source_project: project) } + let_it_be(:admin_merge_request_role) do + create(:member_role, :guest, namespace: project.group, admin_merge_request: true) + end + + let_it_be(:project_member) do + create(:project_member, :guest, member_role: admin_merge_request_role, user: user, project: project) + end + + before do + sign_in(user) + end + + it 'allows approving and revoking approval' do + visit project_merge_request_path(project, merge_request) + expect(page).to have_button('Approve', exact: true) + + click_approval_button('Approve') + expect(page).to have_content('Approved by you') + + click_approval_button('Revoke approval') + expect(page).to have_content('Approval is optional') + end + end + + def click_approval_button(action) + page.within('.mr-state-widget') do + click_button(action) + end + + wait_for_requests + end +end diff --git a/ee/spec/policies/merge_request_policy_spec.rb b/ee/spec/policies/merge_request_policy_spec.rb index 8f4a7051ceb02e..e2a799776af528 100644 --- a/ee/spec/policies/merge_request_policy_spec.rb +++ b/ee/spec/policies/merge_request_policy_spec.rb @@ -548,4 +548,55 @@ def policy_for(user) it { is_expected.to be_disallowed(:summarize_submitted_review) } end end + + describe "Custom roles `admin_merge_request` ability" do + let_it_be(:project) { create(:project, :public, :in_group) } + let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + + subject { described_class.new(guest, merge_request) } + + context 'when the `custom_roles` feature is enabled' do + before do + stub_licensed_features(custom_roles: true) + end + + context 'when the user is a member of a custom role with `admin_merge_request` enabled' do + let_it_be(:custom_role) { create(:member_role, :guest, namespace: project.group, admin_merge_request: true) } + let_it_be(:project_member) { create(:project_member, :guest, member_role: custom_role, project: project, user: guest) } + + it 'enables the `approve_merge_request` ability' do + expect(subject).to be_allowed(:approve_merge_request) + end + + context 'when the `admin_merge_request` feature flag is disabled' do + before do + stub_feature_flags(admin_merge_request: false) + end + + it 'disables the `approve_merge_request` ability' do + expect(subject).to be_disallowed(:approve_merge_request) + end + end + end + + context 'when the user is a member of a custom role with `admin_merge_request` disabled' do + let_it_be(:custom_role) { create(:member_role, :guest, namespace: project.group, admin_merge_request: false) } + let_it_be(:project_member) { create(:project_member, :guest, member_role: custom_role, project: project, user: guest) } + + it 'disables the `approve_merge_request` ability' do + expect(subject).to be_disallowed(:approve_merge_request) + end + end + end + + context 'when the `custom_roles` feature is disabled' do + before do + stub_licensed_features(custom_roles: false) + end + + it 'disables the `approve_merge_request` ability' do + expect(subject).to be_disallowed(:approve_merge_request) + end + end + end end diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb index a100266a86cc6e..c3ac3c66270bb3 100644 --- a/ee/spec/policies/project_policy_spec.rb +++ b/ee/spec/policies/project_policy_spec.rb @@ -2574,6 +2574,29 @@ def create_member_role(member, abilities = member_role_abilities) it_behaves_like 'custom roles abilities' end + + context 'for a member role with admin_merge_request true' do + let(:member_role_abilities) { { admin_merge_request: true } } + let(:allowed_abilities) do + [ + :admin_merge_request, + :create_merge_request_from, + :download_code + ] + end + + it_behaves_like 'custom roles abilities' + end + + context 'for a member role with admin_merge_request true with `admin_merge_request` feature disabled' do + before do + stub_feature_flags(admin_merge_request: false) + stub_licensed_features(custom_roles: true) + create_member_role(group_member_guest, admin_merge_request: true) + end + + it { is_expected.to be_disallowed(:admin_merge_request) } + end end describe 'permissions for suggested reviewers bot', :saas do diff --git a/ee/spec/requests/api/member_roles_spec.rb b/ee/spec/requests/api/member_roles_spec.rb index 6d968e4c153060..e7290307659d96 100644 --- a/ee/spec/requests/api/member_roles_spec.rb +++ b/ee/spec/requests/api/member_roles_spec.rb @@ -33,6 +33,7 @@ :member_role, namespace: group_with_member_roles, base_access_level: ::Gitlab::Access::REPORTER, + admin_merge_request: true, read_code: true, read_dependency: true, read_vulnerability: false @@ -101,6 +102,7 @@ "read_code" => false, "read_dependency" => false, "read_vulnerability" => true, + "admin_merge_request" => false, "admin_vulnerability" => false, "group_id" => group_id }, @@ -112,6 +114,7 @@ "read_code" => true, "read_dependency" => true, "read_vulnerability" => false, + "admin_merge_request" => true, "admin_vulnerability" => false, "group_id" => group_id } -- GitLab From 2d7b1bbe0118069d049e2467fedd47ca8034e0d1 Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 10 Aug 2023 14:16:20 -0600 Subject: [PATCH 02/18] Add additional spec for when user does not have permission --- .../user_sees_approve_via_custom_role_spec.rb | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb b/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb index 49be61ddac28d7..ca6eaf5d3767d6 100644 --- a/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb +++ b/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb @@ -3,24 +3,22 @@ require 'spec_helper' RSpec.describe 'Merge request > User approves via custom role', :js, feature_category: :code_review_workflow do + let_it_be(:current_user) { create(:user) } + let_it_be(:project) { create(:project, :public, :repository, :in_group) } + let_it_be(:merge_request) { create(:merge_request, source_project: project) } + before do stub_licensed_features(custom_roles: true) + sign_in(current_user) end context 'when the user has `admin_merge_request` enabled at the project level' do - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public, :repository, :in_group) } - let_it_be(:merge_request) { create(:merge_request, source_project: project) } let_it_be(:admin_merge_request_role) do create(:member_role, :guest, namespace: project.group, admin_merge_request: true) end let_it_be(:project_member) do - create(:project_member, :guest, member_role: admin_merge_request_role, user: user, project: project) - end - - before do - sign_in(user) + create(:project_member, :guest, member_role: admin_merge_request_role, user: current_user, project: project) end it 'allows approving and revoking approval' do @@ -35,6 +33,22 @@ end end + context 'when the user does not have the `admin_merge_request` permission enabled' do + let_it_be(:non_admin_merge_request_role) do + create(:member_role, :guest, namespace: project.group, admin_merge_request: false) + end + + let_it_be(:project_member) do + create(:project_member, :guest, member_role: non_admin_merge_request_role, user: current_user, project: project) + end + + it 'allows approving and revoking approval' do + visit project_merge_request_path(project, merge_request) + + expect(page).not_to have_button('Approve', exact: true) + end + end + def click_approval_button(action) page.within('.mr-state-widget') do click_button(action) -- GitLab From 07f17159a20f4699a404a2b6b45f1fd95e39e635 Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 10 Aug 2023 14:31:56 -0600 Subject: [PATCH 03/18] Add column_exists? checks to migration --- ...205051_add_admin_merge_request_to_member_roles.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb b/db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb index 90a540a46d81f3..52560621c9a85d 100644 --- a/db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb +++ b/db/migrate/20230802205051_add_admin_merge_request_to_member_roles.rb @@ -1,7 +1,17 @@ # frozen_string_literal: true class AddAdminMergeRequestToMemberRoles < Gitlab::Database::Migration[2.1] - def change + enable_lock_retries! + + def up + return if column_exists?(:member_roles, :admin_merge_request) + add_column :member_roles, :admin_merge_request, :boolean, default: false, null: false end + + def down + return unless column_exists?(:member_roles, :admin_merge_request) + + remove_column :member_roles, :admin_merge_request + end end -- GitLab From 54d9bfd67036864b1b11c95ae5de1e41809d1ff9 Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 10 Aug 2023 15:25:34 -0600 Subject: [PATCH 04/18] Update spec description --- .../merge_request/user_sees_approve_via_custom_role_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb b/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb index ca6eaf5d3767d6..18db6f9e090d78 100644 --- a/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb +++ b/ee/spec/features/merge_request/user_sees_approve_via_custom_role_spec.rb @@ -42,7 +42,7 @@ create(:project_member, :guest, member_role: non_admin_merge_request_role, user: current_user, project: project) end - it 'allows approving and revoking approval' do + it 'prevents approving' do visit project_merge_request_path(project, merge_request) expect(page).not_to have_button('Approve', exact: true) -- GitLab From cef02d23207fdaa897d5c7ba5314a0f733dc9ba6 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 11 Aug 2023 16:48:59 -0600 Subject: [PATCH 05/18] Remove with_scope --- ee/app/policies/ee/merge_request_policy.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/ee/app/policies/ee/merge_request_policy.rb b/ee/app/policies/ee/merge_request_policy.rb index f3e78531454f77..320dd33e5fdfcc 100644 --- a/ee/app/policies/ee/merge_request_policy.rb +++ b/ee/app/policies/ee/merge_request_policy.rb @@ -58,7 +58,6 @@ module MergeRequestPolicy ::Gitlab::Llm::StageCheck.available?(subject.project.root_ancestor, :summarize_submitted_review) end - with_scope :subject condition(:role_enables_admin_merge_request) do ::Feature.enabled?(:admin_merge_request, subject&.project) && @user.custom_permission_for?(subject.project, :admin_merge_request) -- GitLab From b4311e0340e4c361fb2d80146036edc9399e988e Mon Sep 17 00:00:00 2001 From: mo khan Date: Mon, 14 Aug 2023 16:09:05 -0600 Subject: [PATCH 06/18] Remove :create_merge_request_from and :download_code permissions --- ee/app/policies/ee/project_policy.rb | 2 -- ee/spec/policies/project_policy_spec.rb | 8 +------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/ee/app/policies/ee/project_policy.rb b/ee/app/policies/ee/project_policy.rb index 9304ccb78b444c..744d4b4443970d 100644 --- a/ee/app/policies/ee/project_policy.rb +++ b/ee/app/policies/ee/project_policy.rb @@ -636,8 +636,6 @@ module ProjectPolicy rule { custom_roles_allowed & role_enables_admin_merge_request }.policy do enable :admin_merge_request - enable :create_merge_request_from - enable :download_code end rule { custom_roles_allowed & role_enables_admin_vulnerability }.policy do diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb index c3ac3c66270bb3..b14a13fbcc4eaf 100644 --- a/ee/spec/policies/project_policy_spec.rb +++ b/ee/spec/policies/project_policy_spec.rb @@ -2577,13 +2577,7 @@ def create_member_role(member, abilities = member_role_abilities) context 'for a member role with admin_merge_request true' do let(:member_role_abilities) { { admin_merge_request: true } } - let(:allowed_abilities) do - [ - :admin_merge_request, - :create_merge_request_from, - :download_code - ] - end + let(:allowed_abilities) { [:admin_merge_request] } it_behaves_like 'custom roles abilities' end -- GitLab From 6ded78233702b7da8196601dc20256b3a3cb1b1c Mon Sep 17 00:00:00 2001 From: mo khan Date: Mon, 14 Aug 2023 16:45:14 -0600 Subject: [PATCH 07/18] Restore :download_code permission to enable :admin_merge_request --- ee/app/policies/ee/project_policy.rb | 1 + ee/spec/policies/project_policy_spec.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/ee/app/policies/ee/project_policy.rb b/ee/app/policies/ee/project_policy.rb index 744d4b4443970d..461cf1e40bcaf0 100644 --- a/ee/app/policies/ee/project_policy.rb +++ b/ee/app/policies/ee/project_policy.rb @@ -636,6 +636,7 @@ module ProjectPolicy rule { custom_roles_allowed & role_enables_admin_merge_request }.policy do enable :admin_merge_request + enable :download_code # required to negate https://gitlab.com/gitlab-org/gitlab/-/blob/3061d30d9b3d6d4c4dd5abe68bc1e4a8a93c7966/app/policies/project_policy.rb#L603-607 end rule { custom_roles_allowed & role_enables_admin_vulnerability }.policy do diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb index b14a13fbcc4eaf..a45c880b6db788 100644 --- a/ee/spec/policies/project_policy_spec.rb +++ b/ee/spec/policies/project_policy_spec.rb @@ -2590,6 +2590,7 @@ def create_member_role(member, abilities = member_role_abilities) end it { is_expected.to be_disallowed(:admin_merge_request) } + it { is_expected.to be_disallowed(:download_code) } end end -- GitLab From 054913602972ed4bec7fda0952584c900e383ef2 Mon Sep 17 00:00:00 2001 From: mo khan Date: Mon, 14 Aug 2023 17:10:10 -0600 Subject: [PATCH 08/18] Add a request spec --- .../admin_merge_request/request_spec.rb | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb diff --git a/ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb b/ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb new file mode 100644 index 00000000000000..5f78c0fa2215d2 --- /dev/null +++ b/ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "User with admin_merge_request custom role", feature_category: :system_access do + let_it_be(:current_user) { create(:user) } + let_it_be(:project) { create(:project, :public, :repository, :in_group) } + let_it_be(:merge_request) { create(:merge_request, target_project: project, source_project: project) } + + before do + stub_licensed_features(custom_roles: true) + + sign_in(current_user) + end + + describe Projects::MergeRequestsController do + let_it_be(:role) { create(:member_role, :guest, namespace: project.group, admin_merge_request: true) } + let_it_be(:member) { create(:project_member, :guest, member_role: role, user: current_user, project: project) } + + describe "#show" do + it "user has access via a custom role" do + get namespace_project_merge_request_path( + namespace_id: project.namespace.to_param, + project_id: project, + id: merge_request.iid + ) + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template(:show) + end + end + end +end -- GitLab From 70ac2e4ce8935041f69a5892813261d9e4d306ff Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 16 Aug 2023 10:42:43 -0600 Subject: [PATCH 09/18] Use lazy navigation operator to access project --- ee/app/policies/ee/merge_request_policy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/app/policies/ee/merge_request_policy.rb b/ee/app/policies/ee/merge_request_policy.rb index 320dd33e5fdfcc..fa26b15a752536 100644 --- a/ee/app/policies/ee/merge_request_policy.rb +++ b/ee/app/policies/ee/merge_request_policy.rb @@ -60,7 +60,7 @@ module MergeRequestPolicy condition(:role_enables_admin_merge_request) do ::Feature.enabled?(:admin_merge_request, subject&.project) && - @user.custom_permission_for?(subject.project, :admin_merge_request) + @user.custom_permission_for?(subject&.project, :admin_merge_request) end with_scope :subject -- GitLab From 8c19b24c2c575d73c68722fb7e2f136e63c406f7 Mon Sep 17 00:00:00 2001 From: Imre Farkas Date: Thu, 17 Aug 2023 18:18:11 +0000 Subject: [PATCH 10/18] Apply 1 suggestion(s) to 1 file(s) --- ee/app/policies/ee/merge_request_policy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/app/policies/ee/merge_request_policy.rb b/ee/app/policies/ee/merge_request_policy.rb index fa26b15a752536..45c8ff2ebd5b1e 100644 --- a/ee/app/policies/ee/merge_request_policy.rb +++ b/ee/app/policies/ee/merge_request_policy.rb @@ -65,7 +65,7 @@ module MergeRequestPolicy with_scope :subject condition(:custom_roles_allowed) do - subject&.project&.group&.root_ancestor&.custom_roles_enabled? + subject&.project&.custom_roles_enabled? end def read_only? -- GitLab From b8981830782f9f302c3a42024a2d92849d0ede59 Mon Sep 17 00:00:00 2001 From: Imre Farkas Date: Thu, 17 Aug 2023 18:32:40 +0000 Subject: [PATCH 11/18] Apply 1 suggestion(s) to 1 file(s) --- .../requests/custom_roles/admin_merge_request/request_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb b/ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb index 5f78c0fa2215d2..51ce2566ce0f93 100644 --- a/ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb +++ b/ee/spec/requests/custom_roles/admin_merge_request/request_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" -RSpec.describe "User with admin_merge_request custom role", feature_category: :system_access do +RSpec.describe "User with admin_merge_request custom role", feature_category: :code_review_workflow do let_it_be(:current_user) { create(:user) } let_it_be(:project) { create(:project, :public, :repository, :in_group) } let_it_be(:merge_request) { create(:merge_request, target_project: project, source_project: project) } -- GitLab From e40da5a2328d5f248bffe201b93e0fceef88cfd1 Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 17 Aug 2023 14:58:34 -0600 Subject: [PATCH 12/18] Add guard clause to ensure @user is a User --- ee/app/policies/ee/merge_request_policy.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ee/app/policies/ee/merge_request_policy.rb b/ee/app/policies/ee/merge_request_policy.rb index 45c8ff2ebd5b1e..f28068d61c658c 100644 --- a/ee/app/policies/ee/merge_request_policy.rb +++ b/ee/app/policies/ee/merge_request_policy.rb @@ -59,6 +59,8 @@ module MergeRequestPolicy end condition(:role_enables_admin_merge_request) do + next unless @user.is_a?(User) + ::Feature.enabled?(:admin_merge_request, subject&.project) && @user.custom_permission_for?(subject&.project, :admin_merge_request) end -- GitLab From 99da406c1c711ce70246e34d1d7cc3492cc3b57b Mon Sep 17 00:00:00 2001 From: mo khan Date: Thu, 17 Aug 2023 15:09:03 -0600 Subject: [PATCH 13/18] Push context down to nested context --- ee/spec/policies/project_policy_spec.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb index a45c880b6db788..bbbd80a8d3088a 100644 --- a/ee/spec/policies/project_policy_spec.rb +++ b/ee/spec/policies/project_policy_spec.rb @@ -2580,17 +2580,17 @@ def create_member_role(member, abilities = member_role_abilities) let(:allowed_abilities) { [:admin_merge_request] } it_behaves_like 'custom roles abilities' - end - context 'for a member role with admin_merge_request true with `admin_merge_request` feature disabled' do - before do - stub_feature_flags(admin_merge_request: false) - stub_licensed_features(custom_roles: true) - create_member_role(group_member_guest, admin_merge_request: true) - end + context 'with `admin_merge_request` feature disabled' do + before do + stub_feature_flags(admin_merge_request: false) + stub_licensed_features(custom_roles: true) + create_member_role(group_member_guest, admin_merge_request: true) + end - it { is_expected.to be_disallowed(:admin_merge_request) } - it { is_expected.to be_disallowed(:download_code) } + it { is_expected.to be_disallowed(:admin_merge_request) } + it { is_expected.to be_disallowed(:download_code) } + end end end -- GitLab From d1d700e9f5ba4d6cd745bd925c843ce9d9732f8d Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 18 Aug 2023 10:25:45 -0600 Subject: [PATCH 14/18] Add documentation for admin_merge_request permission --- doc/api/member_roles.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/api/member_roles.md b/doc/api/member_roles.md index 9d3e51efabd32c..08f98d964edefc 100644 --- a/doc/api/member_roles.md +++ b/doc/api/member_roles.md @@ -12,6 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - [Admin vulnerability added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121534) in GitLab 16.1. > - [Read dependency added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126247) in GitLab 16.3. > - [Name and description fields added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126423) in GitLab 16.3. +> - [Admin merge request added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128302) in GitLab 16.4. ## List all member roles of a group @@ -34,6 +35,7 @@ If successful, returns [`200`](rest/index.md#status-codes) and the following res | `[].description` | string | The description of the member role. | | `[].group_id` | integer | The ID of the group that the member role belongs to. | | `[].base_access_level` | integer | Base access level for member role. Valid values are 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), or 50 (Owner).| +| `[].admin_merge_request` | boolean | Permission to admin project merge requests and enables the ability to `download_code`. | | `[].admin_vulnerability` | boolean | Permission to admin project vulnerabilities. | | `[].read_code` | boolean | Permission to read project code. | | `[].read_dependency` | boolean | Permission to read project dependencies. | @@ -55,6 +57,7 @@ Example response: "description: "Custom guest that can read code", "group_id": 84, "base_access_level": 10, + "admin_merge_request": false, "admin_vulnerability": false, "read_code": true, "read_dependency": false, @@ -66,6 +69,7 @@ Example response: "description: "Custom guest that read and admin security entities", "group_id": 84, "base_access_level": 10, + "admin_merge_request": false, "admin_vulnerability": true, "read_code": false, "read_dependency": true, @@ -92,6 +96,7 @@ To add a member role to a group, the group must be at root-level (have no parent | `name` | string | yes | The name of the member role. | | `description` | string | no | The description of the member role. | | `base_access_level` | integer | yes | Base access level for configured role. Valid values are 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), or 50 (Owner).| +| `admin_merge_request` | boolean | no | Permission to admin project merge requests. | | `admin_vulnerability` | boolean | no | Permission to admin project vulnerabilities. | | `read_code` | boolean | no | Permission to read project code. | | `read_dependency` | boolean | no | Permission to read project dependencies. | @@ -106,6 +111,7 @@ If successful, returns [`201`](rest/index.md#status-codes) and the following att | `description` | string | The description of the member role. | | `group_id` | integer | The ID of the group that the member role belongs to. | | `base_access_level` | integer | Base access level for member role. | +| `admin_merge_request` | boolean | Permission to admin project merge requests. | | `admin_vulnerability` | boolean | Permission to admin project vulnerabilities. | | `read_code` | boolean | Permission to read project code. | | `read_dependency` | boolean | Permission to read project dependencies. | @@ -126,6 +132,7 @@ Example response: "description": null, "group_id": 84, "base_access_level": 10, + "admin_merge_requests": false, "admin_vulnerability": false, "read_code": true, "read_dependency": false, -- GitLab From 373a5cb22f1ed86547d7ff69dfc8ac49cfb965b2 Mon Sep 17 00:00:00 2001 From: mo khan Date: Fri, 18 Aug 2023 10:28:41 -0600 Subject: [PATCH 15/18] Change milestone of feature flag --- ee/config/feature_flags/development/admin_merge_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/config/feature_flags/development/admin_merge_request.yml b/ee/config/feature_flags/development/admin_merge_request.yml index 92416e49e9ddb3..15b7d0ac3ae980 100644 --- a/ee/config/feature_flags/development/admin_merge_request.yml +++ b/ee/config/feature_flags/development/admin_merge_request.yml @@ -2,7 +2,7 @@ name: admin_merge_request introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128302 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/421478 -milestone: '16.3' +milestone: '16.4' type: development group: group::threat insights default_enabled: false -- GitLab From 811110838b5c2bba97d6f8a559ff1836d5cb2f0f Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 23 Aug 2023 16:06:30 -0600 Subject: [PATCH 16/18] Update documentation --- doc/user/permissions.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/user/permissions.md b/doc/user/permissions.md index d19f98b98ed6d0..e2bf8f7a0af14b 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -488,6 +488,7 @@ The following custom roles are available: - The Guest+1 role, which allows users with the Guest role to view code. - In GitLab 16.1 and later, you can create a custom role that can view vulnerability reports and change the status of the vulnerabilities. +- In GitLab 16.4 and later, you can create a custom role that can approve merge requests. You can discuss individual custom role and permission requests in [issue 391760](https://gitlab.com/gitlab-org/gitlab/-/issues/391760). @@ -518,7 +519,9 @@ You can see the required minimal access levels and abilities requirements in the | Ability | Minimal access level | Required ability | | -- | -- | -- | | `read_code` | Guest | - | +| `read_dependency` | Guest | - | | `read_vulnerability` | Guest | - | +| `admin_merge_request` | Guest | - | | `admin_vulnerability` | Guest | `read_vulnerability` | ### Associate a custom role with an existing group member -- GitLab From 4960bf23c0dc1e7dbf039aacf8268ab84de64f38 Mon Sep 17 00:00:00 2001 From: mo khan Date: Wed, 23 Aug 2023 16:10:46 -0600 Subject: [PATCH 17/18] Add documentation for when read_dependency became available --- doc/user/permissions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/user/permissions.md b/doc/user/permissions.md index e2bf8f7a0af14b..ba186bf883c8cc 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -488,6 +488,7 @@ The following custom roles are available: - The Guest+1 role, which allows users with the Guest role to view code. - In GitLab 16.1 and later, you can create a custom role that can view vulnerability reports and change the status of the vulnerabilities. +- In GitLab 16.3 and later, you can create a custom role that can view the dependency list. - In GitLab 16.4 and later, you can create a custom role that can approve merge requests. You can discuss individual custom role and permission requests in [issue 391760](https://gitlab.com/gitlab-org/gitlab/-/issues/391760). -- GitLab From 07aebe2646ce6d135ebc4cf1f66042b71e358565 Mon Sep 17 00:00:00 2001 From: Russell Dickenson Date: Thu, 24 Aug 2023 03:59:09 +0000 Subject: [PATCH 18/18] Apply 1 suggestion(s) to 1 file(s) --- doc/api/member_roles.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/api/member_roles.md b/doc/api/member_roles.md index 08f98d964edefc..311f43bcebf265 100644 --- a/doc/api/member_roles.md +++ b/doc/api/member_roles.md @@ -12,7 +12,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - [Admin vulnerability added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121534) in GitLab 16.1. > - [Read dependency added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126247) in GitLab 16.3. > - [Name and description fields added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126423) in GitLab 16.3. -> - [Admin merge request added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128302) in GitLab 16.4. +> - [Admin merge request introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128302) in GitLab 16.4 [with a flag](../administration/feature_flags.md) named `admin_merge_request`. Disabled by default. + +FLAG: +On self-managed GitLab, by default this feature is not available. To make it available, an administrator can [enable the feature flag](../administration/feature_flags.md) named `admin_merge_request`. +On GitLab.com, this feature is not available. ## List all member roles of a group -- GitLab