Merge pull request from GHSA-jhrq-qvrm-qr36
* Fix insufficient Content-Type checking of fetched ActivityStreams objects * Allow JSON-LD documents with multiple profiles
This commit is contained in:
		
							parent
							
								
									a8ee6fdd62
								
							
						
					
					
						commit
						9fee5e8526
					
				| @ -174,7 +174,19 @@ module JsonLdHelper | |||||||
|     build_request(uri, on_behalf_of, options: request_options).perform do |response| |     build_request(uri, on_behalf_of, options: request_options).perform do |response| | ||||||
|       raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error |       raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error | ||||||
| 
 | 
 | ||||||
|       body_to_json(response.body_with_limit) if response.code == 200 |       body_to_json(response.body_with_limit) if response.code == 200 && valid_activitypub_content_type?(response) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def valid_activitypub_content_type?(response) | ||||||
|  |     return true if response.mime_type == 'application/activity+json' | ||||||
|  | 
 | ||||||
|  |     # When the mime type is `application/ld+json`, we need to check the profile, | ||||||
|  |     # but `http.rb` does not parse it for us. | ||||||
|  |     return false unless response.mime_type == 'application/ld+json' | ||||||
|  | 
 | ||||||
|  |     response.headers[HTTP::Headers::CONTENT_TYPE]&.split(';')&.map(&:strip)&.any? do |str| | ||||||
|  |       str.start_with?('profile="') && str[9...-1].split.include?('https://www.w3.org/ns/activitystreams') | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -44,7 +44,7 @@ class FetchResourceService < BaseService | |||||||
|     @response_code = response.code |     @response_code = response.code | ||||||
|     return nil if response.code != 200 |     return nil if response.code != 200 | ||||||
| 
 | 
 | ||||||
|     if ['application/activity+json', 'application/ld+json'].include?(response.mime_type) |     if valid_activitypub_content_type?(response) | ||||||
|       body = response.body_with_limit |       body = response.body_with_limit | ||||||
|       json = body_to_json(body) |       json = body_to_json(body) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -56,15 +56,15 @@ describe JsonLdHelper do | |||||||
|   describe '#fetch_resource' do |   describe '#fetch_resource' do | ||||||
|     context 'when the second argument is false' do |     context 'when the second argument is false' do | ||||||
|       it 'returns resource even if the retrieved ID and the given URI does not match' do |       it 'returns resource even if the retrieved ID and the given URI does not match' do | ||||||
|         stub_request(:get, 'https://bob.test/').to_return body: '{"id": "https://alice.test/"}' |         stub_request(:get, 'https://bob.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://alice.test/').to_return body: '{"id": "https://alice.test/"}' |         stub_request(:get, 'https://alice.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) | ||||||
| 
 | 
 | ||||||
|         expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' }) |         expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do |       it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do | ||||||
|         stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://marvin.test/"}' |         stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://marvin.test/"}', headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://marvin.test/').to_return body: '{"id": "https://alice.test/"}' |         stub_request(:get, 'https://marvin.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) | ||||||
| 
 | 
 | ||||||
|         expect(fetch_resource('https://mallory.test/', false)).to be_nil |         expect(fetch_resource('https://mallory.test/', false)).to be_nil | ||||||
|       end |       end | ||||||
| @ -72,7 +72,7 @@ describe JsonLdHelper do | |||||||
| 
 | 
 | ||||||
|     context 'when the second argument is true' do |     context 'when the second argument is true' do | ||||||
|       it 'returns nil if the retrieved ID and the given URI does not match' do |       it 'returns nil if the retrieved ID and the given URI does not match' do | ||||||
|         stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://alice.test/"}' |         stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         expect(fetch_resource('https://mallory.test/', true)).to be_nil |         expect(fetch_resource('https://mallory.test/', true)).to be_nil | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| @ -80,12 +80,12 @@ describe JsonLdHelper do | |||||||
| 
 | 
 | ||||||
|   describe '#fetch_resource_without_id_validation' do |   describe '#fetch_resource_without_id_validation' do | ||||||
|     it 'returns nil if the status code is not 200' do |     it 'returns nil if the status code is not 200' do | ||||||
|       stub_request(:get, 'https://host.test/').to_return status: 400, body: '{}' |       stub_request(:get, 'https://host.test/').to_return(status: 400, body: '{}', headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       expect(fetch_resource_without_id_validation('https://host.test/')).to be_nil |       expect(fetch_resource_without_id_validation('https://host.test/')).to be_nil | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     it 'returns hash' do |     it 'returns hash' do | ||||||
|       stub_request(:get, 'https://host.test/').to_return status: 200, body: '{}' |       stub_request(:get, 'https://host.test/').to_return(status: 200, body: '{}', headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       expect(fetch_resource_without_id_validation('https://host.test/')).to eq({}) |       expect(fetch_resource_without_id_validation('https://host.test/')).to eq({}) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ RSpec.describe ActivityPub::Activity::Announce do | |||||||
|     context 'when sender is followed by a local account' do |     context 'when sender is followed by a local account' do | ||||||
|       before do |       before do | ||||||
|         Fabricate(:account).follow!(sender) |         Fabricate(:account).follow!(sender) | ||||||
|         stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json)) |         stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         subject.perform |         subject.perform | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
| @ -120,7 +120,7 @@ RSpec.describe ActivityPub::Activity::Announce do | |||||||
|       let(:object_json) { 'https://example.com/actor/hello-world' } |       let(:object_json) { 'https://example.com/actor/hello-world' } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json)) |         stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       context 'when the relay is enabled' do |       context 'when the relay is enabled' do | ||||||
|  | |||||||
| @ -72,11 +72,11 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do | |||||||
| 
 | 
 | ||||||
