Split status batch and moderation actions (#37970)
This commit is contained in:
parent
919b1e69b8
commit
e2c9426c77
@ -13,7 +13,7 @@ class Admin::Reports::ActionsController < Admin::BaseController
|
|||||||
|
|
||||||
case action_from_button
|
case action_from_button
|
||||||
when 'delete', 'mark_as_sensitive'
|
when 'delete', 'mark_as_sensitive'
|
||||||
Admin::StatusBatchAction.new(status_batch_action_params).save!
|
Admin::ModerationAction.new(moderation_action_params).save!
|
||||||
when 'silence', 'suspend'
|
when 'silence', 'suspend'
|
||||||
Admin::AccountAction.new(account_action_params).save!
|
Admin::AccountAction.new(account_action_params).save!
|
||||||
else
|
else
|
||||||
@ -25,9 +25,8 @@ class Admin::Reports::ActionsController < Admin::BaseController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def status_batch_action_params
|
def moderation_action_params
|
||||||
shared_params
|
shared_params
|
||||||
.merge(status_ids: @report.status_ids)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_action_params
|
def account_action_params
|
||||||
|
|||||||
@ -78,8 +78,6 @@ module Admin
|
|||||||
'report'
|
'report'
|
||||||
elsif params[:remove_from_report]
|
elsif params[:remove_from_report]
|
||||||
'remove_from_report'
|
'remove_from_report'
|
||||||
elsif params[:delete]
|
|
||||||
'delete'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -66,20 +66,6 @@ class Admin::AccountAction < Admin::BaseAction
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_strike!
|
|
||||||
@warning = target_account.strikes.create!(
|
|
||||||
account: current_account,
|
|
||||||
report: report,
|
|
||||||
action: type,
|
|
||||||
text: text_for_warning,
|
|
||||||
status_ids: status_ids
|
|
||||||
)
|
|
||||||
|
|
||||||
# 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? && type == 'none'
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_reports!
|
def process_reports!
|
||||||
# If we're doing "mark as resolved" on a single report,
|
# If we're doing "mark as resolved" on a single report,
|
||||||
# then we want to keep other reports open in case they
|
# then we want to keep other reports open in case they
|
||||||
@ -131,17 +117,6 @@ class Admin::AccountAction < Admin::BaseAction
|
|||||||
queue_suspension_worker! if type == 'suspend'
|
queue_suspension_worker! if type == 'suspend'
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_notification!
|
|
||||||
return unless warnable?
|
|
||||||
|
|
||||||
UserMailer.warning(target_account.user, warning).deliver_later!
|
|
||||||
LocalNotificationWorker.perform_async(target_account.id, warning.id, 'AccountWarning', 'moderation_warning')
|
|
||||||
end
|
|
||||||
|
|
||||||
def warnable?
|
|
||||||
send_email_notification? && target_account.local?
|
|
||||||
end
|
|
||||||
|
|
||||||
def status_ids
|
def status_ids
|
||||||
report.status_ids if with_report? && include_statuses?
|
report.status_ids if with_report? && include_statuses?
|
||||||
end
|
end
|
||||||
|
|||||||
@ -39,4 +39,27 @@ class Admin::BaseAction
|
|||||||
def with_report?
|
def with_report?
|
||||||
!report.nil?
|
!report.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def process_strike!(action = type)
|
||||||
|
@warning = target_account.strikes.create!(
|
||||||
|
account: current_account,
|
||||||
|
report: report,
|
||||||
|
action:,
|
||||||
|
text: text_for_warning,
|
||||||
|
status_ids: status_ids
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_notification!
|
||||||
|
return unless warnable?
|
||||||
|
|
||||||
|
UserMailer.warning(target_account.user, warning).deliver_later!
|
||||||
|
LocalNotificationWorker.perform_async(target_account.id, warning.id, 'AccountWarning', 'moderation_warning')
|
||||||
|
end
|
||||||
|
|
||||||
|
def warnable?
|
||||||
|
send_email_notification? && target_account.local?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
84
app/models/admin/moderation_action.rb
Normal file
84
app/models/admin/moderation_action.rb
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Admin::ModerationAction < Admin::BaseAction
|
||||||
|
TYPES = %w(
|
||||||
|
delete
|
||||||
|
mark_as_sensitive
|
||||||
|
).freeze
|
||||||
|
|
||||||
|
validates :report_id, presence: true
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def status_ids
|
||||||
|
report.status_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
def statuses
|
||||||
|
@statuses ||= Status.with_discarded.where(id: status_ids).reorder(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_action!
|
||||||
|
case type
|
||||||
|
when 'delete'
|
||||||
|
handle_delete!
|
||||||
|
when 'mark_as_sensitive'
|
||||||
|
handle_mark_as_sensitive!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_delete!
|
||||||
|
statuses.each { |status| authorize([:admin, status], :destroy?) }
|
||||||
|
|
||||||
|
ApplicationRecord.transaction do
|
||||||
|
statuses.each do |status|
|
||||||
|
status.discard_with_reblogs
|
||||||
|
log_action(:destroy, status)
|
||||||
|
end
|
||||||
|
|
||||||
|
report.resolve!(current_account)
|
||||||
|
log_action(:resolve, report)
|
||||||
|
|
||||||
|
process_strike!(:delete_statuses)
|
||||||
|
|
||||||
|
statuses.each { |status| Tombstone.find_or_create_by(uri: status.uri, account: status.account, by_moderator: true) } unless target_account.local?
|
||||||
|
end
|
||||||
|
|
||||||
|
process_notification!
|
||||||
|
|
||||||
|
RemovalWorker.push_bulk(status_ids) { |status_id| [status_id, { 'preserve' => target_account.local?, 'immediate' => !target_account.local? }] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_mark_as_sensitive!
|
||||||
|
representative_account = Account.representative
|
||||||
|
|
||||||
|
# Can't use a transaction here because UpdateStatusService queues
|
||||||
|
# Sidekiq jobs
|
||||||
|
statuses.includes(:media_attachments, preview_cards_status: :preview_card).find_each do |status|
|
||||||
|
next if status.discarded? || !(status.with_media? || status.with_preview_card?)
|
||||||
|
|
||||||
|
authorize([:admin, status], :update?)
|
||||||
|
|
||||||
|
if target_account.local?
|
||||||
|
UpdateStatusService.new.call(status, representative_account.id, sensitive: true)
|
||||||
|
else
|
||||||
|
status.update(sensitive: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
log_action(:update, status)
|
||||||
|
|
||||||
|
report.resolve!(current_account)
|
||||||
|
log_action(:resolve, report)
|
||||||
|
end
|
||||||
|
|
||||||
|
process_strike!(:mark_statuses_as_sensitive)
|
||||||
|
|
||||||
|
process_notification!
|
||||||
|
end
|
||||||
|
|
||||||
|
def target_account
|
||||||
|
report.target_account
|
||||||
|
end
|
||||||
|
|
||||||
|
def text_for_warning = text
|
||||||
|
end
|
||||||
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
class Admin::StatusBatchAction < Admin::BaseAction
|
class Admin::StatusBatchAction < Admin::BaseAction
|
||||||
TYPES = %w(
|
TYPES = %w(
|
||||||
delete
|
|
||||||
mark_as_sensitive
|
|
||||||
report
|
report
|
||||||
remove_from_report
|
remove_from_report
|
||||||
).freeze
|
).freeze
|
||||||
@ -20,10 +18,6 @@ class Admin::StatusBatchAction < Admin::BaseAction
|
|||||||
return if status_ids.empty?
|
return if status_ids.empty?
|
||||||
|
|
||||||
case type
|
case type
|
||||||
when 'delete'
|
|
||||||
handle_delete!
|
|
||||||
when 'mark_as_sensitive'
|
|
||||||
handle_mark_as_sensitive!
|
|
||||||
when 'report'
|
when 'report'
|
||||||
handle_report!
|
handle_report!
|
||||||
when 'remove_from_report'
|
when 'remove_from_report'
|
||||||
@ -31,71 +25,6 @@ class Admin::StatusBatchAction < Admin::BaseAction
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_delete!
|
|
||||||
statuses.each { |status| authorize([:admin, status], :destroy?) }
|
|
||||||
|
|
||||||
ApplicationRecord.transaction do
|
|
||||||
statuses.each do |status|
|
|
||||||
status.discard_with_reblogs
|
|
||||||
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,
|
|
||||||
text: text
|
|
||||||
)
|
|
||||||
|
|
||||||
statuses.each { |status| Tombstone.find_or_create_by(uri: status.uri, account: status.account, by_moderator: true) } unless target_account.local?
|
|
||||||
end
|
|
||||||
|
|
||||||
process_notification!
|
|
||||||
|
|
||||||
RemovalWorker.push_bulk(status_ids) { |status_id| [status_id, { 'preserve' => target_account.local?, 'immediate' => !target_account.local? }] }
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_mark_as_sensitive!
|
|
||||||
representative_account = Account.representative
|
|
||||||
|
|
||||||
# Can't use a transaction here because UpdateStatusService queues
|
|
||||||
# Sidekiq jobs
|
|
||||||
statuses.includes(:media_attachments, preview_cards_status: :preview_card).find_each do |status|
|
|
||||||
next if status.discarded? || !(status.with_media? || status.with_preview_card?)
|
|
||||||
|
|
||||||
authorize([:admin, status], :update?)
|
|
||||||
|
|
||||||
if target_account.local?
|
|
||||||
UpdateStatusService.new.call(status, representative_account.id, sensitive: true)
|
|
||||||
else
|
|
||||||
status.update(sensitive: true)
|
|
||||||
end
|
|
||||||
|
|
||||||
log_action(:update, status)
|
|
||||||
|
|
||||||
if with_report?
|
|
||||||
report.resolve!(current_account)
|
|
||||||
log_action(:resolve, report)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@warning = target_account.strikes.create!(
|
|
||||||
action: :mark_statuses_as_sensitive,
|
|
||||||
account: current_account,
|
|
||||||
report: report,
|
|
||||||
status_ids: status_ids,
|
|
||||||
text: text
|
|
||||||
)
|
|
||||||
|
|
||||||
process_notification!
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_report!
|
def handle_report!
|
||||||
@report = Report.new(report_params) unless with_report?
|
@report = Report.new(report_params) unless with_report?
|
||||||
@report.status_ids = (@report.status_ids + allowed_status_ids).uniq
|
@report.status_ids = (@report.status_ids + allowed_status_ids).uniq
|
||||||
@ -111,17 +40,6 @@ class Admin::StatusBatchAction < Admin::BaseAction
|
|||||||
report.save!
|
report.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_notification!
|
|
||||||
return unless warnable?
|
|
||||||
|
|
||||||
UserMailer.warning(target_account.user, @warning).deliver_later!
|
|
||||||
LocalNotificationWorker.perform_async(target_account.id, @warning.id, 'AccountWarning', 'moderation_warning')
|
|
||||||
end
|
|
||||||
|
|
||||||
def warnable?
|
|
||||||
send_email_notification && target_account.local?
|
|
||||||
end
|
|
||||||
|
|
||||||
def target_account
|
def target_account
|
||||||
@target_account ||= statuses.first.account
|
@target_account ||= statuses.first.account
|
||||||
end
|
end
|
||||||
|
|||||||
57
spec/models/admin/moderation_action_spec.rb
Normal file
57
spec/models/admin/moderation_action_spec.rb
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Admin::ModerationAction do
|
||||||
|
subject do
|
||||||
|
described_class.new(
|
||||||
|
current_account:,
|
||||||
|
type:,
|
||||||
|
report_id:,
|
||||||
|
text:
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:current_account) { Fabricate(:admin_user).account }
|
||||||
|
let(:target_account) { Fabricate(:account) }
|
||||||
|
let(:statuses) { Fabricate.times(2, :status, account: target_account) }
|
||||||
|
let(:status_ids) { statuses.map(&:id) }
|
||||||
|
let(:report) { Fabricate(:report, target_account:, status_ids:) }
|
||||||
|
let(:report_id) { report.id }
|
||||||
|
let(:text) { 'test' }
|
||||||
|
|
||||||
|
describe '#save!' do
|
||||||
|
context 'when `type` is `delete`' do
|
||||||
|
let(:type) { 'delete' }
|
||||||
|
|
||||||
|
it 'discards the statuses' do
|
||||||
|
subject.save!
|
||||||
|
|
||||||
|
statuses.each do |status|
|
||||||
|
expect(status.reload).to be_discarded
|
||||||
|
end
|
||||||
|
expect(report.reload).to be_action_taken
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when `type` is `mark_as_sensitive`' do
|
||||||
|
let(:type) { 'mark_as_sensitive' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
preview_card = Fabricate(:preview_card)
|
||||||
|
statuses.each do |status|
|
||||||
|
PreviewCardsStatus.create!(status:, preview_card:)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'marks the statuses as sensitive' do
|
||||||
|
subject.save!
|
||||||
|
|
||||||
|
statuses.each do |status|
|
||||||
|
expect(status.reload).to be_sensitive
|
||||||
|
end
|
||||||
|
expect(report.reload).to be_action_taken
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -22,39 +22,6 @@ RSpec.describe Admin::StatusBatchAction do
|
|||||||
let(:text) { 'test' }
|
let(:text) { 'test' }
|
||||||
|
|
||||||
describe '#save!' do
|
describe '#save!' do
|
||||||
context 'when `type` is `delete`' do
|
|
||||||
let(:type) { 'delete' }
|
|
||||||
|
|
||||||
it 'discards the statuses' do
|
|
||||||
subject.save!
|
|
||||||
|
|
||||||
statuses.each do |status|
|
|
||||||
expect(status.reload).to be_discarded
|
|
||||||
end
|
|
||||||
expect(report.reload).to be_action_taken
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when `type` is `mark_as_sensitive`' do
|
|
||||||
let(:type) { 'mark_as_sensitive' }
|
|
||||||
|
|
||||||
before do
|
|
||||||
preview_card = Fabricate(:preview_card)
|
|
||||||
statuses.each do |status|
|
|
||||||
PreviewCardsStatus.create!(status:, preview_card:)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'marks the statuses as sensitive' do
|
|
||||||
subject.save!
|
|
||||||
|
|
||||||
statuses.each do |status|
|
|
||||||
expect(status.reload).to be_sensitive
|
|
||||||
end
|
|
||||||
expect(report.reload).to be_action_taken
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when `type` is `report`' do
|
context 'when `type` is `report`' do
|
||||||
let(:report_id) { nil }
|
let(:report_id) { nil }
|
||||||
let(:type) { 'report' }
|
let(:type) { 'report' }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user