mirror of
https://github.com/discourse/discourse.git
synced 2024-12-30 08:33:45 +08:00
118f7869bb
This commit introduces a new feature that allows staff to bulk select and delete users directly from the users list at `/admin/users/list`. The main use-case for this feature is make deleting spammers easier when a site is under a large spam attack. Internal topic: t/140321.
77 lines
1.9 KiB
Ruby
77 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class User::BulkDestroy
|
|
include Service::Base
|
|
|
|
params do
|
|
attribute :user_ids, :array
|
|
|
|
validates :user_ids, length: { maximum: 100 }
|
|
end
|
|
|
|
model :users
|
|
policy :can_delete_users
|
|
step :delete
|
|
|
|
private
|
|
|
|
def fetch_users(params:)
|
|
ids = params.user_ids
|
|
# this order cluase ensures we retrieve the users in the same order as the
|
|
# IDs in the param. we do this to ensure the users are deleted in the same
|
|
# order as they're selected in the UI
|
|
User.where(id: ids).order(DB.sql_fragment("array_position(ARRAY[?], users.id)", ids))
|
|
end
|
|
|
|
def can_delete_users(guardian:, users:)
|
|
users.all? { |u| guardian.can_delete_user?(u) }
|
|
end
|
|
|
|
def delete(users:, guardian:)
|
|
users
|
|
.find_each
|
|
.with_index(1) do |user, position|
|
|
success =
|
|
UserDestroyer.new(guardian.user).destroy(
|
|
user,
|
|
delete_posts: true,
|
|
prepare_for_destroy: true,
|
|
context: I18n.t("staff_action_logs.bulk_user_delete"),
|
|
)
|
|
|
|
if success
|
|
publish_progress(
|
|
guardian.user,
|
|
{ position:, username: user.username, total: users.size, success: true },
|
|
)
|
|
else
|
|
publish_progress(
|
|
guardian.user,
|
|
{
|
|
position:,
|
|
username: user.username,
|
|
total: users.size,
|
|
failed: true,
|
|
error: user.errors.full_messages.join(", "),
|
|
},
|
|
)
|
|
end
|
|
rescue => err
|
|
publish_progress(
|
|
guardian.user,
|
|
{
|
|
position:,
|
|
username: user.username,
|
|
total: users.size,
|
|
failed: true,
|
|
error: err.message,
|
|
},
|
|
)
|
|
end
|
|
end
|
|
|
|
def publish_progress(actor, data)
|
|
::MessageBus.publish("/bulk-user-delete", data, user_ids: [actor.id])
|
|
end
|
|
end
|