From 14f436c457560862fafabd753eb314c8b8a8e674 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 17 Jan 2022 09:41:33 +0100 Subject: Add notifications for statuses deleted by moderators (#17204) --- app/models/admin/account_action.rb | 28 ++++------ app/models/admin/status_batch_action.rb | 92 +++++++++++++++++++++++++++++++++ app/models/admin/status_filter.rb | 41 +++++++++++++++ 3 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 app/models/admin/status_batch_action.rb create mode 100644 app/models/admin/status_filter.rb (limited to 'app/models/admin') diff --git a/app/models/admin/account_action.rb b/app/models/admin/account_action.rb index bf222391f..d3be4be3f 100644 --- a/app/models/admin/account_action.rb +++ b/app/models/admin/account_action.rb @@ -33,7 +33,7 @@ class Admin::AccountAction def save! ApplicationRecord.transaction do process_action! - process_warning! + process_strike! end process_email! @@ -74,20 +74,14 @@ class Admin::AccountAction 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? + def process_strike! + @warning = target_account.strikes.create!( + account: current_account, + report: report, + action: type, + text: text_for_warning, + status_ids: status_ids + ) end def process_reports! @@ -143,7 +137,7 @@ class Admin::AccountAction end def process_email! - UserMailer.warning(target_account.user, warning, status_ids).deliver_later! if warnable? + UserMailer.warning(target_account.user, warning).deliver_later! if warnable? end def warnable? @@ -151,7 +145,7 @@ class Admin::AccountAction end def status_ids - report.status_ids if report && include_statuses + report.status_ids if with_report? && include_statuses end def reports diff --git a/app/models/admin/status_batch_action.rb b/app/models/admin/status_batch_action.rb new file mode 100644 index 000000000..319deff98 --- /dev/null +++ b/app/models/admin/status_batch_action.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +class Admin::StatusBatchAction + include ActiveModel::Model + include AccountableConcern + include Authorization + + attr_accessor :current_account, :type, + :status_ids, :report_id + + def save! + process_action! + end + + private + + def statuses + Status.with_discarded.where(id: status_ids) + end + + def process_action! + return if status_ids.empty? + + case type + when 'delete' + handle_delete! + when 'report' + handle_report! + when 'remove_from_report' + handle_remove_from_report! + end + end + + def handle_delete! + statuses.each { |status| authorize(status, :destroy?) } + + ApplicationRecord.transaction do + statuses.each do |status| + status.discard + log_action(:destroy, status) + end + + if with_report? + report.resolve!(current_account) + log_action(:resolve, report) + end + + @warning = target_account.strikes.create!( + action: :delete_statuses, + account: current_account, + report: report, + status_ids: status_ids + ) + + statuses.each { |status| Tombstone.find_or_create_by(uri: status.uri, account: status.account, by_moderator: true) } unless target_account.local? + end + + UserMailer.warning(target_account.user, @warning).deliver_later! if target_account.local? + RemovalWorker.push_bulk(status_ids) { |status_id| [status_id, preserve: target_account.local?, immediate: !target_account.local?] } + end + + def handle_report! + @report = Report.new(report_params) unless with_report? + @report.status_ids = (@report.status_ids + status_ids.map(&:to_i)).uniq + @report.save! + + @report_id = @report.id + end + + def handle_remove_from_report! + return unless with_report? + + report.status_ids -= status_ids.map(&:to_i) + report.save! + end + + def report + @report ||= Report.find(report_id) if report_id.present? + end + + def with_report? + !report.nil? + end + + def target_account + @target_account ||= statuses.first.account + end + + def report_params + { account: current_account, target_account: target_account } + end +end diff --git a/app/models/admin/status_filter.rb b/app/models/admin/status_filter.rb new file mode 100644 index 000000000..ce5bb5f46 --- /dev/null +++ b/app/models/admin/status_filter.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +class Admin::StatusFilter + KEYS = %i( + media + id + report_id + ).freeze + + attr_reader :params + + def initialize(account, params) + @account = account + @params = params + end + + def results + scope = @account.statuses.where(visibility: [:public, :unlisted]) + + params.each do |key, value| + next if %w(page report_id).include?(key.to_s) + + scope.merge!(scope_for(key, value.to_s.strip)) if value.present? + end + + scope + end + + private + + def scope_for(key, value) + case key.to_s + when 'media' + Status.joins(:media_attachments).merge(@account.media_attachments.reorder(nil)).group(:id) + when 'id' + Status.where(id: value) + else + raise "Unknown filter: #{key}" + end + end +end -- cgit