Add batch suspend for accounts in admin UI (#17009)

This commit is contained in:
Eugen Rochko
2021-12-05 21:48:39 +01:00
committed by GitHub
parent 2e2ea6bb6b
commit 0fb9536d38
26 changed files with 312 additions and 278 deletions

View File

@ -125,6 +125,8 @@ class Account < ApplicationRecord
:unconfirmed_email,
:current_sign_in_ip,
:current_sign_in_at,
:created_at,
:sign_up_ip,
:confirmed?,
:approved?,
:pending?,

View File

@ -2,18 +2,15 @@
class AccountFilter
KEYS = %i(
local
remote
by_domain
active
pending
silenced
suspended
origin
status
permissions
username
by_domain
display_name
email
ip
staff
invited_by
order
).freeze
@ -21,11 +18,10 @@ class AccountFilter
def initialize(params)
@params = params
set_defaults!
end
def results
scope = Account.includes(:user).reorder(nil)
scope = Account.includes(:account_stat, user: [:session_activations, :invite_request]).without_instance_actor.reorder(nil)
params.each do |key, value|
scope.merge!(scope_for(key, value.to_s.strip)) if value.present?
@ -36,30 +32,16 @@ class AccountFilter
private
def set_defaults!
params['local'] = '1' if params['remote'].blank?
params['active'] = '1' if params['suspended'].blank? && params['silenced'].blank? && params['pending'].blank?
params['order'] = 'recent' if params['order'].blank?
end
def scope_for(key, value)
case key.to_s
when 'local'
Account.local.without_instance_actor
when 'remote'
Account.remote
when 'origin'
origin_scope(value)
when 'permissions'
permissions_scope(value)
when 'status'
status_scope(value)
when 'by_domain'
Account.where(domain: value)
when 'active'
Account.without_suspended
when 'pending'
accounts_with_users.merge(User.pending)
when 'disabled'
accounts_with_users.merge(User.disabled)
when 'silenced'
Account.silenced
when 'suspended'
Account.suspended
when 'username'
Account.matches_username(value)
when 'display_name'
@ -68,8 +50,8 @@ class AccountFilter
accounts_with_users.merge(User.matches_email(value))
when 'ip'
valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value)) : Account.none
when 'staff'
accounts_with_users.merge(User.staff)
when 'invited_by'
invited_by_scope(value)
when 'order'
order_scope(value)
else
@ -77,21 +59,56 @@ class AccountFilter
end
end
def order_scope(value)
case value
def origin_scope(value)
case value.to_s
when 'local'
Account.local
when 'remote'
Account.remote
else
raise "Unknown origin: #{value}"
end
end
def status_scope(value)
case value.to_s
when 'active'
params['remote'] ? Account.joins(:account_stat).by_recent_status : Account.joins(:user).by_recent_sign_in
Account.without_suspended
when 'pending'
accounts_with_users.merge(User.pending)
when 'suspended'
Account.suspended
else
raise "Unknown status: #{value}"
end
end
def order_scope(value)
case value.to_s
when 'active'
accounts_with_users.left_joins(:account_stat).order(Arel.sql('coalesce(users.current_sign_in_at, account_stats.last_status_at, to_timestamp(0)) desc, accounts.id desc'))
when 'recent'
Account.recent
when 'alphabetic'
Account.alphabetic
else
raise "Unknown order: #{value}"
end
end
def invited_by_scope(value)
Account.left_joins(user: :invite).merge(Invite.where(user_id: value.to_s))
end
def permissions_scope(value)
case value.to_s
when 'staff'
accounts_with_users.merge(User.staff)
else
raise "Unknown permissions: #{value}"
end
end
def accounts_with_users
Account.joins(:user)
Account.left_joins(:user)
end
def valid_ip?(value)

View File

@ -17,7 +17,7 @@ class Admin::ActionLog < ApplicationRecord
serialize :recorded_changes
belongs_to :account
belongs_to :target, polymorphic: true
belongs_to :target, polymorphic: true, optional: true
default_scope -> { order('id desc') }

View File

@ -11,6 +11,8 @@ class Admin::ActionLogFilter
assigned_to_self_report: { target_type: 'Report', action: 'assigned_to_self' }.freeze,
change_email_user: { target_type: 'User', action: 'change_email' }.freeze,
confirm_user: { target_type: 'User', action: 'confirm' }.freeze,
approve_user: { target_type: 'User', action: 'approve' }.freeze,
reject_user: { target_type: 'User', action: 'reject' }.freeze,
create_account_warning: { target_type: 'AccountWarning', action: 'create' }.freeze,
create_announcement: { target_type: 'Announcement', action: 'create' }.freeze,
create_custom_emoji: { target_type: 'CustomEmoji', action: 'create' }.freeze,

View File

@ -3,6 +3,7 @@
class Form::AccountBatch
include ActiveModel::Model
include Authorization
include AccountableConcern
include Payloadable
attr_accessor :account_ids, :action, :current_account
@ -25,19 +26,21 @@ class Form::AccountBatch
suppress_follow_recommendation!
when 'unsuppress_follow_recommendation'
unsuppress_follow_recommendation!
when 'suspend'
suspend!
end
end
private
def follow!
accounts.find_each do |target_account|
accounts.each do |target_account|
FollowService.new.call(current_account, target_account)
end
end
def unfollow!
accounts.find_each do |target_account|
accounts.each do |target_account|
UnfollowService.new.call(current_account, target_account)
end
end
@ -61,23 +64,31 @@ class Form::AccountBatch
end
def approve!
users = accounts.includes(:user).map(&:user)
users.each { |user| authorize(user, :approve?) }
.each(&:approve!)
accounts.includes(:user).find_each do |account|
approve_account(account)
end
end
def reject!
records = accounts.includes(:user)
accounts.includes(:user).find_each do |account|
reject_account(account)
end
end
records.each { |account| authorize(account.user, :reject?) }
.each { |account| DeleteAccountService.new.call(account, reserve_email: false, reserve_username: false) }
def suspend!
accounts.find_each do |account|
if account.user_pending?
reject_account(account)
else
suspend_account(account)
end
end
end
def suppress_follow_recommendation!
authorize(:follow_recommendation, :suppress?)
accounts.each do |account|
accounts.find_each do |account|
FollowRecommendationSuppression.create(account: account)
end
end
@ -87,4 +98,24 @@ class Form::AccountBatch
FollowRecommendationSuppression.where(account_id: account_ids).destroy_all
end
def reject_account(account)
authorize(account.user, :reject?)
log_action(:reject, account.user, username: account.username)
account.suspend!(origin: :local)
AccountDeletionWorker.perform_async(account.id, reserve_username: false)
end
def suspend_account(account)
authorize(account, :suspend?)
log_action(:suspend, account)
account.suspend!(origin: :local)
Admin::SuspensionWorker.perform_async(account.id)
end
def approve_account(account)
authorize(account.user, :approve?)
log_action(:approve, account.user)
account.user.approve!
end
end