From 3e3e9ce847c709f4aee39f7cd19346cdbaa89f45 Mon Sep 17 00:00:00 2001 From: Miki Amos Date: Mon, 8 Dec 2025 18:39:33 +0200 Subject: [PATCH 1/6] Add security manager to group helper Changelog: added --- app/helpers/projects_helper.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index fb82a2d4501c5c..cec36d433444ab 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -803,10 +803,19 @@ def localized_access_names Gitlab::Access::GUEST => _('Guest'), Gitlab::Access::PLANNER => _('Planner'), Gitlab::Access::REPORTER => _('Reporter'), + **( + + if ::Gitlab::Security::SecurityManagerConfig.enabled? + { Gitlab::Access::SECURITY_MANAGER => _('Security Manager') } + else + {} + end + + ), Gitlab::Access::DEVELOPER => _('Developer'), Gitlab::Access::MAINTAINER => _('Maintainer'), Gitlab::Access::OWNER => _('Owner') - } + }.compact end def configure_oauth_import_message(provider, help_url) -- GitLab From 236de9c031cc38f23c37245b907400e083d98a28 Mon Sep 17 00:00:00 2001 From: Miki Amos Date: Wed, 10 Dec 2025 16:49:53 +0200 Subject: [PATCH 2/6] Add frontend feature flag for security manager enabled --- lib/gitlab/gon_helper.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index ff4b60d2c0a13b..64ebdbed095ccd 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -113,6 +113,8 @@ def add_gon_feature_flags # Expose the Project Studio user preference as if it were a feature flag push_force_frontend_feature_flag(:project_studio_enabled, Users::ProjectStudio.new(current_user).enabled?) + + push_force_frontend_feature_flag(:security_manager_role_enabled, Gitlab::Security::SecurityManagerConfig.enabled?) end # Exposes the state of a feature flag to the frontend code. -- GitLab From eda9ca6421d1bf27d10a4b83ddf4c2114799a091 Mon Sep 17 00:00:00 2001 From: Miki Amos Date: Wed, 10 Dec 2025 20:56:57 +0200 Subject: [PATCH 3/6] Add the security manager to access_level constants.js --- .../javascripts/access_level/constants.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/app/assets/javascripts/access_level/constants.js b/app/assets/javascripts/access_level/constants.js index d346f3ed40e011..ba09a23c9d333d 100644 --- a/app/assets/javascripts/access_level/constants.js +++ b/app/assets/javascripts/access_level/constants.js @@ -6,6 +6,7 @@ export const ACCESS_LEVEL_MINIMAL_ACCESS_INTEGER = 5; export const ACCESS_LEVEL_GUEST_INTEGER = 10; export const ACCESS_LEVEL_PLANNER_INTEGER = 15; export const ACCESS_LEVEL_REPORTER_INTEGER = 20; +export const ACCESS_LEVEL_SECURITY_MANAGER_INTEGER = 25; export const ACCESS_LEVEL_DEVELOPER_INTEGER = 30; export const ACCESS_LEVEL_MAINTAINER_INTEGER = 40; export const ACCESS_LEVEL_OWNER_INTEGER = 50; @@ -17,6 +18,7 @@ export const ACCESS_LEVEL_MINIMAL_ACCESS_STRING = 'MINIMAL_ACCESS'; export const ACCESS_LEVEL_GUEST_STRING = 'GUEST'; export const ACCESS_LEVEL_PLANNER_STRING = 'PLANNER'; export const ACCESS_LEVEL_REPORTER_STRING = 'REPORTER'; +export const ACCESS_LEVEL_SECURITY_MANAGER_STRING = 'SECURITY_MANAGER'; export const ACCESS_LEVEL_DEVELOPER_STRING = 'DEVELOPER'; export const ACCESS_LEVEL_MAINTAINER_STRING = 'MAINTAINER'; export const ACCESS_LEVEL_OWNER_STRING = 'OWNER'; @@ -27,6 +29,9 @@ export const ACCESS_LEVELS_INTEGER_TO_STRING = { [ACCESS_LEVEL_GUEST_INTEGER]: ACCESS_LEVEL_GUEST_STRING, [ACCESS_LEVEL_PLANNER_INTEGER]: ACCESS_LEVEL_PLANNER_STRING, [ACCESS_LEVEL_REPORTER_INTEGER]: ACCESS_LEVEL_REPORTER_STRING, + ...(window.gon?.features?.securityManagerRoleEnabled + ? { [ACCESS_LEVEL_SECURITY_MANAGER_INTEGER]: ACCESS_LEVEL_SECURITY_MANAGER_STRING } + : {}), [ACCESS_LEVEL_DEVELOPER_INTEGER]: ACCESS_LEVEL_DEVELOPER_STRING, [ACCESS_LEVEL_MAINTAINER_INTEGER]: ACCESS_LEVEL_MAINTAINER_STRING, [ACCESS_LEVEL_OWNER_INTEGER]: ACCESS_LEVEL_OWNER_STRING, @@ -38,6 +43,9 @@ export const ACCESS_LEVELS_STRING_TO_INTEGER = { [ACCESS_LEVEL_GUEST_STRING]: ACCESS_LEVEL_GUEST_INTEGER, [ACCESS_LEVEL_PLANNER_STRING]: ACCESS_LEVEL_PLANNER_INTEGER, [ACCESS_LEVEL_REPORTER_STRING]: ACCESS_LEVEL_REPORTER_INTEGER, + ...(window.gon?.features?.securityManagerRoleEnabled + ? { [ACCESS_LEVEL_SECURITY_MANAGER_STRING]: ACCESS_LEVEL_SECURITY_MANAGER_INTEGER } + : {}), [ACCESS_LEVEL_DEVELOPER_STRING]: ACCESS_LEVEL_DEVELOPER_INTEGER, [ACCESS_LEVEL_MAINTAINER_STRING]: ACCESS_LEVEL_MAINTAINER_INTEGER, [ACCESS_LEVEL_OWNER_STRING]: ACCESS_LEVEL_OWNER_INTEGER, @@ -48,11 +56,23 @@ const ACCESS_LEVEL_MINIMAL_ACCESS = __('Minimal Access'); const ACCESS_LEVEL_GUEST = __('Guest'); const ACCESS_LEVEL_PLANNER = __('Planner'); const ACCESS_LEVEL_REPORTER = __('Reporter'); +const ACCESS_LEVEL_SECURITY_MANAGER = __('Security Manager'); const ACCESS_LEVEL_DEVELOPER = __('Developer'); const ACCESS_LEVEL_MAINTAINER = __('Maintainer'); const ACCESS_LEVEL_OWNER = __('Owner'); export const ACCESS_LEVEL_ADMIN = __('Admin'); +const SECURITY_MANAGER_ROLE = { + value: 'SECURITY_MANAGER', + text: ACCESS_LEVEL_SECURITY_MANAGER, + accessLevel: ACCESS_LEVEL_SECURITY_MANAGER_INTEGER, + occupiesSeat: true, + description: s__( + 'MemberRole|The Security Manager role provides comprehensive visibility and management over security aspects of the group or project.', + ), +}; + + export const BASE_ROLES = [ { value: 'MINIMAL_ACCESS', @@ -91,6 +111,7 @@ export const BASE_ROLES = [ 'MemberRole|The Reporter role is suitable for team members who need to stay informed about a project or group but do not actively contribute code.', ), }, + ...(window.gon?.features?.securityManagerRoleEnabled ? [SECURITY_MANAGER_ROLE] : []), { value: 'DEVELOPER', text: ACCESS_LEVEL_DEVELOPER, @@ -134,6 +155,9 @@ export const ACCESS_LEVEL_LABELS = { [ACCESS_LEVEL_GUEST_INTEGER]: ACCESS_LEVEL_GUEST, [ACCESS_LEVEL_PLANNER_INTEGER]: ACCESS_LEVEL_PLANNER, [ACCESS_LEVEL_REPORTER_INTEGER]: ACCESS_LEVEL_REPORTER, + ...(window.gon?.features?.securityManagerRoleEnabled + ? { [ACCESS_LEVEL_SECURITY_MANAGER_INTEGER]: ACCESS_LEVEL_SECURITY_MANAGER } + : {}), [ACCESS_LEVEL_DEVELOPER_INTEGER]: ACCESS_LEVEL_DEVELOPER, [ACCESS_LEVEL_MAINTAINER_INTEGER]: ACCESS_LEVEL_MAINTAINER, [ACCESS_LEVEL_OWNER_INTEGER]: ACCESS_LEVEL_OWNER, -- GitLab From 231f374cfb0c26e889c21e44265a37345aa88ec8 Mon Sep 17 00:00:00 2001 From: Miki Amos Date: Thu, 11 Dec 2025 11:24:13 +0200 Subject: [PATCH 4/6] Fix prettier and locals strings --- app/assets/javascripts/access_level/constants.js | 1 - locale/gitlab.pot | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/access_level/constants.js b/app/assets/javascripts/access_level/constants.js index ba09a23c9d333d..fab02c28969eaf 100644 --- a/app/assets/javascripts/access_level/constants.js +++ b/app/assets/javascripts/access_level/constants.js @@ -72,7 +72,6 @@ const SECURITY_MANAGER_ROLE = { ), }; - export const BASE_ROLES = [ { value: 'MINIMAL_ACCESS', diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b96411c49d6662..4de37933f1e2ea 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -59898,6 +59898,9 @@ msgstr "" msgid "Security Finding not found" msgstr "" +msgid "Security Manager" +msgstr "" + msgid "Security Policy project already exists, but is not linked." msgstr "" -- GitLab From ce0bd5e5294e460bba0580312387fa13ad09d240 Mon Sep 17 00:00:00 2001 From: Miki Amos Date: Thu, 11 Dec 2025 16:53:06 +0200 Subject: [PATCH 5/6] Add test for project helper security manager addition --- spec/helpers/projects_helper_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 90ac8f09f7db30..6233948291b926 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -1632,6 +1632,15 @@ def license_name expect(helper.localized_project_human_access(key)).to eq(localized_project_human_access) end end + context 'with security manager enabled' do + before do + allow(Gitlab::Security::SecurityManagerConfig).to receive(:enabled?).and_return(true) + end + + it 'include security manager in localized_project_human_access' do + expect(helper.localized_project_human_access(Gitlab::Access::SECURITY_MANAGER)).to eq(_('Security Manager')) + end + end end describe '#vue_fork_divergence_data' do -- GitLab From 31ae46d19c8d3e198770931437bc669c54e1bd38 Mon Sep 17 00:00:00 2001 From: Miki Amos Date: Wed, 17 Dec 2025 15:09:51 +0200 Subject: [PATCH 6/6] Fix the unit test for project_helper_spec --- spec/helpers/projects_helper_spec.rb | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 6233948291b926..ffb2b4c923933b 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -1622,6 +1622,7 @@ def license_name Gitlab::Access::MINIMAL_ACCESS | _("Minimal Access") Gitlab::Access::GUEST | _('Guest') Gitlab::Access::REPORTER | _('Reporter') + Gitlab::Access::SECURITY_MANAGER | _('Security Manager') Gitlab::Access::DEVELOPER | _('Developer') Gitlab::Access::MAINTAINER | _('Maintainer') Gitlab::Access::OWNER | _('Owner') @@ -1632,15 +1633,6 @@ def license_name expect(helper.localized_project_human_access(key)).to eq(localized_project_human_access) end end - context 'with security manager enabled' do - before do - allow(Gitlab::Security::SecurityManagerConfig).to receive(:enabled?).and_return(true) - end - - it 'include security manager in localized_project_human_access' do - expect(helper.localized_project_human_access(Gitlab::Access::SECURITY_MANAGER)).to eq(_('Security Manager')) - end - end end describe '#vue_fork_divergence_data' do -- GitLab