# 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