From c96a91f9a18a860b8725c6d62bda92f0f1f583b3 Mon Sep 17 00:00:00 2001 From: huzaifaiftikhar1 Date: Tue, 7 Jun 2022 20:40:50 +0530 Subject: [PATCH 1/2] Add support for delayed project deletion for personal projects Enable delayed project deletion feature for personal projects that are in user namespace. Changelog: added EE: true --- .../visibility_and_access_controls.md | 1 + doc/user/project/settings/index.md | 2 +- ee/app/models/ee/project.rb | 17 +++++++------ .../controllers/projects_controller_spec.rb | 18 ++++++++++++- .../factories/namespaces/user_namespaces.rb | 25 +++++++++++++++++++ ee/spec/models/project_spec.rb | 8 ++++-- 6 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 ee/spec/factories/namespaces/user_namespaces.rb diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md index a0acc70829d673..8a9db68b34f581 100644 --- a/doc/user/admin_area/settings/visibility_and_access_controls.md +++ b/doc/user/admin_area/settings/visibility_and_access_controls.md @@ -52,6 +52,7 @@ By default both administrators and anyone with the **Owner** role can delete a p > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2 for groups created after August 12, 2021. > - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/352960) from default delayed project deletion in GitLab 15.1. +> - [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89466) in GitLab 15.1. Instance-level protection against accidental deletion of groups and projects. diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md index b1514203f4b6ed..9eb255e0d94c9d 100644 --- a/doc/user/project/settings/index.md +++ b/doc/user/project/settings/index.md @@ -455,7 +455,7 @@ in GitLab 12.6, and then to [immediate deletion](https://gitlab.com/gitlab-org/g ### Delayed project deletion **(PREMIUM)** -Projects in a group (not a personal namespace) can be deleted after a delay period. Multiple settings can affect whether +Projects can be deleted after a delay period. Multiple settings can affect whether delayed project deletion is enabled for a particular project: - Self-managed instance [settings](../../admin_area/settings/visibility_and_access_controls.md#deletion-protection). diff --git a/ee/app/models/ee/project.rb b/ee/app/models/ee/project.rb index 4a358329f501d2..64b836f5f7e8da 100644 --- a/ee/app/models/ee/project.rb +++ b/ee/app/models/ee/project.rb @@ -137,7 +137,7 @@ def lock_for_confirmation!(id) scope :verification_failed_wikis, -> { joins(:repository_state).merge(ProjectRepositoryState.verification_failed_wikis) } scope :for_plan_name, -> (name) { joins(namespace: { gitlab_subscription: :hosted_plan }).where(plans: { name: name }) } scope :with_feature_available, -> (name) do - projects_with_feature_available_in_plan = ::Project.for_group(::Group.with_feature_available_in_plan(name)) + projects_with_feature_available_in_plan = ::Project.in_namespace(::Namespace.with_feature_available_in_plan(name)) public_projects_in_public_groups = ::Project.public_only.for_group(::Group.public_only) from_union([projects_with_feature_available_in_plan, public_projects_in_public_groups]) end @@ -949,13 +949,16 @@ def requirements_ci_variables end end - # Return the group's setting for delayed deletion, false for user namespace - # projects - # + # Return the group's setting for delayed deletion def group_deletion_mode_configured? - return false unless group&.namespace_settings - - group.namespace_settings.delayed_project_removal? + if group&.namespace_settings + group.namespace_settings.delayed_project_removal? + elsif namespace&.namespace_settings + # for projects under user namespace + namespace.namespace_settings.delayed_project_removal? + else + false + end end def latest_ingested_security_pipeline diff --git a/ee/spec/controllers/projects_controller_spec.rb b/ee/spec/controllers/projects_controller_spec.rb index 0a685533523ed5..d288aac225b947 100644 --- a/ee/spec/controllers/projects_controller_spec.rb +++ b/ee/spec/controllers/projects_controller_spec.rb @@ -791,7 +791,23 @@ context 'for projects in user namespace' do let(:project) { create(:project, namespace: user.namespace) } - it_behaves_like 'deletes project right away' + context 'when feature is enabled at instance level' do + before do + stub_application_setting(deletion_adjourned_period: 7) + stub_application_setting(delayed_project_removal: true) + end + + it_behaves_like 'marks project for deletion' + end + + context 'when feature is not enabled at instance level' do + before do + stub_application_setting(deletion_adjourned_period: 0) + stub_application_setting(delayed_project_removal: false) + end + + it_behaves_like 'deletes project right away' + end end end diff --git a/ee/spec/factories/namespaces/user_namespaces.rb b/ee/spec/factories/namespaces/user_namespaces.rb new file mode 100644 index 00000000000000..73d18a27d9ad3c --- /dev/null +++ b/ee/spec/factories/namespaces/user_namespaces.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :user_namespace_with_plan, class: 'Namespaces::UserNamespace', parent: :namespace do + sequence(:name) { |n| "user_namespace#{n}" } + type { Namespaces::UserNamespace.sti_name } + + transient do + plan { :free_plan } + trial_ends_on { nil } + end + + after(:create) do |user_namespace, evaluator| + if evaluator.plan + create(:namespace_settings, namespace: user_namespace) + + create(:gitlab_subscription, + namespace: user_namespace, + hosted_plan: create(evaluator.plan), + trial: evaluator.trial_ends_on.present?, + trial_ends_on: evaluator.trial_ends_on) + end + end + end +end diff --git a/ee/spec/models/project_spec.rb b/ee/spec/models/project_spec.rb index 7f77d011574523..f3403e952a1d09 100644 --- a/ee/spec/models/project_spec.rb +++ b/ee/spec/models/project_spec.rb @@ -456,9 +456,13 @@ premium_project = create(:project, :archived, creator: user, namespace: premium_group) no_plan_project = create(:project, :archived, creator: user, namespace: no_plan_group) no_plan_public_project = create(:project, :archived, creator: user, visibility: ::Gitlab::VisibilityLevel::PUBLIC, namespace: no_plan_group) + free_user_namespace = create(:user_namespace_with_plan, plan: :free_plan) + ultimate_user_namespace = create(:user_namespace_with_plan, plan: :ultimate_plan) + free_personal_project = create(:project, :archived, creator: user, namespace: free_user_namespace) + ultimate_personal_project = create(:project, :archived, creator: user, namespace: ultimate_user_namespace) - expect(described_class.with_feature_available(:adjourned_deletion_for_projects_and_groups)).to contain_exactly(premium_project, ultimate_project, no_plan_public_project) - expect(described_class.with_feature_available(:adjourned_deletion_for_projects_and_groups)).not_to include(no_plan_project) + expect(described_class.with_feature_available(:adjourned_deletion_for_projects_and_groups)).to contain_exactly(premium_project, ultimate_project, no_plan_public_project, ultimate_personal_project) + expect(described_class.with_feature_available(:adjourned_deletion_for_projects_and_groups)).not_to include(no_plan_project, free_personal_project) end end end -- GitLab From a4bcfb467d861b7330f9401a0909e3c756208120 Mon Sep 17 00:00:00 2001 From: huzaifaiftikhar1 Date: Tue, 14 Jun 2022 14:56:18 +0530 Subject: [PATCH 2/2] Modify user_namespace factory instead of creating a new one --- doc/user/project/settings/index.md | 2 ++ .../factories/namespaces/user_namespaces.rb | 33 +++++++++---------- ee/spec/models/project_spec.rb | 4 +-- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md index 9eb255e0d94c9d..46a6c1a049edcb 100644 --- a/doc/user/project/settings/index.md +++ b/doc/user/project/settings/index.md @@ -455,6 +455,8 @@ in GitLab 12.6, and then to [immediate deletion](https://gitlab.com/gitlab-org/g ### Delayed project deletion **(PREMIUM)** +> [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89466) in GitLab 15.1. + Projects can be deleted after a delay period. Multiple settings can affect whether delayed project deletion is enabled for a particular project: diff --git a/ee/spec/factories/namespaces/user_namespaces.rb b/ee/spec/factories/namespaces/user_namespaces.rb index 73d18a27d9ad3c..a0e4a923407394 100644 --- a/ee/spec/factories/namespaces/user_namespaces.rb +++ b/ee/spec/factories/namespaces/user_namespaces.rb @@ -1,24 +1,23 @@ # frozen_string_literal: true -FactoryBot.define do - factory :user_namespace_with_plan, class: 'Namespaces::UserNamespace', parent: :namespace do - sequence(:name) { |n| "user_namespace#{n}" } - type { Namespaces::UserNamespace.sti_name } - - transient do - plan { :free_plan } - trial_ends_on { nil } - end +FactoryBot.modify do + factory :user_namespace do + trait :user_namespace_with_plan do + transient do + plan { :free_plan } + trial_ends_on { nil } + end - after(:create) do |user_namespace, evaluator| - if evaluator.plan - create(:namespace_settings, namespace: user_namespace) + after(:create) do |user_namespace, evaluator| + if evaluator.plan + create(:namespace_settings, namespace: user_namespace) - create(:gitlab_subscription, - namespace: user_namespace, - hosted_plan: create(evaluator.plan), - trial: evaluator.trial_ends_on.present?, - trial_ends_on: evaluator.trial_ends_on) + create(:gitlab_subscription, + namespace: user_namespace, + hosted_plan: create(evaluator.plan), + trial: evaluator.trial_ends_on.present?, + trial_ends_on: evaluator.trial_ends_on) + end end end end diff --git a/ee/spec/models/project_spec.rb b/ee/spec/models/project_spec.rb index f3403e952a1d09..dc3f4ff52959b3 100644 --- a/ee/spec/models/project_spec.rb +++ b/ee/spec/models/project_spec.rb @@ -456,8 +456,8 @@ premium_project = create(:project, :archived, creator: user, namespace: premium_group) no_plan_project = create(:project, :archived, creator: user, namespace: no_plan_group) no_plan_public_project = create(:project, :archived, creator: user, visibility: ::Gitlab::VisibilityLevel::PUBLIC, namespace: no_plan_group) - free_user_namespace = create(:user_namespace_with_plan, plan: :free_plan) - ultimate_user_namespace = create(:user_namespace_with_plan, plan: :ultimate_plan) + free_user_namespace = create(:user_namespace, :user_namespace_with_plan, plan: :free_plan) + ultimate_user_namespace = create(:user_namespace, :user_namespace_with_plan, plan: :ultimate_plan) free_personal_project = create(:project, :archived, creator: user, namespace: free_user_namespace) ultimate_personal_project = create(:project, :archived, creator: user, namespace: ultimate_user_namespace) -- GitLab