7d985f2aac
There are edge cases where requests to certain hosts timeout when using the vanilla HTTP.rb gem, which the goldfinger gem uses. Now that we no longer need to support OStatus servers, webfinger logic is so simple that there is no point encapsulating it in a gem, so we can just use our own Request class. With that, we benefit from more robust timeout code and IPv4/IPv6 resolution. Fix #14091
79 lines
1.8 KiB
Ruby
79 lines
1.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class RemoteFollow
|
|
include ActiveModel::Validations
|
|
include RoutingHelper
|
|
include WebfingerHelper
|
|
|
|
attr_accessor :acct, :addressable_template
|
|
|
|
validates :acct, presence: true, domain: { acct: true }
|
|
|
|
def initialize(attrs = {})
|
|
@acct = normalize_acct(attrs[:acct])
|
|
end
|
|
|
|
def valid?
|
|
return false unless super
|
|
|
|
fetch_template!
|
|
|
|
errors.empty?
|
|
end
|
|
|
|
def subscribe_address_for(account)
|
|
addressable_template.expand(uri: ActivityPub::TagManager.instance.uri_for(account)).to_s
|
|
end
|
|
|
|
def interact_address_for(status)
|
|
addressable_template.expand(uri: ActivityPub::TagManager.instance.uri_for(status)).to_s
|
|
end
|
|
|
|
private
|
|
|
|
def normalize_acct(value)
|
|
return if value.blank?
|
|
|
|
username, domain = value.strip.gsub(/\A@/, '').split('@')
|
|
|
|
domain = begin
|
|
if TagManager.instance.local_domain?(domain)
|
|
nil
|
|
else
|
|
TagManager.instance.normalize_domain(domain)
|
|
end
|
|
end
|
|
|
|
[username, domain].compact.join('@')
|
|
rescue Addressable::URI::InvalidURIError
|
|
value
|
|
end
|
|
|
|
def fetch_template!
|
|
return missing_resource_error if acct.blank?
|
|
|
|
_, domain = acct.split('@')
|
|
|
|
if domain.nil?
|
|
@addressable_template = Addressable::Template.new("#{authorize_interaction_url}?uri={uri}")
|
|
elsif redirect_uri_template.nil?
|
|
missing_resource_error
|
|
else
|
|
@addressable_template = Addressable::Template.new(redirect_uri_template)
|
|
end
|
|
end
|
|
|
|
def redirect_uri_template
|
|
acct_resource&.link('http://ostatus.org/schema/1.0/subscribe', 'template')
|
|
end
|
|
|
|
def acct_resource
|
|
@acct_resource ||= webfinger!("acct:#{acct}")
|
|
rescue Webfinger::Error, HTTP::ConnectionError
|
|
nil
|
|
end
|
|
|
|
def missing_resource_error
|
|
errors.add(:acct, I18n.t('remote_follow.missing_resource'))
|
|
end
|
|
end
|