From 93e8a15415c35dbe4089b5d20c08161646ba76b3 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 8 Jul 2023 20:00:02 +0200 Subject: [PATCH] Add forwarding of reported replies to servers being replied to (#25341) --- app/lib/activitypub/activity/flag.rb | 9 +++--- app/services/report_service.rb | 14 +++++---- spec/services/report_service_spec.rb | 43 +++++++++++++++++++++------- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/app/lib/activitypub/activity/flag.rb b/app/lib/activitypub/activity/flag.rb index dc1932f597..304cf0ad2f 100644 --- a/app/lib/activitypub/activity/flag.rb +++ b/app/lib/activitypub/activity/flag.rb @@ -4,13 +4,14 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity def perform return if skip_reports? - target_accounts = object_uris.filter_map { |uri| account_from_uri(uri) }.select(&:local?) - target_statuses_by_account = object_uris.filter_map { |uri| status_from_uri(uri) }.select(&:local?).group_by(&:account_id) + target_accounts = object_uris.filter_map { |uri| account_from_uri(uri) } + target_statuses_by_account = object_uris.filter_map { |uri| status_from_uri(uri) }.group_by(&:account_id) target_accounts.each do |target_account| - target_statuses = target_statuses_by_account[target_account.id] + target_statuses = target_statuses_by_account[target_account.id] + replied_to_accounts = Account.local.where(id: target_statuses.filter_map(&:in_reply_to_account_id)) - next if target_account.suspended? + next if target_account.suspended? || (!target_account.local? && replied_to_accounts.none?) ReportService.new.call( @account, diff --git a/app/services/report_service.rb b/app/services/report_service.rb index 0ce525b071..3444e1dfaf 100644 --- a/app/services/report_service.rb +++ b/app/services/report_service.rb @@ -45,11 +45,15 @@ class ReportService < BaseService end def forward_to_origin! - ActivityPub::DeliveryWorker.perform_async( - payload, - some_local_account.id, - @target_account.inbox_url - ) + # Send report to the server where the account originates from + ActivityPub::DeliveryWorker.perform_async(payload, some_local_account.id, @target_account.inbox_url) + + # Send report to servers to which the account was replying to, so they also have a chance to act + inbox_urls = Account.remote.where(id: Status.where(id: reported_status_ids).where.not(in_reply_to_account_id: nil).select(:in_reply_to_account_id)).inboxes - [@target_account.inbox_url] + + inbox_urls.each do |inbox_url| + ActivityPub::DeliveryWorker.perform_async(payload, some_local_account.id, inbox_url) + end end def forward? diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb index b8ceedb851..660ce3db23 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -17,24 +17,45 @@ RSpec.describe ReportService, type: :service do context 'with a remote account' do let(:remote_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') } + let(:forward) { false } before do stub_request(:post, 'http://example.com/inbox').to_return(status: 200) end - it 'sends ActivityPub payload when forward is true' do - subject.call(source_account, remote_account, forward: true) - expect(a_request(:post, 'http://example.com/inbox')).to have_been_made + context 'when forward is true' do + let(:forward) { true } + + it 'sends ActivityPub payload when forward is true' do + subject.call(source_account, remote_account, forward: forward) + expect(a_request(:post, 'http://example.com/inbox')).to have_been_made + end + + it 'has an uri' do + report = subject.call(source_account, remote_account, forward: forward) + expect(report.uri).to_not be_nil + end + + context 'when reporting a reply' do + let(:remote_thread_account) { Fabricate(:account, domain: 'foo.com', protocol: :activitypub, inbox_url: 'http://foo.com/inbox') } + let(:reported_status) { Fabricate(:status, account: remote_account, thread: Fabricate(:status, account: remote_thread_account)) } + + before do + stub_request(:post, 'http://foo.com/inbox').to_return(status: 200) + end + + it 'sends ActivityPub payload to the author of the replied-to post' do + subject.call(source_account, remote_account, status_ids: [reported_status.id], forward: forward) + expect(a_request(:post, 'http://foo.com/inbox')).to have_been_made + end + end end - it 'does not send anything when forward is false' do - subject.call(source_account, remote_account, forward: false) - expect(a_request(:post, 'http://example.com/inbox')).to_not have_been_made - end - - it 'has an uri' do - report = subject.call(source_account, remote_account, forward: true) - expect(report.uri).to_not be_nil + context 'when forward is false' do + it 'does not send anything' do + subject.call(source_account, remote_account, forward: forward) + expect(a_request(:post, 'http://example.com/inbox')).to_not have_been_made + end end end