mirror of
https://github.com/mastodon/mastodon.git
synced 2024-11-25 22:15:11 +01:00
b5f7e12817
Fix #12113
174 lines
3.9 KiB
Ruby
174 lines
3.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Admin::AccountAction
|
|
include ActiveModel::Model
|
|
include AccountableConcern
|
|
include Authorization
|
|
|
|
TYPES = %w(
|
|
none
|
|
disable
|
|
silence
|
|
suspend
|
|
).freeze
|
|
|
|
attr_accessor :target_account,
|
|
:current_account,
|
|
:type,
|
|
:text,
|
|
:report_id,
|
|
:warning_preset_id
|
|
|
|
attr_reader :warning, :send_email_notification, :include_statuses
|
|
|
|
def send_email_notification=(value)
|
|
@send_email_notification = ActiveModel::Type::Boolean.new.cast(value)
|
|
end
|
|
|
|
def include_statuses=(value)
|
|
@include_statuses = ActiveModel::Type::Boolean.new.cast(value)
|
|
end
|
|
|
|
def save!
|
|
ApplicationRecord.transaction do
|
|
process_action!
|
|
process_warning!
|
|
end
|
|
|
|
process_email!
|
|
process_reports!
|
|
process_queue!
|
|
end
|
|
|
|
def report
|
|
@report ||= Report.find(report_id) if report_id.present?
|
|
end
|
|
|
|
def with_report?
|
|
!report.nil?
|
|
end
|
|
|
|
class << self
|
|
def types_for_account(account)
|
|
if account.local?
|
|
TYPES
|
|
else
|
|
TYPES - %w(none disable)
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def process_action!
|
|
case type
|
|
when 'none'
|
|
handle_resolve!
|
|
when 'disable'
|
|
handle_disable!
|
|
when 'silence'
|
|
handle_silence!
|
|
when 'suspend'
|
|
handle_suspend!
|
|
end
|
|
end
|
|
|
|
def process_warning!
|
|
return unless warnable?
|
|
|
|
authorize(target_account, :warn?)
|
|
|
|
@warning = AccountWarning.create!(target_account: target_account,
|
|
account: current_account,
|
|
action: type,
|
|
text: text_for_warning)
|
|
|
|
# A log entry is only interesting if the warning contains
|
|
# custom text from someone. Otherwise it's just noise.
|
|
|
|
log_action(:create, warning) if warning.text.present?
|
|
end
|
|
|
|
def process_reports!
|
|
# If we're doing "mark as resolved" on a single report,
|
|
# then we want to keep other reports open in case they
|
|
# contain new actionable information.
|
|
#
|
|
# Otherwise, we will mark all unresolved reports about
|
|
# the account as resolved.
|
|
|
|
reports.each { |report| authorize(report, :update?) }
|
|
|
|
reports.each do |report|
|
|
log_action(:resolve, report)
|
|
report.resolve!(current_account)
|
|
end
|
|
end
|
|
|
|
def handle_resolve!
|
|
if with_report? && report.account_id == -99 && target_account.trust_level == Account::TRUST_LEVELS[:untrusted]
|
|
# This is an automated report and it is being dismissed, so it's
|
|
# a false positive, in which case update the account's trust level
|
|
# to prevent further spam checks
|
|
|
|
target_account.update(trust_level: Account::TRUST_LEVELS[:trusted])
|
|
end
|
|
end
|
|
|
|
def handle_disable!
|
|
authorize(target_account.user, :disable?)
|
|
log_action(:disable, target_account.user)
|
|
target_account.user&.disable!
|
|
end
|
|
|
|
def handle_silence!
|
|
authorize(target_account, :silence?)
|
|
log_action(:silence, target_account)
|
|
target_account.silence!
|
|
end
|
|
|
|
def handle_suspend!
|
|
authorize(target_account, :suspend?)
|
|
log_action(:suspend, target_account)
|
|
target_account.suspend!
|
|
end
|
|
|
|
def text_for_warning
|
|
[warning_preset&.text, text].compact.join("\n\n")
|
|
end
|
|
|
|
def queue_suspension_worker!
|
|
Admin::SuspensionWorker.perform_async(target_account.id)
|
|
end
|
|
|
|
def process_queue!
|
|
queue_suspension_worker! if type == 'suspend'
|
|
end
|
|
|
|
def process_email!
|
|
UserMailer.warning(target_account.user, warning, status_ids).deliver_now! if warnable?
|
|
end
|
|
|
|
def warnable?
|
|
send_email_notification && target_account.local?
|
|
end
|
|
|
|
def status_ids
|
|
@report.status_ids if @report && include_statuses
|
|
end
|
|
|
|
def reports
|
|
@reports ||= begin
|
|
if type == 'none' && with_report?
|
|
[report]
|
|
else
|
|
Report.where(target_account: target_account).unresolved
|
|
end
|
|
end
|
|
end
|
|
|
|
def warning_preset
|
|
@warning_preset ||= AccountWarningPreset.find(warning_preset_id) if warning_preset_id.present?
|
|
end
|
|
end
|