discourse/app/services/user_anonymizer.rb

121 lines
3.2 KiB
Ruby

# frozen_string_literal: true
class UserAnonymizer
attr_reader :user_history
EMAIL_SUFFIX = "@anonymized.invalid"
# opts:
# anonymize_ip - an optional new IP to update their logs with
def initialize(user, actor = nil, opts = nil)
@user = user
@actor = actor
@user_history = nil
@opts = opts || {}
end
def self.make_anonymous(user, actor = nil, opts = nil)
self.new(user, actor, opts).make_anonymous
end
def make_anonymous
User.transaction do
@prev_email = @user.email
@prev_username = @user.username
unless UsernameChanger.new(@user, make_anon_username).change(run_update_job: false)
raise "Failed to change username"
end
@user.reload
@user.password = SecureRandom.hex
@user.name = SiteSetting.full_name_required ? @user.username : nil
@user.date_of_birth = nil
@user.title = nil
@user.uploaded_avatar_id = nil
if @opts.has_key?(:anonymize_ip)
@user.ip_address = @opts[:anonymize_ip]
@user.registration_ip_address = @opts[:anonymize_ip]
end
@user.save!
@user.primary_email.update_attribute(:email, "#{@user.username}#{EMAIL_SUFFIX}")
@user.primary_email.update_attribute(:normalized_email, "#{@user.username}#{EMAIL_SUFFIX}")
options = @user.user_option
options.mailing_list_mode = false
options.email_digests = false
options.email_level = UserOption.email_level_types[:never]
options.email_messages_level = UserOption.email_level_types[:never]
options.save!
if profile = @user.user_profile
profile.update!(
location: nil,
website: nil,
bio_raw: nil,
bio_cooked: nil,
profile_background_upload: nil,
card_background_upload: nil,
)
end
@user.clear_status!
@user.user_avatar&.destroy!
@user.single_sign_on_record&.destroy!
@user.oauth2_user_infos.destroy_all
@user.user_associated_accounts.destroy_all
@user.api_keys.destroy_all
@user.user_api_keys.destroy_all
@user.user_emails.secondary.destroy_all
@user_history = log_action
end
UsernameChanger.update_username(
user_id: @user.id,
old_username: @prev_username,
new_username: @user.username,
avatar_template: @user.avatar_template,
)
Jobs.enqueue(
:anonymize_user,
user_id: @user.id,
prev_email: @prev_email,
anonymize_ip: @opts[:anonymize_ip],
)
DiscourseEvent.trigger(:user_anonymized, user: @user, opts: @opts)
@user
end
private
def make_anon_username
100.times do
new_username = "anon#{(SecureRandom.random_number * 100_000_000).to_i}"
return new_username unless User.where(username_lower: new_username).exists?
end
raise "Failed to generate an anon username"
end
def log_action
history_details = {
action: UserHistory.actions[:anonymize_user],
target_user_id: @user.id,
acting_user_id: @actor ? @actor.id : @user.id,
}
if SiteSetting.log_anonymizer_details?
history_details[:email] = @prev_email
history_details[:details] = "username: #{@prev_username}"
end
UserHistory.create!(history_details)
end
end