Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream changes #1158

Merged
Merged
Changes from 1 commit
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
23aeef5
Remove Salmon and PubSubHubbub (#11205)
Gargron Jul 6, 2019
5827671
Fix support for HTTP proxies (#11245)
ClearlyClaire Jul 7, 2019
406b463
Fix URLs appearing twice in errors of ActivityPub::DeliveryWorker (#1…
Gargron Jul 7, 2019
b851456
Remove Atom feeds and old URLs in the form of `GET /:username/updates…
Gargron Jul 7, 2019
3ece6e2
Update fuubar dependency to 2.4.1 (#11248)
nilsding Jul 7, 2019
87c1ad4
Fix BackupService crashing when an attachment is missing (#11241)
ClearlyClaire Jul 8, 2019
239befc
Bump react-redux from 6.0.1 to 7.1.0 (#11256)
dependabot-preview[bot] Jul 8, 2019
6a313f8
Bump intl-relativeformat from 2.2.0 to 6.4.2 (#11255)
dependabot-preview[bot] Jul 8, 2019
1a8bbcd
Bump compression-webpack-plugin from 2.0.0 to 3.0.0 (#11224)
dependabot-preview[bot] Jul 8, 2019
76d5fd1
Bump @babel/plugin-proposal-class-properties from 7.4.4 to 7.5.0 (#11…
dependabot-preview[bot] Jul 8, 2019
d0b40ae
Bump eslint-plugin-react from 7.12.1 to 7.14.2 (#11253)
dependabot-preview[bot] Jul 8, 2019
f935004
Bump tzinfo-data from 1.2019.1 to 1.2019.2 (#11258)
dependabot-preview[bot] Jul 8, 2019
01ee35f
Bump aws-sdk-s3 from 1.43.0 to 1.45.0 (#11262)
dependabot-preview[bot] Jul 8, 2019
d76ca89
Bump simplecov from 0.16.1 to 0.17.0 (#11260)
dependabot-preview[bot] Jul 8, 2019
f147764
Bump faker from 1.9.3 to 1.9.6 (#11259)
dependabot-preview[bot] Jul 8, 2019
63c7fe8
Refactor controllers for statuses, accounts, and more (#11249)
Gargron Jul 8, 2019
ef15246
Remove unused remote unfollow controller (#11250)
Gargron Jul 8, 2019
1e7187f
Fix Status.remote scope matching *all* statuses (#11265)
ClearlyClaire Jul 8, 2019
4e92183
Refactor domain block checks (#11268)
Gargron Jul 9, 2019
6172263
Fix activity being rendered within activity due to caching (#11271)
Gargron Jul 9, 2019
27ad4c1
Fix old migration script depending on the StreamEntry model (#11278)
ClearlyClaire Jul 10, 2019
85eb418
Fix handling of webfinger redirects in ResolveAccountService (#11279)
ClearlyClaire Jul 10, 2019
d04c584
Drop magic-public-key from webfinger replies as it's only used for OS…
ClearlyClaire Jul 10, 2019
5d3feed
Refactor fetching of remote resources (#11251)
Gargron Jul 10, 2019
a6dc6a2
[Security] Bump lodash from 4.17.11 to 4.17.13 (#11287)
dependabot-preview[bot] Jul 11, 2019
4e8dcc5
Add HTTP signatures to all outgoing ActivityPub GET requests (#11284)
Gargron Jul 11, 2019
4e1260f
Fix BlockService trying to reject incorrect follow request (#11288)
ClearlyClaire Jul 11, 2019
5bf67ca
Add ActivityPub secure mode (#11269)
Gargron Jul 11, 2019
4023027
Change the retry limit in error of web push notification (#11292)
highemerly Jul 12, 2019
6ff67be
Add a spam check (#11217)
Gargron Jul 13, 2019
6af0c95
Bump rubocop-rails from 2.0.1 to 2.2.0 (#11257)
dependabot-preview[bot] Jul 13, 2019
2ea4dbb
Bump handlebars from 4.1.0 to 4.1.2 (#11293)
PatOnTheBack Jul 14, 2019
3595ce6
Fix leaking private statuses the admin account follows (#11300)
ClearlyClaire Jul 15, 2019
2f813b7
Disable LDSigning when AUTHORIZED_FETCH is set to true (#11295)
ClearlyClaire Jul 15, 2019
e7353c4
Change default interface of web and streaming from 0.0.0.0 to 127.0.0…
Gargron Jul 15, 2019
cecd0c3
New Crowdin translations (#11153)
Gargron Jul 15, 2019
b3f44aa
Add periodic removal of older thumbnails for preview cards (#11304)
Gargron Jul 15, 2019
5b4a934
Fix consistent interpolations (#11317)
ykzts Jul 15, 2019
851ad99
Bump eslint-plugin-import from 2.17.3 to 2.18.0 (#11310)
dependabot-preview[bot] Jul 15, 2019
23b29f7
Bump @babel/runtime from 7.4.5 to 7.5.4 (#11315)
dependabot-preview[bot] Jul 15, 2019
7840d56
Bump lodash from 4.17.13 to 4.17.14 (#11312)
dependabot-preview[bot] Jul 15, 2019
ae16820
Bump webpack from 4.34.0 to 4.35.3 (#11309)
dependabot-preview[bot] Jul 15, 2019
4562c3c
Bump eslint-plugin-jsx-a11y from 6.2.1 to 6.2.3 (#11314)
dependabot-preview[bot] Jul 15, 2019
9b1d3e4
Add option to disable real-time updates in web UI (#9984)
Gargron Jul 16, 2019
b4c9a86
Make puma bind address configurable with BIND env var (#11326)
zunda Jul 16, 2019
91544a6
Remove unused Account#magic_key (#11327)
ClearlyClaire Jul 16, 2019
15ddabf
Fix caching headers in ActivityPub endpoints (#11331)
ClearlyClaire Jul 16, 2019
5599cae
Extend AUTHORIZED_FETCH mode to user blocks as well (#11332)
ClearlyClaire Jul 16, 2019
873828a
Fix custom CSS controller (#11336)
ClearlyClaire Jul 17, 2019
fccd25c
Change terms and privacy policy pages to always be accessible (#11334)
Gargron Jul 17, 2019
7e2b6da
Add setting to disable the anti-spam (#11296)
ClearlyClaire Jul 17, 2019
87f4aea
Fix typo in StatusPolicy (#11344)
ClearlyClaire Jul 17, 2019
7cc98eb
Bump puma from 3.12.1 to 4.0.1 (#11306)
dependabot-preview[bot] Jul 17, 2019
cbd7748
Bump rubocop-rails from 2.2.0 to 2.2.1 (#11308)
dependabot-preview[bot] Jul 17, 2019
3a6fe65
Bump rack-attack from 6.0.0 to 6.1.0 (#11313)
dependabot-preview[bot] Jul 17, 2019
5bfe1e1
Change language detection to include hashtags as words (#11341)
Gargron Jul 18, 2019
4906cab
Add aac, m4a, 3gp to allowed audio formats (#11342)
Gargron Jul 18, 2019
84e9884
Fix only one middle dot being recognized in hashtags (#11345)
Gargron Jul 18, 2019
15c7478
Change Dockerfile to bind to 0.0.0.0 instead of docker-compose.yml (#…
Gargron Jul 18, 2019
730c405
Add ActivityPub actor representing the entire server (#11321)
ClearlyClaire Jul 18, 2019
fda437a
Fix sanitizing lists contents (#11354)
ClearlyClaire Jul 18, 2019
8df0022
Added logout to dropdown menu (#11353)
koyuawsmbrtn Jul 19, 2019
4fa6472
Fix avatar animation on hover when not logged in (#11349)
ClearlyClaire Jul 19, 2019
aa22b38
Change single-column mode to scroll the whole page (#11359)
Gargron Jul 19, 2019
6867a0b
Bump strong_migrations from 0.4.0 to 0.4.1 (#11307)
dependabot-preview[bot] Jul 19, 2019
249991c
Merge branch 'master' into glitch-soc/merge-upstream
ClearlyClaire Jul 19, 2019
bf3ab44
Remove Atom feeds and old URLs in the form of `GET /:username/updates…
Gargron Jul 7, 2019
490cf3a
[Glitch] Add ActivityPub actor representing the entire server
ClearlyClaire Jul 18, 2019
3407ae8
Fix sanitizer text case for glitch-soc, which preserves lists
ClearlyClaire Jul 19, 2019
86d4461
Fix HTML entities being encoded as hashtag links…
ClearlyClaire Jul 19, 2019
650459f
Fix some flash notices/alerts staying on unrelated pages (#11364)
ClearlyClaire Jul 19, 2019
c37c1da
Disallow numeric-only hashtags (#11363)
ClearlyClaire Jul 19, 2019
055450b
Merge branch 'master' into glitch-soc/merge-upstream
ClearlyClaire Jul 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor fetching of remote resources (mastodon#11251)
Gargron authored Jul 10, 2019
commit 5d3feed191bcbe2769512119752b426108152fe9
47 changes: 26 additions & 21 deletions app/helpers/jsonld_helper.rb
Original file line number Diff line number Diff line change
@@ -16,13 +16,15 @@ def first_of_value(value)
# The url attribute can be a string, an array of strings, or an array of objects.
# The objects could include a mimeType. Not-included mimeType means it's text/html.
def url_to_href(value, preferred_type = nil)
single_value = if value.is_a?(Array) && !value.first.is_a?(String)
value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
elsif value.is_a?(Array)
value.first
else
value
end
single_value = begin
if value.is_a?(Array) && !value.first.is_a?(String)
value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
elsif value.is_a?(Array)
value.first
else
value
end
end

if single_value.nil? || single_value.is_a?(String)
single_value
@@ -64,7 +66,9 @@ def canonicalize(json)
def fetch_resource(uri, id, on_behalf_of = nil)
unless id
json = fetch_resource_without_id_validation(uri, on_behalf_of)

return unless json

uri = json['id']
end

@@ -74,24 +78,26 @@ def fetch_resource(uri, id, on_behalf_of = nil)

def fetch_resource_without_id_validation(uri, on_behalf_of = nil, raise_on_temporary_error = false)
build_request(uri, on_behalf_of).perform do |response|
unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error
raise Mastodon::UnexpectedResponseError, response
end
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error

return body_to_json(response.body_with_limit) if response.code == 200
end

# If request failed, retry without doing it on behalf of a user
return if on_behalf_of.nil?

build_request(uri).perform do |response|
unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error
raise Mastodon::UnexpectedResponseError, response
end
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error

response.code == 200 ? body_to_json(response.body_with_limit) : nil
end
end

def body_to_json(body, compare_id: nil)
json = body.is_a?(String) ? Oj.load(body, mode: :strict) : body

return if compare_id.present? && json['id'] != compare_id

json
rescue Oj::ParseError
nil
@@ -105,35 +111,34 @@ def merge_context(context, new_context)
end
end

private

def response_successful?(response)
(200...300).cover?(response.code)
end

def response_error_unsalvageable?(response)
(400...500).cover?(response.code) && response.code != 429
response.code == 501 || ((400...500).cover?(response.code) && ![401, 408, 429].include?(response.code))
end

def build_request(uri, on_behalf_of = nil)
request = Request.new(:get, uri)
request.on_behalf_of(on_behalf_of) if on_behalf_of
request.add_headers('Accept' => 'application/activity+json, application/ld+json')
request
Request.new(:get, uri).tap do |request|
request.on_behalf_of(on_behalf_of) if on_behalf_of
request.add_headers('Accept' => 'application/activity+json, application/ld+json')
end
end

def load_jsonld_context(url, _options = {}, &_block)
json = Rails.cache.fetch("jsonld:context:#{url}", expires_in: 30.days, raw: true) do
request = Request.new(:get, url)
request.add_headers('Accept' => 'application/ld+json')

request.perform do |res|
raise JSON::LD::JsonLdError::LoadingDocumentFailed unless res.code == 200 && res.mime_type == 'application/ld+json'

res.body_with_limit
end
end

doc = JSON::LD::API::RemoteDocument.new(url, json)

block_given? ? yield(doc) : doc
end
end
2 changes: 1 addition & 1 deletion app/lib/request.rb
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ def initialize(verb, url, **options)
end

def on_behalf_of(account, key_id_format = :acct, sign_with: nil)
raise ArgumentError unless account.local?
raise ArgumentError, 'account must be local' unless account&.local?

@account = account
@keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : @account.keypair
20 changes: 10 additions & 10 deletions app/services/activitypub/fetch_remote_status_service.rb
Original file line number Diff line number Diff line change
@@ -5,18 +5,18 @@ class ActivityPub::FetchRemoteStatusService < BaseService

# Should be called when uri has already been checked for locality
def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil)
@json = if prefetched_body.nil?
fetch_resource(uri, id, on_behalf_of)
else
body_to_json(prefetched_body, compare_id: id ? uri : nil)
end
@json = begin
if prefetched_body.nil?
fetch_resource(uri, id, on_behalf_of)
else
body_to_json(prefetched_body, compare_id: id ? uri : nil)
end
end

return unless supported_context? && expected_type?

return if actor_id.nil? || !trustworthy_attribution?(@json['id'], actor_id)
return if !(supported_context? && expected_type?) || actor_id.nil? || !trustworthy_attribution?(@json['id'], actor_id)

actor = ActivityPub::TagManager.instance.uri_to_resource(actor_id, Account)
actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id, id: true) if actor.nil? || needs_update(actor)
actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id, id: true) if actor.nil? || needs_update?(actor)

return if actor.nil? || actor.suspended?

@@ -46,7 +46,7 @@ def expected_type?
equals_or_includes_any?(@json['type'], ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
end

def needs_update(actor)
def needs_update?(actor)
actor.possibly_stale?
end
end
93 changes: 0 additions & 93 deletions app/services/fetch_atom_service.rb

This file was deleted.

2 changes: 1 addition & 1 deletion app/services/fetch_link_card_service.rb
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ def call(status)
end

attach_card if @card&.persisted?
rescue HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
Rails.logger.debug "Error fetching link #{@url}: #{e}"
nil
end
2 changes: 1 addition & 1 deletion app/services/fetch_remote_account_service.rb
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
class FetchRemoteAccountService < BaseService
def call(url, prefetched_body = nil, protocol = :ostatus)
if prefetched_body.nil?
resource_url, resource_options, protocol = FetchAtomService.new.call(url)
resource_url, resource_options, protocol = FetchResourceService.new.call(url)
else
resource_url = url
resource_options = { prefetched_body: prefetched_body }
2 changes: 1 addition & 1 deletion app/services/fetch_remote_status_service.rb
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
class FetchRemoteStatusService < BaseService
def call(url, prefetched_body = nil, protocol = :ostatus)
if prefetched_body.nil?
resource_url, resource_options, protocol = FetchAtomService.new.call(url)
resource_url, resource_options, protocol = FetchResourceService.new.call(url)
else
resource_url = url
resource_options = { prefetched_body: prefetched_body }
68 changes: 68 additions & 0 deletions app/services/fetch_resource_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# frozen_string_literal: true

class FetchResourceService < BaseService
include JsonLdHelper

ACCEPT_HEADER = 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams", text/html'

def call(url)
return if url.blank?

process(url)
rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
Rails.logger.debug "Error fetching resource #{@url}: #{e}"
nil
end

private

def process(url, terminal = false)
@url = url

perform_request { |response| process_response(response, terminal) }
end

def perform_request(&block)
Request.new(:get, @url).add_headers('Accept' => ACCEPT_HEADER).perform(&block)
end

def process_response(response, terminal = false)
return nil if response.code != 200

if ['application/activity+json', 'application/ld+json'].include?(response.mime_type)
body = response.body_with_limit
json = body_to_json(body)

[json['id'], { prefetched_body: body, id: true }, :activitypub] if supported_context?(json) && (equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) || expected_type?(json))
elsif !terminal
link_header = response['Link'] && parse_link_header(response)

if link_header&.find_link(%w(rel alternate))
process_link_headers(link_header)
elsif response.mime_type == 'text/html'
process_html(response)
end
end
end

def expected_type?(json)
equals_or_includes_any?(json['type'], ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
end

def process_html(response)
page = Nokogiri::HTML(response.body_with_limit)
json_link = page.xpath('//link[@rel="alternate"]').find { |link| ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(link['type']) }

process(json_link['href'], terminal: true) unless json_link.nil?
end

def process_link_headers(link_header)
json_link = link_header.find_link(%w(rel alternate), %w(type application/activity+json)) || link_header.find_link(%w(rel alternate), ['type', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'])

process(json_link.href, terminal: true) unless json_link.nil?
end

def parse_link_header(response)
LinkHeader.parse(response['Link'].is_a?(Array) ? response['Link'].first : response['Link'])
end
end
47 changes: 16 additions & 31 deletions app/services/resolve_url_service.rb
Original file line number Diff line number Diff line change
@@ -4,64 +4,49 @@ class ResolveURLService < BaseService
include JsonLdHelper
include Authorization

attr_reader :url

def call(url, on_behalf_of: nil)
@url = url
@url = url
@on_behalf_of = on_behalf_of

return process_local_url if local_url?

process_url unless fetched_atom_feed.nil?
if local_url?
process_local_url
elsif !fetched_resource.nil?
process_url
end
end

private

def process_url
if equals_or_includes_any?(type, ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES)
FetchRemoteAccountService.new.call(atom_url, body, protocol)
FetchRemoteAccountService.new.call(resource_url, body, protocol)
elsif equals_or_includes_any?(type, ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
FetchRemoteStatusService.new.call(atom_url, body, protocol)
FetchRemoteStatusService.new.call(resource_url, body, protocol)
end
end

def fetched_atom_feed
@_fetched_atom_feed ||= FetchAtomService.new.call(url)
def fetched_resource
@fetched_resource ||= FetchResourceService.new.call(@url)
end

def atom_url
fetched_atom_feed.first
def resource_url
fetched_resource.first
end

def body
fetched_atom_feed.second[:prefetched_body]
fetched_resource.second[:prefetched_body]
end

def protocol
fetched_atom_feed.third
fetched_resource.third
end

def type
return json_data['type'] if protocol == :activitypub

case xml_root
when 'feed'
'Person'
when 'entry'
'Note'
end
end

def json_data
@_json_data ||= body_to_json(body)
end

def xml_root
xml_data.root.name
end

def xml_data
@_xml_data ||= Nokogiri::XML(body, nil, 'utf-8')
@json_data ||= body_to_json(body)
end

def local_url?
@@ -83,10 +68,10 @@ def process_local_url

def check_local_status(status)
return if status.nil?

authorize_with @on_behalf_of, status, :show?
status
rescue Mastodon::NotPermittedError
# Do not disclose the existence of status the user is not authorized to see
nil
end
end
16 changes: 5 additions & 11 deletions app/workers/activitypub/delivery_worker.rb
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

class ActivityPub::DeliveryWorker
include Sidekiq::Worker
include JsonLdHelper

STOPLIGHT_FAILURE_THRESHOLD = 10
STOPLIGHT_COOLDOWN = 60
@@ -32,9 +33,10 @@ def perform(json, source_account_id, inbox_url, options = {})
private

def build_request(http_client)
request = Request.new(:post, @inbox_url, body: @json, http_client: http_client)
request.on_behalf_of(@source_account, :uri, sign_with: @options[:sign_with])
request.add_headers(HEADERS)
Request.new(:post, @inbox_url, body: @json, http_client: http_client).tap do |request|
request.on_behalf_of(@source_account, :uri, sign_with: @options[:sign_with])
request.add_headers(HEADERS)
end
end

def perform_request
@@ -53,14 +55,6 @@ def perform_request
.run
end

def response_successful?(response)
(200...300).cover?(response.code)
end

def response_error_unsalvageable?(response)
response.code == 501 || ((400...500).cover?(response.code) && ![401, 408, 429].include?(response.code))
end

def failure_tracker
@failure_tracker ||= DeliveryFailureTracker.new(@inbox_url)
end
1 change: 1 addition & 0 deletions spec/services/fetch_remote_account_service_spec.rb
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
let(:url) { 'https://example.com/alice' }
let(:prefetched_body) { nil }
let(:protocol) { :ostatus }

subject { FetchRemoteAccountService.new.call(url, prefetched_body, protocol) }

let(:actor) do
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
require 'rails_helper'

RSpec.describe FetchAtomService, type: :service do
RSpec.describe FetchResourceService, type: :service do
let!(:representative) { Fabricate(:account) }

describe '#call' do
let(:url) { 'http://example.com' }
subject { FetchAtomService.new.call(url) }
subject { described_class.new.call(url) }

context 'url is blank' do
let(:url) { '' }
@@ -23,8 +25,7 @@
allow(Request).to receive_message_chain(:new, :add_headers, :perform).and_raise(OpenSSL::SSL::SSLError)
end

it 'output log and return nil' do
expect_any_instance_of(ActiveSupport::Logger).to receive(:debug).with('SSL error: OpenSSL::SSL::SSLError')
it 'return nil' do
is_expected.to be_nil
end
end
@@ -34,8 +35,7 @@
allow(Request).to receive_message_chain(:new, :add_headers, :perform).and_raise(HTTP::ConnectionError)
end

it 'output log and return nil' do
expect_any_instance_of(ActiveSupport::Logger).to receive(:debug).with('HTTP ConnectionError: HTTP::ConnectionError')
it 'return nil' do
is_expected.to be_nil
end
end
@@ -57,7 +57,7 @@
context 'content type is application/atom+xml' do
let(:content_type) { 'application/atom+xml' }

it { is_expected.to eq [url, { :prefetched_body => "" }, :ostatus] }
it { is_expected.to eq nil }
end

context 'content_type is activity+json' do
44 changes: 5 additions & 39 deletions spec/services/resolve_url_service_spec.rb
Original file line number Diff line number Diff line change
@@ -6,48 +6,14 @@
subject { described_class.new }

describe '#call' do
it 'returns nil when there is no atom url' do
url = 'http://example.com/missing-atom'
it 'returns nil when there is no resource url' do
url = 'http://example.com/missing-resource'
service = double
allow(FetchAtomService).to receive(:new).and_return service
allow(service).to receive(:call).with(url).and_return(nil)

result = subject.call(url)
expect(result).to be_nil
end

it 'fetches remote accounts for feed types' do
url = 'http://example.com/atom-feed'
service = double
allow(FetchAtomService).to receive(:new).and_return service
feed_url = 'http://feed-url'
feed_content = '<feed>contents</feed>'
allow(service).to receive(:call).with(url).and_return([feed_url, { prefetched_body: feed_content }])

account_service = double
allow(FetchRemoteAccountService).to receive(:new).and_return(account_service)
allow(account_service).to receive(:call)

_result = subject.call(url)

expect(account_service).to have_received(:call).with(feed_url, feed_content, nil)
end

it 'fetches remote statuses for entry types' do
url = 'http://example.com/atom-entry'
service = double
allow(FetchAtomService).to receive(:new).and_return service
feed_url = 'http://feed-url'
feed_content = '<entry>contents</entry>'
allow(service).to receive(:call).with(url).and_return([feed_url, { prefetched_body: feed_content }])

account_service = double
allow(FetchRemoteStatusService).to receive(:new).and_return(account_service)
allow(account_service).to receive(:call)

_result = subject.call(url)
allow(FetchResourceService).to receive(:new).and_return service
allow(service).to receive(:call).with(url).and_return(nil)

expect(account_service).to have_received(:call).with(feed_url, feed_content, nil)
expect(subject.call(url)).to be_nil
end
end
end