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
 |