gitlab-org--gitlab-foss/app/services/users/migrate_to_ghost_user_service.rb

97 lines
2.5 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
# When a user is destroyed, some of their associated records are
# moved to a "Ghost User", to prevent these associated records from
# being destroyed.
#
# For example, all the issues/MRs a user has created are _not_ destroyed
# when the user is destroyed.
module Users
class MigrateToGhostUserService
extend ActiveSupport::Concern
attr_reader :ghost_user, :user
def initialize(user)
@user = user
end
def execute
transition = user.block_transition
user.transaction do
# Block the user before moving records to prevent a data race.
# For example, if the user creates an issue after `migrate_issues`
# runs and before the user is destroyed, the destroy will fail with
# an exception.
user.block
# Reverse the user block if record migration fails
2017-11-02 10:51:42 -04:00
if !migrate_records_in_transaction && transition
transition.rollback
user.save!
end
end
user.reset
end
private
2017-11-02 10:51:42 -04:00
def migrate_records_in_transaction
user.transaction(requires_new: true) do
@ghost_user = User.ghost
2017-11-02 10:51:42 -04:00
migrate_records
end
end
2017-11-02 10:51:42 -04:00
def migrate_records
migrate_issues
migrate_merge_requests
migrate_notes
migrate_abuse_reports
migrate_award_emoji
migrate_snippets
migrate_reviews
2017-11-02 10:51:42 -04:00
end
# rubocop: disable CodeReuse/ActiveRecord
def migrate_issues
user.issues.update_all(author_id: ghost_user.id)
Issue.where(last_edited_by_id: user.id).update_all(last_edited_by_id: ghost_user.id)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def migrate_merge_requests
user.merge_requests.update_all(author_id: ghost_user.id)
MergeRequest.where(merge_user_id: user.id).update_all(merge_user_id: ghost_user.id)
end
# rubocop: enable CodeReuse/ActiveRecord
def migrate_notes
user.notes.update_all(author_id: ghost_user.id)
end
def migrate_abuse_reports
user.reported_abuse_reports.update_all(reporter_id: ghost_user.id)
end
def migrate_award_emoji
user.award_emoji.update_all(user_id: ghost_user.id)
end
def migrate_snippets
snippets = user.snippets.only_project_snippets
snippets.update_all(author_id: ghost_user.id)
end
def migrate_reviews
user.reviews.update_all(author_id: ghost_user.id)
end
end
end
Users::MigrateToGhostUserService.prepend_if_ee('EE::Users::MigrateToGhostUserService')