From 24b60d60f08669f30f6790828a69bab9f28f2793 Mon Sep 17 00:00:00 2001 From: James Nutt <jnutt@gitlab.com> Date: Tue, 17 Sep 2024 14:26:21 +0100 Subject: [PATCH] Allow block of admin user contribution mapping This MR introduces an application setting (disabled by default) which controls the ability to perform user contribution mapping to users with administrative privileges on the instance. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/474963 --- app/helpers/application_settings_helper.rb | 1 + app/models/application_setting.rb | 3 +- .../application_setting_implementation.rb | 1 + .../import/source_users/reassign_service.rb | 24 +++++++++- .../application_setting_importers.json | 3 ++ .../_import_and_export.html.haml | 6 +++ .../settings/import_and_export_settings.md | 13 ++++++ doc/user/project/import/index.md | 3 ++ locale/gitlab.pot | 12 +++-- .../source_users/reassign_service_spec.rb | 44 +++++++++++++++++-- 10 files changed, 101 insertions(+), 9 deletions(-) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 1ee886b4a7682..2923241485af7 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -503,6 +503,7 @@ def visible_attributes :bulk_import_enabled, :bulk_import_max_download_file_size, :silent_admin_exports_enabled, + :allow_contribution_mapping_to_admins, :allow_runner_registration_token, :user_defaults_to_private_profile, :deactivation_email_additional_text, diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index d19ea0f41ea70..c9e90ffbdce87 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -648,7 +648,8 @@ def self.kroki_formats_attributes throttle_unauthenticated_git_http_period_in_seconds: [:integer, { default: 3600 }] jsonb_accessor :importers, - silent_admin_exports_enabled: [:boolean, { default: false }] + silent_admin_exports_enabled: [:boolean, { default: false }], + allow_contribution_mapping_to_admins: [:boolean, { default: false }] validates :rate_limits, json_schema: { filename: "application_setting_rate_limits" } diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index 342e76f06d44d..aa58009b3d781 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -264,6 +264,7 @@ def defaults # rubocop:disable Metrics/AbcSize bulk_import_enabled: false, bulk_import_max_download_file_size: 5120, silent_admin_exports_enabled: false, + allow_contribution_mapping_to_admins: false, allow_runner_registration_token: true, user_defaults_to_private_profile: false, projects_api_rate_limit_unauthenticated: 400, diff --git a/app/services/import/source_users/reassign_service.rb b/app/services/import/source_users/reassign_service.rb index e872bd124ec31..9a6020119c5d2 100644 --- a/app/services/import/source_users/reassign_service.rb +++ b/app/services/import/source_users/reassign_service.rb @@ -35,14 +35,34 @@ def reassign_user def error_invalid_assignee ServiceResponse.error( - message: s_('Import|Only active regular, auditor, or administrator users can be assigned'), + message: invalid_assignee_message, reason: :invalid_assignee, payload: import_source_user ) end + def invalid_assignee_message + if allow_mapping_to_admins? + s_('UserMapping|You can assign users with regular, auditor, or administrator access only.') + else + s_('UserMapping|You can assign only active users with regular or auditor access. ' \ + 'To assign users with administrator access, ask your GitLab administrator to ' \ + 'enable the "Allow contribution mapping to admins" setting.') + end + end + def valid_assignee?(user) - user.present? && user.human? && user.active? + user.present? && + user.human? && + user.active? && + # rubocop:disable Cop/UserAdmin -- This should not be affected by admin mode. + # We just want to know whether the user CAN have admin privileges or not. + (allow_mapping_to_admins? ? true : !user.admin?) + # rubocop:enable Cop/UserAdmin + end + + def allow_mapping_to_admins? + ::Gitlab::CurrentSettings.allow_contribution_mapping_to_admins? end end end diff --git a/app/validators/json_schemas/application_setting_importers.json b/app/validators/json_schemas/application_setting_importers.json index c69507456b8c3..f33229fc2969e 100644 --- a/app/validators/json_schemas/application_setting_importers.json +++ b/app/validators/json_schemas/application_setting_importers.json @@ -5,6 +5,9 @@ "properties": { "silent_admin_exports_enabled": { "type": "boolean" + }, + "allow_contribution_mapping_to_admins": { + "type": "boolean" } }, "additionalProperties": false diff --git a/app/views/admin/application_settings/_import_and_export.html.haml b/app/views/admin/application_settings/_import_and_export.html.haml index b3a8b6cc5f6f8..31b7cccce20c3 100644 --- a/app/views/admin/application_settings/_import_and_export.html.haml +++ b/app/views/admin/application_settings/_import_and_export.html.haml @@ -22,6 +22,12 @@ - silent_admin_exports_label_text = safe_format(s_('AdminSettings|Silent exports by admins %{silent_admin_exports_link_start}%{icon}%{silent_admin_exports_link_end}'), tag_pair_silent_admin_exports, icon: sprite_icon('question-o')) = f.label :silent_admin_exports_enabled, silent_admin_exports_label_text, class: 'gl-font-bold' = f.gitlab_ui_checkbox_component :silent_admin_exports_enabled, s_('AdminSettings|Enabled') + - if Feature.enabled?(:importer_user_mapping, current_user) + .form-group + - tag_pair_allow_contribution_mapping_to_admins = tag_pair(link_to('', help_page_path('administration/settings/import_and_export_settings.md', anchor: 'allow-contribution-mapping-to-administrators'), target: '_blank', rel: 'noopener noreferrer'), :allow_contribution_mapping_to_admins_link_start, :allow_contribution_mapping_to_admins_link_end) + - allow_contribution_mapping_to_admins_label_text = safe_format(s_('AdminSettings|Allow contribution mapping to administrators %{allow_contribution_mapping_to_admins_link_start}%{icon}%{allow_contribution_mapping_to_admins_link_end}'), tag_pair_allow_contribution_mapping_to_admins, icon: sprite_icon('question-o')) + = f.label :allow_contribution_mapping_to_admins, allow_contribution_mapping_to_admins_label_text, class: 'gl-font-bold' + = f.gitlab_ui_checkbox_component :allow_contribution_mapping_to_admins, s_('AdminSettings|Enabled') .form-group = f.label :max_export_size, _('Maximum export size (MiB)'), class: 'label-light' = f.number_field :max_export_size, class: 'form-control gl-form-input', title: _('Maximum size of export files.'), data: { toggle: 'tooltip', container: 'body' } diff --git a/doc/administration/settings/import_and_export_settings.md b/doc/administration/settings/import_and_export_settings.md index c50cd43d6bc88..43a1d4067a860 100644 --- a/doc/administration/settings/import_and_export_settings.md +++ b/doc/administration/settings/import_and_export_settings.md @@ -83,6 +83,19 @@ To enable silent admin project and group file exports: 1. Scroll to **Silent exports by admins**. 1. Select the **Enabled** checkbox. +## Allow contribution mapping to administrators + +> - Introduced in GitLab 17.5 [with flag](../../administration/feature_flags.md) named `importer_user_mapping`. Disabled by default. + +Allow mapping of imported user contributions to administrators. + +To allow mapping of imported user contributions to administrators: + +1. On the left sidebar, at the bottom, select **Admin**. +1. Select **Settings > General**, then expand **Import and export settings**. +1. Scroll to **Allow contribution mapping to administrators**. +1. Select the **Enabled** checkbox. + ## Max export size > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86124) in GitLab 15.0. diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md index ae3ce992039cb..3b993f9c78643 100644 --- a/doc/user/project/import/index.md +++ b/doc/user/project/import/index.md @@ -241,6 +241,9 @@ starting. Reassigning contributions and membership to an incorrect user poses a security threat, because the user becomes a member of your group. They can, therefore, view information they should not be able to see. +Reassigning contributions to users with administrator access is disabled by default, but you can +[enable](../../../administration/settings/import_and_export_settings.md#allow-contribution-mapping-to-administrators) it. + #### Request reassignment in UI Prerequisites: diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a3414d09e633d..350ef0c80a439 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -4004,6 +4004,9 @@ msgstr "" msgid "AdminSettings|All new projects can use instance runners by default." msgstr "" +msgid "AdminSettings|Allow contribution mapping to administrators %{allow_contribution_mapping_to_admins_link_start}%{icon}%{allow_contribution_mapping_to_admins_link_end}" +msgstr "" + msgid "AdminSettings|Allow migrating GitLab groups and projects by direct transfer" msgstr "" @@ -28264,9 +28267,6 @@ msgstr "" msgid "Import|No import details" msgstr "" -msgid "Import|Only active regular, auditor, or administrator users can be assigned" -msgstr "" - msgid "Import|Partially completed" msgstr "" @@ -59627,6 +59627,12 @@ msgstr "" msgid "UserMapping|Use a CSV file to reassign contributions from placeholder users to existing group members. This can be done in a few steps. %{linkStart}Learn more about matching users by CSV%{linkEnd}." msgstr "" +msgid "UserMapping|You can assign only active users with regular or auditor access. To assign users with administrator access, ask your GitLab administrator to enable the \"Allow contribution mapping to admins\" setting." +msgstr "" + +msgid "UserMapping|You can assign users with regular, auditor, or administrator access only." +msgstr "" + msgid "UserMapping|You have approved the reassignment of contributions from %{strong_open}%{source_user_name} (@%{source_username})%{strong_close} on %{strong_open}%{source_hostname}%{strong_close} to yourself on the group %{strong_open}%{destination_group}%{strong_close}. Reassignment processing is in progress." msgstr "" diff --git a/spec/services/import/source_users/reassign_service_spec.rb b/spec/services/import/source_users/reassign_service_spec.rb index cf00ed011ff0d..8eee628d3da2f 100644 --- a/spec/services/import/source_users/reassign_service_spec.rb +++ b/spec/services/import/source_users/reassign_service_spec.rb @@ -56,21 +56,59 @@ let(:assignee_user) { nil } it_behaves_like 'an error response', 'invalid assignee', - error: 'Only active regular, auditor, or administrator users can be assigned' + error: s_('UserMapping|You can assign only active users with regular or auditor access. ' \ + 'To assign users with administrator access, ask your GitLab administrator to ' \ + 'enable the "Allow contribution mapping to admins" setting.') end context 'when assignee user is not a human' do let(:assignee_user) { create(:user, :bot) } it_behaves_like 'an error response', 'invalid assignee', - error: 'Only active regular, auditor, or administrator users can be assigned' + error: s_('UserMapping|You can assign only active users with regular or auditor access. ' \ + 'To assign users with administrator access, ask your GitLab administrator to ' \ + 'enable the "Allow contribution mapping to admins" setting.') end context 'when assignee user is not active' do let(:assignee_user) { create(:user, :deactivated) } it_behaves_like 'an error response', 'invalid assignee', - error: 'Only active regular, auditor, or administrator users can be assigned' + error: s_('UserMapping|You can assign only active users with regular or auditor access. ' \ + 'To assign users with administrator access, ask your GitLab administrator to ' \ + 'enable the "Allow contribution mapping to admins" setting.') + end + + context 'when assignee user is an admin' do + let(:assignee_user) { create(:user, :admin) } + + it_behaves_like 'an error response', 'invalid assignee', + error: s_('UserMapping|You can assign only active users with regular or auditor access. ' \ + 'To assign users with administrator access, ask your GitLab administrator to ' \ + 'enable the "Allow contribution mapping to admins" setting.') + end + + context 'when allow_contribution_mapping_to_admins setting is enabled' do + before do + stub_application_setting(allow_contribution_mapping_to_admins: true) + end + + context 'and the assignee user is invalid' do + let(:assignee_user) { create(:user, :deactivated) } + + it_behaves_like 'an error response', 'invalid assignee', + error: s_('UserMapping|You can assign users with regular, auditor, or administrator access only.') + end + + context 'and the assignee user is an admin' do + let(:assignee_user) { create(:user, :admin) } + + it 'assigns the user' do + expect(Notify).to receive_message_chain(:import_source_user_reassign, :deliver_now) + + expect(service.execute).to be_success + end + end end context 'when an error occurs' do -- GitLab