|   shared_examples 'sets pinned posts' do |   shared_examples 'sets pinned posts' do | ||||||
|     before do |     before do | ||||||
|       stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known)) |       stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined)) |       stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404) |       stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404) | ||||||
|       stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) |       stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null)) |       stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
| 
 | 
 | ||||||
|       subject.call(actor, note: true, hashtag: false) |       subject.call(actor, note: true, hashtag: false) | ||||||
|     end |     end | ||||||
| @ -94,7 +94,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do | |||||||
|   describe '#call' do |   describe '#call' do | ||||||
|     context 'when the endpoint is a Collection' do |     context 'when the endpoint is a Collection' do | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'sets pinned posts' |       it_behaves_like 'sets pinned posts' | ||||||
| @ -111,7 +111,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do | |||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'sets pinned posts' |       it_behaves_like 'sets pinned posts' | ||||||
| @ -120,7 +120,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do | |||||||
|         let(:items) { 'https://example.com/account/pinned/unknown-reachable' } |         let(:items) { 'https://example.com/account/pinned/unknown-reachable' } | ||||||
| 
 | 
 | ||||||
|         before do |         before do | ||||||
|           stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) |           stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|           subject.call(actor, note: true, hashtag: false) |           subject.call(actor, note: true, hashtag: false) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
| @ -147,7 +147,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do | |||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'sets pinned posts' |       it_behaves_like 'sets pinned posts' | ||||||
| @ -156,7 +156,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do | |||||||
|         let(:items) { 'https://example.com/account/pinned/unknown-reachable' } |         let(:items) { 'https://example.com/account/pinned/unknown-reachable' } | ||||||
| 
 | 
 | ||||||
|         before do |         before do | ||||||
|           stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable)) |           stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|           subject.call(actor, note: true, hashtag: false) |           subject.call(actor, note: true, hashtag: false) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d | |||||||
|   describe '#call' do |   describe '#call' do | ||||||
|     context 'when the endpoint is a Collection' do |     context 'when the endpoint is a Collection' do | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'sets featured tags' |       it_behaves_like 'sets featured tags' | ||||||
| @ -46,7 +46,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d | |||||||
| 
 | 
 | ||||||
|     context 'when the account already has featured tags' do |     context 'when the account already has featured tags' do | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
| 
 | 
 | ||||||
|         actor.featured_tags.create!(name: 'FoO') |         actor.featured_tags.create!(name: 'FoO') | ||||||
|         actor.featured_tags.create!(name: 'baz') |         actor.featured_tags.create!(name: 'baz') | ||||||
| @ -67,7 +67,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d | |||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'sets featured tags' |       it_behaves_like 'sets featured tags' | ||||||
| @ -88,7 +88,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d | |||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'sets featured tags' |       it_behaves_like 'sets featured tags' | ||||||
|  | |||||||
| @ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do | |||||||
|       before do |       before do | ||||||
|         actor[:inbox] = nil |         actor[:inbox] = nil | ||||||
| 
 | 
 | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
