Fix follower synchronization mechanism erroneously removing followers from multi-page collections ()

This commit is contained in:
Claire 2025-03-25 16:50:05 +01:00 committed by GitHub
parent 81b88095b4
commit 3edac14f02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 8 deletions
app/services/activitypub
spec/services/activitypub

View file

@ -57,6 +57,9 @@ class ActivityPub::SynchronizeFollowersService < BaseService
collection = fetch_collection(collection['first']) if collection['first'].present?
return unless collection.is_a?(Hash)
# Abort if we'd have to paginate through more than one page of followers
return if collection['next'].present?
case collection['type']
when 'Collection', 'CollectionPage'
as_array(collection['items'])

View file

@ -27,14 +27,14 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
}.with_indifferent_access
end
before do
alice.follow!(actor)
bob.follow!(actor)
mallory.request_follow!(actor)
end
shared_examples 'synchronizes followers' do
before do
alice.follow!(actor)
bob.follow!(actor)
mallory.request_follow!(actor)
allow(ActivityPub::DeliveryWorker).to receive(:perform_async)
subject.call(actor, collection_uri)
end
@ -46,7 +46,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
expect(mallory)
.to be_following(actor) # Convert follow request to follow when accepted
expect(ActivityPub::DeliveryWorker)
.to have_received(:perform_async).with(anything, eve.id, actor.inbox_url) # Send Undo Follow to actor
.to have_enqueued_sidekiq_job(anything, eve.id, actor.inbox_url) # Send Undo Follow to actor
end
end
@ -76,7 +76,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
it_behaves_like 'synchronizes followers'
end
context 'when the endpoint is a paginated Collection of actor URIs' do
context 'when the endpoint is a single-page paginated Collection of actor URIs' do
let(:payload) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
@ -96,5 +96,30 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
it_behaves_like 'synchronizes followers'
end
context 'when the endpoint is a paginated Collection of actor URIs with a next page' do
let(:payload) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
type: 'Collection',
id: collection_uri,
first: {
type: 'CollectionPage',
partOf: collection_uri,
items: items,
next: "#{collection_uri}/page2",
},
}.with_indifferent_access
end
before do
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
end
it 'does not change followers' do
expect { subject.call(actor, collection_uri) }
.to_not(change { actor.followers.reload.reorder(id: :asc).pluck(:id) })
end
end
end
end