users: delete accounts with invalid names.
Add a fix script to delete all accounts with invalid usernames. Also change it so the owner-level user can delete accounts belonging to other users. Users who have logged in in the last year and who have a valid email address will be given a one week warning. After that all accounts with invalid names will be deleted. Anyone who has visited the site in the last 6 months will have already seen a warning page that their name must be changed to keep using the site.
This commit is contained in:
@@ -9,7 +9,7 @@ module Maintenance
|
||||
end
|
||||
|
||||
def destroy
|
||||
deletion = UserDeletion.new(CurrentUser.user, params.dig(:user, :password), request)
|
||||
deletion = UserDeletion.new(user: CurrentUser.user, deleter: CurrentUser.user, password: params.dig(:user, :password), request: request)
|
||||
deletion.delete!
|
||||
|
||||
if deletion.errors.none?
|
||||
|
||||
@@ -7,16 +7,18 @@
|
||||
class UserDeletion
|
||||
include ActiveModel::Validations
|
||||
|
||||
attr_reader :user, :password, :request
|
||||
attr_reader :user, :deleter, :password, :request
|
||||
|
||||
validate :validate_deletion
|
||||
|
||||
# Initialize a user deletion.
|
||||
# @param user [User] the user to delete
|
||||
# @param user [User] the user performing the deletion
|
||||
# @param password [String] the user's password (for confirmation)
|
||||
# @param request the HTTP request (for logging the deletion in the user event log)
|
||||
def initialize(user, password, request)
|
||||
def initialize(user:, deleter: user, password: nil, request: nil)
|
||||
@user = user
|
||||
@deleter = deleter
|
||||
@password = password
|
||||
@request = request
|
||||
end
|
||||
@@ -40,11 +42,11 @@ class UserDeletion
|
||||
private
|
||||
|
||||
def create_mod_action
|
||||
ModAction.log("deleted user ##{user.id}", :user_delete, user)
|
||||
ModAction.log("deleted user ##{user.id}", :user_delete, deleter)
|
||||
end
|
||||
|
||||
def create_user_event
|
||||
UserEvent.create_from_request!(user, :user_deletion, request)
|
||||
UserEvent.create_from_request!(user, :user_deletion, request) if request.present?
|
||||
end
|
||||
|
||||
def clear_saved_searches
|
||||
@@ -79,16 +81,30 @@ class UserDeletion
|
||||
end
|
||||
|
||||
def validate_deletion
|
||||
if !user.authenticate_password(password)
|
||||
errors.add(:base, "Password is incorrect")
|
||||
end
|
||||
if user == deleter
|
||||
if !user.authenticate_password(password)
|
||||
errors.add(:base, "Password is incorrect")
|
||||
end
|
||||
|
||||
if user.is_admin?
|
||||
errors.add(:base, "Admins cannot delete their account")
|
||||
end
|
||||
if user.is_admin?
|
||||
errors.add(:base, "Admins cannot delete their account")
|
||||
end
|
||||
|
||||
if user.is_banned?
|
||||
errors.add(:base, "You cannot delete your account if you are banned")
|
||||
if user.is_banned?
|
||||
errors.add(:base, "You cannot delete your account if you are banned")
|
||||
end
|
||||
else
|
||||
if !deleter.is_owner?
|
||||
errors.add(:base, "You cannot delete an account belonging to another user")
|
||||
end
|
||||
|
||||
if user.is_gold?
|
||||
errors.add(:base, "You cannot delete a privileged account")
|
||||
end
|
||||
|
||||
if user.created_at.before?(6.months.ago)
|
||||
errors.add(:base, "You cannot delete a recent account")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
57
script/fixes/115_delete_invalid_users.rb
Executable file
57
script/fixes/115_delete_invalid_users.rb
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require_relative "base"
|
||||
|
||||
def delete(user)
|
||||
return if !user.name_invalid?
|
||||
|
||||
if ENV.fetch("WARN", "false").truthy? && user.can_receive_email?
|
||||
Dmail.create_automated(to: user, title: "Action required: Change your username or your Danbooru account will be deleted", body: <<~EOS)
|
||||
Your current Danbooru username is invalid. Your Danbooru account will be deleted in one week unless you change your username. Use the link below to change your username:
|
||||
|
||||
* "Change username":/user_name_change_requests/new
|
||||
EOS
|
||||
|
||||
puts "[WARN] id=#{user.id} user='#{user.name}' email='#{user.email_address.address}'"
|
||||
elsif ENV.fetch("DELETE", "false").truthy?
|
||||
UserDeletion.new(user: user, deleter: User.owner).delete!
|
||||
puts "[DELETE] id=#{user.id} user='#{user.name}'"
|
||||
end
|
||||
end
|
||||
|
||||
with_confirmation do
|
||||
condition = ENV.fetch("COND", "TRUE")
|
||||
users = User.where(Arel.sql(condition))
|
||||
|
||||
users.where("length(name) = 1").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
|
||||
users.where("length(name) >= 25").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
|
||||
users.where_regex(:name, "[[:space:]]").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
|
||||
users.where_regex(:name, "^[[:punct:]]").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
|
||||
users.where_regex(:name, "[[:punct:]]$").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
|
||||
users.where_regex(:name, "\.(html|json|xml|atom|rss|txt|js|css|csv|png|jpg|jpeg|gif|png|mp4|webm|zip|pdf|exe|sitemap)$").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
|
||||
users.where_regex(:name, "[`~!@#$%^&*()+={}\[\]|\\:;'\"<>,?/]").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
|
||||
users.where_not_regex(:name, "[[:ascii:]]").find_each do |user|
|
||||
delete(user)
|
||||
end
|
||||
end
|
||||
@@ -12,7 +12,7 @@ class UserDeletionTest < ActiveSupport::TestCase
|
||||
context "for an invalid password" do
|
||||
should "fail" do
|
||||
@user = create(:user)
|
||||
@deletion = UserDeletion.new(@user, "wrongpassword", @request)
|
||||
@deletion = UserDeletion.new(user: @user, password: "wrongpassword", request: @request)
|
||||
@deletion.delete!
|
||||
assert_includes(@deletion.errors[:base], "Password is incorrect")
|
||||
end
|
||||
@@ -21,7 +21,7 @@ class UserDeletionTest < ActiveSupport::TestCase
|
||||
context "for an admin" do
|
||||
should "fail" do
|
||||
@user = create(:admin_user)
|
||||
@deletion = UserDeletion.new(@user, "password", @request)
|
||||
@deletion = UserDeletion.new(user: @user, password: "password", request: @request)
|
||||
@deletion.delete!
|
||||
assert_includes(@deletion.errors[:base], "Admins cannot delete their account")
|
||||
end
|
||||
@@ -30,7 +30,7 @@ class UserDeletionTest < ActiveSupport::TestCase
|
||||
context "for a banned user" do
|
||||
should "fail" do
|
||||
@user = create(:banned_user)
|
||||
@deletion = UserDeletion.new(@user, "password", @request)
|
||||
@deletion = UserDeletion.new(user: @user, password: "password", request: @request)
|
||||
@deletion.delete!
|
||||
assert_includes(@deletion.errors[:base], "You cannot delete your account if you are banned")
|
||||
end
|
||||
@@ -40,7 +40,7 @@ class UserDeletionTest < ActiveSupport::TestCase
|
||||
context "a valid user deletion" do
|
||||
setup do
|
||||
@user = create(:user, name: "foo", email_address: build(:email_address))
|
||||
@deletion = UserDeletion.new(@user, "password", @request)
|
||||
@deletion = UserDeletion.new(user: @user, password: "password", request: @request)
|
||||
end
|
||||
|
||||
should "blank out the email" do
|
||||
@@ -82,4 +82,24 @@ class UserDeletionTest < ActiveSupport::TestCase
|
||||
assert_equal(0, @post.reload.fav_count)
|
||||
end
|
||||
end
|
||||
|
||||
context "deleting another user's account" do
|
||||
should "work for the owner-level user" do
|
||||
@user = create(:user)
|
||||
@deletion = UserDeletion.new(user: @user, deleter: create(:owner_user))
|
||||
|
||||
@deletion.delete!
|
||||
assert_equal("user_#{@user.id}", @user.reload.name)
|
||||
assert_equal(true, ModAction.exists?(description: "deleted user ##{@user.id}", creator: @deletion.deleter))
|
||||
end
|
||||
|
||||
should "not work for other users" do
|
||||
@user = create(:user)
|
||||
@deletion = UserDeletion.new(user: @user, deleter: create(:admin_user))
|
||||
|
||||
@deletion.delete!
|
||||
assert_not_equal("user_#{@user.id}", @user.reload.name)
|
||||
assert_equal(0, ModAction.count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user