2015-03-07 05:44:54 +08:00
|
|
|
class UserAnonymizer
|
2018-03-06 03:38:18 +08:00
|
|
|
|
|
|
|
attr_reader :user_history
|
|
|
|
|
2018-05-01 01:42:51 +08:00
|
|
|
# opts:
|
|
|
|
# anonymize_ip - an optional new IP to update their logs with
|
|
|
|
def initialize(user, actor = nil, opts = nil)
|
2015-03-07 05:44:54 +08:00
|
|
|
@user = user
|
|
|
|
@actor = actor
|
2018-03-06 03:38:18 +08:00
|
|
|
@user_history = nil
|
2018-05-01 01:42:51 +08:00
|
|
|
@opts = opts || {}
|
2015-03-07 05:44:54 +08:00
|
|
|
end
|
|
|
|
|
2018-05-01 01:42:51 +08:00
|
|
|
def self.make_anonymous(user, actor = nil, opts = nil)
|
|
|
|
self.new(user, actor, opts).make_anonymous
|
2015-03-07 05:44:54 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def make_anonymous
|
|
|
|
User.transaction do
|
2018-05-01 01:42:51 +08:00
|
|
|
@prev_email = @user.email
|
|
|
|
@prev_username = @user.username
|
2015-03-07 05:44:54 +08:00
|
|
|
|
2018-05-13 22:25:56 +08:00
|
|
|
@user.update_attribute(:uploaded_avatar_id, nil)
|
2018-05-01 07:54:36 +08:00
|
|
|
raise "Failed to change username" unless UsernameChanger.change(@user, make_anon_username)
|
2015-03-07 05:44:54 +08:00
|
|
|
|
|
|
|
@user.reload
|
|
|
|
@user.password = SecureRandom.hex
|
|
|
|
@user.email = "#{@user.username}@example.com"
|
2016-03-17 14:43:21 +08:00
|
|
|
@user.name = SiteSetting.full_name_required ? @user.username : nil
|
2015-03-07 05:44:54 +08:00
|
|
|
@user.date_of_birth = nil
|
|
|
|
@user.title = nil
|
2018-05-01 01:42:51 +08:00
|
|
|
|
2018-05-01 07:54:36 +08:00
|
|
|
anonymize_ips(@opts[:anonymize_ip]) if @opts.has_key?(:anonymize_ip)
|
2018-05-01 01:42:51 +08:00
|
|
|
|
2015-03-07 05:44:54 +08:00
|
|
|
@user.save
|
|
|
|
|
2016-02-17 12:46:19 +08:00
|
|
|
options = @user.user_option
|
|
|
|
options.email_always = false
|
|
|
|
options.mailing_list_mode = false
|
|
|
|
options.email_digests = false
|
|
|
|
options.email_private_messages = false
|
|
|
|
options.email_direct = false
|
|
|
|
options.save
|
|
|
|
|
2015-03-07 05:44:54 +08:00
|
|
|
profile = @user.user_profile
|
|
|
|
profile.destroy if profile
|
|
|
|
@user.create_user_profile
|
|
|
|
|
|
|
|
@user.user_avatar.try(:destroy)
|
|
|
|
@user.twitter_user_info.try(:destroy)
|
|
|
|
@user.google_user_info.try(:destroy)
|
|
|
|
@user.github_user_info.try(:destroy)
|
|
|
|
@user.facebook_user_info.try(:destroy)
|
|
|
|
@user.single_sign_on_record.try(:destroy)
|
|
|
|
@user.oauth2_user_info.try(:destroy)
|
2018-03-01 19:10:27 +08:00
|
|
|
@user.instagram_user_info.try(:destroy)
|
2015-03-07 05:44:54 +08:00
|
|
|
@user.user_open_ids.find_each { |x| x.destroy }
|
|
|
|
@user.api_key.try(:destroy)
|
|
|
|
|
2018-03-06 03:38:18 +08:00
|
|
|
history_details = {
|
|
|
|
action: UserHistory.actions[:anonymize_user],
|
|
|
|
target_user_id: @user.id,
|
|
|
|
acting_user_id: @actor ? @actor.id : @user.id,
|
|
|
|
}
|
|
|
|
|
2018-06-07 18:17:37 +08:00
|
|
|
Invite.with_deleted.where(user_id: @user.id).destroy_all
|
|
|
|
EmailToken.where(user_id: @user.id).destroy_all
|
|
|
|
EmailLog.where(user_id: @user.id).delete_all
|
|
|
|
IncomingEmail.where("user_id = ? OR from_address = ?", @user.id, @prev_email).delete_all
|
|
|
|
|
|
|
|
Post.with_deleted
|
|
|
|
.where(user_id: @user.id)
|
|
|
|
.where.not(raw_email: nil)
|
|
|
|
.update_all(raw_email: nil)
|
|
|
|
|
2018-03-06 03:38:18 +08:00
|
|
|
if SiteSetting.log_anonymizer_details?
|
2018-05-01 01:42:51 +08:00
|
|
|
history_details[:email] = @prev_email
|
|
|
|
history_details[:details] = "username: #{@prev_username}"
|
2018-03-06 03:38:18 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
@user_history = UserHistory.create(history_details)
|
2015-03-07 05:44:54 +08:00
|
|
|
end
|
2018-05-03 00:25:06 +08:00
|
|
|
|
|
|
|
DiscourseEvent.trigger(:user_anonymized, user: @user, opts: @opts)
|
2015-03-07 05:44:54 +08:00
|
|
|
@user
|
|
|
|
end
|
|
|
|
|
2018-05-01 01:42:51 +08:00
|
|
|
private
|
|
|
|
|
2018-06-07 13:28:18 +08:00
|
|
|
def make_anon_username
|
|
|
|
100.times do
|
|
|
|
new_username = "anon#{(SecureRandom.random_number * 100000000).to_i}"
|
|
|
|
return new_username unless User.where(username_lower: new_username).exists?
|
2015-03-07 05:44:54 +08:00
|
|
|
end
|
2018-06-07 13:28:18 +08:00
|
|
|
raise "Failed to generate an anon username"
|
|
|
|
end
|
2018-05-01 01:42:51 +08:00
|
|
|
|
|
|
|
def ip_where(column = 'user_id')
|
|
|
|
["#{column} = :user_id AND ip_address IS NOT NULL", user_id: @user.id]
|
2015-03-07 05:44:54 +08:00
|
|
|
end
|
2018-05-01 01:42:51 +08:00
|
|
|
|
|
|
|
def anonymize_ips(new_ip)
|
|
|
|
@user.ip_address = new_ip
|
|
|
|
@user.registration_ip_address = new_ip
|
|
|
|
|
|
|
|
IncomingLink.where(ip_where('current_user_id')).update_all(ip_address: new_ip)
|
|
|
|
ScreenedEmail.where(email: @prev_email).update_all(ip_address: new_ip)
|
|
|
|
SearchLog.where(ip_where).update_all(ip_address: new_ip)
|
|
|
|
TopicLinkClick.where(ip_where).update_all(ip_address: new_ip)
|
|
|
|
TopicViewItem.where(ip_where).update_all(ip_address: new_ip)
|
|
|
|
UserHistory.where(ip_where('acting_user_id')).update_all(ip_address: new_ip)
|
|
|
|
UserProfileView.where(ip_where).update_all(ip_address: new_ip)
|
|
|
|
|
|
|
|
# UserHistory for delete_user logs the user's IP. Note this is quite ugly but we don't
|
|
|
|
# have a better way of querying on details right now.
|
|
|
|
UserHistory.where(
|
|
|
|
"action = :action AND details LIKE 'id: #{@user.id}\n%'",
|
|
|
|
action: UserHistory.actions[:delete_user]
|
|
|
|
).update_all(ip_address: new_ip)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2015-03-07 05:44:54 +08:00
|
|
|
end
|