1
0
mirror of https://github.com/mastodon/mastodon synced 2024-12-22 10:38:14 +09:00
mastodon/app/services/subscribe_service.rb
James 6b2be5dbfb Guarantee Subscription service first account has proper URL details (#4732)
* Guarantee Subscription service first account has proper URL details

Subscription Service potentially could break if the first user suspended
themselves, creating a situation where the urls that populate throughout
subscription service's PuSH request would cause the remote API to throw 503 errors.

Guaranteeing that the first account picked is not suspended prevents this problem.

* Fix style issue
2017-08-31 15:44:00 +02:00

58 lines
1.6 KiB
Ruby

# frozen_string_literal: true
class SubscribeService < BaseService
def call(account)
return if account.hub_url.blank?
@account = account
@account.secret = SecureRandom.hex
@response = build_request.perform
if response_failed_permanently?
# We're not allowed to subscribe. Fail and move on.
@account.secret = ''
@account.save!
elsif response_successful?
# The subscription will be confirmed asynchronously.
@account.save!
else
# The response was either a 429 rate limit, or a 5xx error.
# We need to retry at a later time. Fail loudly!
raise Mastodon::UnexpectedResponseError, @response
end
end
private
def build_request
request = Request.new(:post, @account.hub_url, form: subscription_params)
request.on_behalf_of(some_local_account) if some_local_account
request
end
def subscription_params
{
'hub.topic': @account.remote_url,
'hub.mode': 'subscribe',
'hub.callback': api_subscription_url(@account.id),
'hub.verify': 'async',
'hub.secret': @account.secret,
'hub.lease_seconds': 7.days.seconds,
}
end
def some_local_account
@some_local_account ||= Account.local.where(suspended: false).first
end
# Any response in the 3xx or 4xx range, except for 429 (rate limit)
def response_failed_permanently?
(@response.status.redirect? || @response.status.client_error?) && !@response.status.too_many_requests?
end
# Any response in the 2xx range
def response_successful?
@response.status.success?
end
end