diff --git a/app/assets/javascripts/admin/application_settings/deletion_protection/constants.js b/app/assets/javascripts/admin/application_settings/deletion_protection/constants.js index ee455b7fa81d54b3e3fae06a07e7100f6e263f76..f79650ef82da98617d113e4e85a26f737e66f438 100644 --- a/app/assets/javascripts/admin/application_settings/deletion_protection/constants.js +++ b/app/assets/javascripts/admin/application_settings/deletion_protection/constants.js @@ -1,7 +1,7 @@ import { __, s__ } from '~/locale'; export const I18N_DELETION_PROTECTION = { - label: s__('DeletionSettings|Deletion protection'), + label: s__('DeletionSettings|Retention period'), helpText: s__( 'DeletionSettings|Period that deleted groups and projects will remain restorable for.', ), diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index bd460f541903ad31e99112bc85d99bb0748c10ee..fe89034fb16e533a704cde09ab1723d7ce5f8c43 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -261,6 +261,7 @@ def visible_attributes :after_sign_up_text, :akismet_api_key, :akismet_enabled, + :allow_immediate_namespaces_deletion, :allow_local_requests_from_hooks_and_services, :allow_local_requests_from_web_hooks_and_services, :allow_local_requests_from_system_hooks, diff --git a/app/views/admin/application_settings/_deletion_protection_settings.html.haml b/app/views/admin/application_settings/_deletion_retention.html.haml similarity index 100% rename from app/views/admin/application_settings/_deletion_protection_settings.html.haml rename to app/views/admin/application_settings/_deletion_retention.html.haml diff --git a/app/views/admin/application_settings/_immediate_deletion.html.haml b/app/views/admin/application_settings/_immediate_deletion.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..501043e16c51bb24c947be49f38bb5c7ad042109 --- /dev/null +++ b/app/views/admin/application_settings/_immediate_deletion.html.haml @@ -0,0 +1,10 @@ +- if Feature.enabled?(:allow_immediate_namespaces_deletion, current_user) + - form = local_assigns.fetch(:form) + - help_page_link = link_to('', help_page_path('administration/settings/visibility_and_access_controls.md', anchor: 'immediate-deletion'), target: '_blank', rel: 'noopener noreferrer') + + %fieldset.form-group.gl-form-group + %legend.col-form-label + = s_('DeletionSettings|Immediate deletion') + = form.gitlab_ui_checkbox_component :allow_immediate_namespaces_deletion, s_('ImmediateNamespacesDeletionSettings|Allow immediate deletion') do |c| + - c.with_help_text do + = safe_format(s_('ImmediateNamespacesDeletionSettings|Immediately delete groups and projects scheduled for deletion and bypass the configured retention period. %{link_start}Learn more.%{link_end}'), tag_pair(help_page_link, :link_start, :link_end)) diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml index 9092267563a9fc0605b4320c9434a75b453b3b31..8a11688ce237164facd516d65f593405e22e3dfb 100644 --- a/app/views/admin/application_settings/_visibility_and_access.html.haml +++ b/app/views/admin/application_settings/_visibility_and_access.html.haml @@ -4,7 +4,8 @@ %fieldset = render 'shared/project_creation_levels', f: f, method: :default_project_creation, legend: s_('ProjectCreationLevel|Default minimum role required to create projects') = render_if_exists 'admin/application_settings/default_project_deletion_protection_setting', form: f - = render_if_exists 'admin/application_settings/deletion_protection_settings', form: f + = render 'admin/application_settings/deletion_retention' + = render 'admin/application_settings/immediate_deletion', form: f .form-group.visibility-level-setting = f.label :default_project_visibility, class: 'label-bold' = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new) diff --git a/doc/administration/settings/visibility_and_access_controls.md b/doc/administration/settings/visibility_and_access_controls.md index c2177c1ed228f87ecc57fdcd8cc0bfc2c373432f..0ad0f4c5dbd992a0f7c2d9f31df9eee90b0b216b 100644 --- a/doc/administration/settings/visibility_and_access_controls.md +++ b/doc/administration/settings/visibility_and_access_controls.md @@ -98,17 +98,9 @@ To disable the restriction: - Enabled delayed deletion for projects by default [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [on GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in GitLab 16.0. - [Changed to default behavior for groups](https://gitlab.com/gitlab-org/gitlab/-/issues/389557) on the Premium and Ultimate tier in GitLab 16.0. - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0. -- Support for disallowing immediate deletion for groups or projects scheduled for deletion [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/201957) in GitLab 18.4 [with a flag](../../administration/feature_flags/_index.md) named `disallow_immediate_deletion`. Disabled by default. {{< /history >}} -{{< alert type="flag" >}} - -The availability of this feature is controlled by a feature flag. -For more information, see the history. - -{{< /alert >}} - These protections help guard against accidental deletion of groups and projects on your instance. ### Retention period @@ -128,6 +120,38 @@ To configure deletion protection for groups and projects: 1. Scroll to **Deletion protection** and set the retention period to a value between `1` and `90` days. 1. Select **Save changes**. +### Immediate deletion + +{{< history >}} + +- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/561680) in GitLab 18.4 [with a flag](../../administration/feature_flags/_index.md) named `disallow_immediate_deletion`. Disabled by default. +- [Replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/569453) in GitLab 18.5 by an instance setting to allow immediate deletion of groups and projects scheduled for deletion. [Controlled by a flag](../feature_flags/_index.md) named `allow_immediate_namespaces_deletion`. Feature flag is disabled by default. + +{{< /history >}} + +{{< alert type="flag" >}} + +The availability of this feature is controlled by a feature flag. +For more information, see the history. + +{{< /alert >}} + +Immediately delete groups and projects scheduled for deletion. This action bypasses the configured retention period and deletes groups or projects immediately. + +To turn off immediate deletion for groups and projects: + +1. On the left sidebar, at the bottom, select **Admin**. +1. Select **Settings** > **General**. +1. Expand **Visibility and access controls**. +1. Under **Immediate deletion**, clear the checkbox. +1. Select **Save changes**. + +{{< alert type="note" >}} + +Administrators can still delete groups and projects when this setting is turned off. + +{{< /alert >}} + ### Override defaults and delete immediately To override the delay, and immediately delete a project marked for removal: diff --git a/doc/api/settings.md b/doc/api/settings.md index 2dd7f15bc86da4bc825df73d8611fbdfae0ac47c..b153c2657d0d5143ad9a2556ce3afb88dd666aca 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -463,6 +463,7 @@ to configure other related settings. These requirements are | `allowed_integrations` | array of strings | no | When `allow_all_integrations` is `false`, only integrations in this list are allowed on the instance. Ultimate only. | | `allow_account_deletion` | boolean | no | Set to `true` to allow users to delete their accounts. Premium and Ultimate only. | | `allow_group_owners_to_manage_ldap` | boolean | no | Set to `true` to allow group owners to manage LDAP. Premium and Ultimate only. | +| `allow_immediate_namespaces_deletion` | boolean | no | Immediately delete groups and projects scheduled for deletion. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/569453) in GitLab 18.5. Behind a [feature flag](../administration/feature_flags/_index.md) named `allow_immediate_namespaces_deletion`. Disabled by default. | | `allow_local_requests_from_hooks_and_services` | boolean | no | (Deprecated: Use `allow_local_requests_from_web_hooks_and_services` instead) Allow requests to the local network from webhooks and integrations. | | `allow_local_requests_from_system_hooks` | boolean | no | Allow requests to the local network from system hooks. | | `allow_local_requests_from_web_hooks_and_services` | boolean | no | Allow requests to the local network from webhooks and integrations. | diff --git a/locale/gitlab.pot b/locale/gitlab.pot index fbdcdc9f6752613a0beb375b7df1d6bc1f594b7b..8696ab63935ceff6818a068236e980eb19d4db79 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -22469,7 +22469,7 @@ msgstr "" msgid "Deletion scheduled at: %{time}" msgstr "" -msgid "DeletionSettings|Deletion protection" +msgid "DeletionSettings|Immediate deletion" msgstr "" msgid "DeletionSettings|Maximum deletion protection duration is 90 days." @@ -22481,6 +22481,9 @@ msgstr "" msgid "DeletionSettings|Period that deleted groups and projects will remain restorable for." msgstr "" +msgid "DeletionSettings|Retention period" +msgstr "" + msgid "Denied authorization of account nickname %{user_name}." msgstr "" @@ -33968,6 +33971,12 @@ msgstr "" msgid "Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior." msgstr "" +msgid "ImmediateNamespacesDeletionSettings|Allow immediate deletion" +msgstr "" + +msgid "ImmediateNamespacesDeletionSettings|Immediately delete groups and projects scheduled for deletion and bypass the configured retention period. %{link_start}Learn more.%{link_end}" +msgstr "" + msgid "Immutable tag rules require an Ultimate license" msgstr "" diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index e75b70b5f869f68c290848f78e27fccc8d78c37b..e4c17bf64d541e8e7ba31456a6de8c2bfdb50631 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -50,6 +50,21 @@ end end + it 'change deletion settings', :js do + within_testid('admin-visibility-access-settings') do + fill_in 'Retention period', with: 30 + uncheck 'Allow immediate deletion' + click_button 'Save changes' + end + + expect(page).to have_content 'Application settings saved successfully' + + within_testid('admin-visibility-access-settings') do + expect(find_field('Retention period').value).to eq('30') + expect(find_field('Allow immediate deletion')).not_to be_checked + end + end + it 'modify import sources' do expect(current_settings.import_sources).to be_empty diff --git a/spec/views/admin/application_settings/_deletion_protection_settings.html.haml_spec.rb b/spec/views/admin/application_settings/_deletion_protection_settings.html.haml_spec.rb deleted file mode 100644 index 0ab746ff30f9d3bc61da92d1ac5b61a0ee9c01d4..0000000000000000000000000000000000000000 --- a/spec/views/admin/application_settings/_deletion_protection_settings.html.haml_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'admin/application_settings/_deletion_protection_settings', feature_category: :system_access do - let_it_be(:application_setting) do - build( - :application_setting, - deletion_adjourned_period: 1 - ) - end - - before do - assign(:application_setting, application_setting) - end - - it 'renders the deletion protection settings app root' do - render - - expect(rendered).to have_selector('#js-admin-deletion-protection-settings') - end -end diff --git a/spec/views/admin/application_settings/general.html.haml_spec.rb b/spec/views/admin/application_settings/general.html.haml_spec.rb index b5b4ead41a248d996d5e75f3f0b12aeced28fd0c..39b336391bbe8852c007aed08fcf4cc7f1d643dd 100644 --- a/spec/views/admin/application_settings/general.html.haml_spec.rb +++ b/spec/views/admin/application_settings/general.html.haml_spec.rb @@ -11,6 +11,15 @@ allow(view).to receive(:current_user).and_return(user) end + describe 'deletion protection settings' do + it 'renders the deletion protection settings' do + render + + expect(rendered).to have_selector('#js-admin-deletion-protection-settings') + expect(rendered).to have_field('Allow immediate deletion') + end + end + describe 'sourcegraph integration' do context 'when sourcegraph feature is enabled' do it 'show the form' do