Add support for paginating partial collections in SynchronizeFollowersService
(#34277)
This commit is contained in:
parent
dd6c573cc3
commit
59e189ad3c
3 changed files with 128 additions and 26 deletions
|
@ -10,7 +10,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||
let(:bob) { Fabricate(:account, username: 'bob') }
|
||||
let(:eve) { Fabricate(:account, username: 'eve') }
|
||||
let(:mallory) { Fabricate(:account, username: 'mallory') }
|
||||
let(:collection_uri) { 'http://example.com/partial-followers' }
|
||||
let(:collection_uri) { 'https://example.com/partial-followers' }
|
||||
|
||||
let(:items) do
|
||||
[alice, eve, mallory].map do |account|
|
||||
|
@ -97,7 +97,76 @@ 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
|
||||
context 'when the endpoint is a paginated Collection of actor URIs split across multiple pages' do
|
||||
before do
|
||||
stub_request(:get, 'https://example.com/partial-followers')
|
||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: Oj.dump({
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
type: 'Collection',
|
||||
id: 'https://example.com/partial-followers',
|
||||
first: 'https://example.com/partial-followers/1',
|
||||
}))
|
||||
|
||||
stub_request(:get, 'https://example.com/partial-followers/1')
|
||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: Oj.dump({
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
type: 'CollectionPage',
|
||||
id: 'https://example.com/partial-followers/1',
|
||||
partOf: 'https://example.com/partial-followers',
|
||||
next: 'https://example.com/partial-followers/2',
|
||||
items: [alice, eve].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
|
||||
}))
|
||||
|
||||
stub_request(:get, 'https://example.com/partial-followers/2')
|
||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: Oj.dump({
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
type: 'CollectionPage',
|
||||
id: 'https://example.com/partial-followers/2',
|
||||
partOf: 'https://example.com/partial-followers',
|
||||
items: ActivityPub::TagManager.instance.uri_for(mallory),
|
||||
}))
|
||||
end
|
||||
|
||||
it_behaves_like 'synchronizes followers'
|
||||
end
|
||||
|
||||
context 'when the endpoint is a paginated Collection of actor URIs split across, but one page errors out' do
|
||||
before do
|
||||
stub_request(:get, 'https://example.com/partial-followers')
|
||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: Oj.dump({
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
type: 'Collection',
|
||||
id: 'https://example.com/partial-followers',
|
||||
first: 'https://example.com/partial-followers/1',
|
||||
}))
|
||||
|
||||
stub_request(:get, 'https://example.com/partial-followers/1')
|
||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: Oj.dump({
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
type: 'CollectionPage',
|
||||
id: 'https://example.com/partial-followers/1',
|
||||
partOf: 'https://example.com/partial-followers',
|
||||
next: 'https://example.com/partial-followers/2',
|
||||
items: [mallory].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
|
||||
}))
|
||||
|
||||
stub_request(:get, 'https://example.com/partial-followers/2')
|
||||
.to_return(status: 404)
|
||||
end
|
||||
|
||||
it 'confirms pending follow request but does not remove extra followers' do
|
||||
previous_follower_ids = actor.followers.pluck(:id)
|
||||
|
||||
subject.call(actor, collection_uri)
|
||||
|
||||
expect(previous_follower_ids - actor.followers.reload.pluck(:id))
|
||||
.to be_empty
|
||||
expect(mallory)
|
||||
.to be_following(actor)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the endpoint is a paginated Collection of actor URIs with more pages than we allow' do
|
||||
let(:payload) do
|
||||
{
|
||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||
|
@ -113,12 +182,19 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||
end
|
||||
|
||||
before do
|
||||
stub_const('ActivityPub::SynchronizeFollowersService::MAX_COLLECTION_PAGES', 1)
|
||||
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) })
|
||||
it 'confirms pending follow request but does not remove extra followers' do
|
||||
previous_follower_ids = actor.followers.pluck(:id)
|
||||
|
||||
subject.call(actor, collection_uri)
|
||||
|
||||
expect(previous_follower_ids - actor.followers.reload.pluck(:id))
|
||||
.to be_empty
|
||||
expect(mallory)
|
||||
.to be_following(actor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue