Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/users/destroy_service.rb')
-rw-r--r--app/services/users/destroy_service.rb51
1 files changed, 34 insertions, 17 deletions
diff --git a/app/services/users/destroy_service.rb b/app/services/users/destroy_service.rb
index dfa9316889e..a378cb09854 100644
--- a/app/services/users/destroy_service.rb
+++ b/app/services/users/destroy_service.rb
@@ -23,6 +23,11 @@ module Users
# `hard_delete: true` implies `delete_solo_owned_groups: true`. To perform
# a hard deletion without destroying solo-owned groups, pass
# `delete_solo_owned_groups: false, hard_delete: true` in +options+.
+ #
+ # To make the service asynchronous, a new behaviour is being introduced
+ # behind the user_destroy_with_limited_execution_time_worker feature flag.
+ # Migrating the associated user records, and post-migration cleanup is
+ # handled by the Users::MigrateRecordsToGhostUserWorker cron worker.
def execute(user, options = {})
delete_solo_owned_groups = options.fetch(:delete_solo_owned_groups, options[:hard_delete])
@@ -35,12 +40,14 @@ module Users
return user
end
- # Calling all before/after_destroy hooks for the user because
- # there is no dependent: destroy in the relationship. And the removal
- # is done by a foreign_key. Otherwise they won't be called
- user.members.find_each { |member| member.run_callbacks(:destroy) }
+ user.block
+
+ # Load the records. Groups are unavailable after membership is destroyed.
+ solo_owned_groups = user.solo_owned_groups.load
+
+ user.members.each_batch { |batch| batch.destroy_all } # rubocop:disable Style/SymbolProc, Cop/DestroyAll
- user.solo_owned_groups.each do |group|
+ solo_owned_groups.each do |group|
Groups::DestroyService.new(group, current_user).execute
end
@@ -54,22 +61,32 @@ module Users
yield(user) if block_given?
- MigrateToGhostUserService.new(user).execute(hard_delete: options[:hard_delete])
+ hard_delete = options.fetch(:hard_delete, false)
- response = Snippets::BulkDestroyService.new(current_user, user.snippets).execute(options)
- raise DestroyError, response.message if response.error?
+ if Feature.enabled?(:user_destroy_with_limited_execution_time_worker)
+ Users::GhostUserMigration.create!(user: user,
+ initiator_user: current_user,
+ hard_delete: hard_delete)
- # Rails attempts to load all related records into memory before
- # destroying: https://github.com/rails/rails/issues/22510
- # This ensures we delete records in batches.
- user.destroy_dependent_associations_in_batches(exclude: [:snippets])
- user.nullify_dependent_associations_in_batches
+ else
+ MigrateToGhostUserService.new(user).execute(hard_delete: options[:hard_delete])
- # Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
- user_data = user.destroy
- namespace.destroy
+ response = Snippets::BulkDestroyService.new(current_user, user.snippets)
+ .execute(skip_authorization: hard_delete)
+ raise DestroyError, response.message if response.error?
- user_data
+ # Rails attempts to load all related records into memory before
+ # destroying: https://github.com/rails/rails/issues/22510
+ # This ensures we delete records in batches.
+ user.destroy_dependent_associations_in_batches(exclude: [:snippets])
+ user.nullify_dependent_associations_in_batches
+
+ # Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
+ user_data = user.destroy
+ namespace.destroy
+
+ user_data
+ end
end
end
end