| @ -54,7 +54,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } |       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
| @ -75,7 +75,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } |       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| @ -98,7 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } |       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
| @ -114,7 +114,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } |       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
|  | |||||||
| @ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do | |||||||
|       before do |       before do | ||||||
|         actor[:inbox] = nil |         actor[:inbox] = nil | ||||||
| 
 | 
 | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
| @ -54,7 +54,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } |       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
| @ -75,7 +75,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } |       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| @ -98,7 +98,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } |       let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
| @ -114,7 +114,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do | |||||||
|       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } |       let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |         stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |         stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|       end |       end | ||||||
|  | |||||||
| @ -50,7 +50,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do | |||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   before do |   before do | ||||||
|     stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor)) |     stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|     stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) |     stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' }) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -59,7 +59,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do | |||||||
| 
 | 
 | ||||||
|     context 'when the key is a sub-object from the actor' do |     context 'when the key is a sub-object from the actor' do | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, public_key_id).to_return(body: Oj.dump(actor)) |         stub_request(:get, public_key_id).to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it 'returns the expected account' do |       it 'returns the expected account' do | ||||||
| @ -71,7 +71,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do | |||||||
|       let(:public_key_id) { 'https://example.com/alice-public-key.json' } |       let(:public_key_id) { 'https://example.com/alice-public-key.json' } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }))) |         stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it 'returns the expected account' do |       it 'returns the expected account' do | ||||||
| @ -84,7 +84,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do | |||||||
|       let(:actor_public_key) { 'https://example.com/alice-public-key.json' } |       let(:actor_public_key) { 'https://example.com/alice-public-key.json' } | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }))) |         stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it 'returns the nil' do |       it 'returns the nil' do | ||||||
|  | |||||||
| @ -58,7 +58,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do | |||||||
| 
 | 
 | ||||||
|       context 'when passing the URL to the collection' do |       context 'when passing the URL to the collection' do | ||||||
|         before do |         before do | ||||||
|           stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) |           stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         it 'spawns workers for up to 5 replies on the same server' do |         it 'spawns workers for up to 5 replies on the same server' do | ||||||
| @ -93,7 +93,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do | |||||||
| 
 | 
 | ||||||
|       context 'when passing the URL to the collection' do |       context 'when passing the URL to the collection' do | ||||||
|         before do |         before do | ||||||
|           stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) |           stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         it 'spawns workers for up to 5 replies on the same server' do |         it 'spawns workers for up to 5 replies on the same server' do | ||||||
| @ -132,7 +132,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service do | |||||||
| 
 | 
 | ||||||
|       context 'when passing the URL to the collection' do |       context 'when passing the URL to the collection' do | ||||||
|         before do |         before do | ||||||
|           stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) |           stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         it 'spawns workers for up to 5 replies on the same server' do |         it 'spawns workers for up to 5 replies on the same server' do | ||||||
|  | |||||||
| @ -60,7 +60,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do | |||||||
|   describe '#call' do |   describe '#call' do | ||||||
|     context 'when the endpoint is a Collection of actor URIs' do |     context 'when the endpoint is a Collection of actor URIs' do | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'synchronizes followers' |       it_behaves_like 'synchronizes followers' | ||||||
| @ -77,7 +77,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do | |||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'synchronizes followers' |       it_behaves_like 'synchronizes followers' | ||||||
| @ -98,7 +98,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do | |||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       before do |       before do | ||||||
|         stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload)) |         stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       it_behaves_like 'synchronizes followers' |       it_behaves_like 'synchronizes followers' | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ describe ActivityPub::FetchRepliesWorker do | |||||||
| 
 | 
 | ||||||
|   describe 'perform' do |   describe 'perform' do | ||||||
|     it 'performs a request if the collection URI is from the same host' do |     it 'performs a request if the collection URI is from the same host' do | ||||||
|       stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json) |       stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json, headers: { 'Content-Type': 'application/activity+json' }) | ||||||
|       subject.perform(status.id, 'https://example.com/statuses_replies/1') |       subject.perform(status.id, 'https://example.com/statuses_replies/1') | ||||||
|       expect(a_request(:get, 'https://example.com/statuses_replies/1')).to have_been_made.once |       expect(a_request(:get, 'https://example.com/statuses_replies/1')).to have_been_made.once | ||||||
|     end |     end | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user