Refactor monkey-patching of Goldfinger (#12561)

master
Eugen Rochko 4 years ago committed by GitHub
parent 4a2ea2e51b
commit 4b766f9846
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      app/helpers/webfinger_helper.rb
  2. 3
      app/models/remote_follow.rb
  3. 5
      app/services/activitypub/fetch_remote_account_service.rb
  4. 3
      app/services/resolve_account_service.rb
  5. 20
      config/initializers/http_client_proxy.rb
  6. 10
      spec/controllers/remote_follow_controller_spec.rb

@ -0,0 +1,19 @@
# frozen_string_literal: true
module WebfingerHelper
def webfinger!(uri)
hidden_service_uri = /\.(onion|i2p)(:\d+)?$/.match(uri)
raise Mastodon::HostValidationError, 'Instance does not support hidden service connections' if !Rails.configuration.x.access_to_hidden_service && hidden_service_uri
opts = {
ssl: !hidden_service_uri,
headers: {
'User-Agent': Mastodon::Version.user_agent,
},
}
Goldfinger::Client.new(uri, opts.merge(Rails.configuration.x.http_client_proxy)).finger
end
end

@ -3,6 +3,7 @@
class RemoteFollow class RemoteFollow
include ActiveModel::Validations include ActiveModel::Validations
include RoutingHelper include RoutingHelper
include WebfingerHelper
attr_accessor :acct, :addressable_template attr_accessor :acct, :addressable_template
@ -71,7 +72,7 @@ class RemoteFollow
end end
def acct_resource def acct_resource
@acct_resource ||= Goldfinger.finger("acct:#{acct}") @acct_resource ||= webfinger!("acct:#{acct}")
rescue Goldfinger::Error, HTTP::ConnectionError rescue Goldfinger::Error, HTTP::ConnectionError
nil nil
end end

@ -3,6 +3,7 @@
class ActivityPub::FetchRemoteAccountService < BaseService class ActivityPub::FetchRemoteAccountService < BaseService
include JsonLdHelper include JsonLdHelper
include DomainControlHelper include DomainControlHelper
include WebfingerHelper
SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
@ -35,12 +36,12 @@ class ActivityPub::FetchRemoteAccountService < BaseService
private private
def verified_webfinger? def verified_webfinger?
webfinger = Goldfinger.finger("acct:#{@username}@#{@domain}") webfinger = webfinger!("acct:#{@username}@#{@domain}")
confirmed_username, confirmed_domain = split_acct(webfinger.subject) confirmed_username, confirmed_domain = split_acct(webfinger.subject)
return webfinger.link('self')&.href == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero? return webfinger.link('self')&.href == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
webfinger = Goldfinger.finger("acct:#{confirmed_username}@#{confirmed_domain}") webfinger = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}")
@username, @domain = split_acct(webfinger.subject) @username, @domain = split_acct(webfinger.subject)
self_reference = webfinger.link('self') self_reference = webfinger.link('self')

@ -3,6 +3,7 @@
class ResolveAccountService < BaseService class ResolveAccountService < BaseService
include JsonLdHelper include JsonLdHelper
include DomainControlHelper include DomainControlHelper
include WebfingerHelper
class WebfingerRedirectError < StandardError; end class WebfingerRedirectError < StandardError; end
@ -76,7 +77,7 @@ class ResolveAccountService < BaseService
end end
def process_webfinger!(uri, redirected = false) def process_webfinger!(uri, redirected = false)
@webfinger = Goldfinger.finger("acct:#{uri}") @webfinger = webfinger!("acct:#{uri}")
confirmed_username, confirmed_domain = @webfinger.subject.gsub(/\Aacct:/, '').split('@') confirmed_username, confirmed_domain = @webfinger.subject.gsub(/\Aacct:/, '').split('@')
if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero? if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?

@ -1,24 +1,22 @@
Rails.application.configure do Rails.application.configure do
config.x.http_client_proxy = {} config.x.http_client_proxy = {}
if ENV['http_proxy'].present? if ENV['http_proxy'].present?
proxy = URI.parse(ENV['http_proxy']) proxy = URI.parse(ENV['http_proxy'])
raise "Unsupported proxy type: #{proxy.scheme}" unless %w(http https).include? proxy.scheme raise "Unsupported proxy type: #{proxy.scheme}" unless %w(http https).include? proxy.scheme
raise "No proxy host" unless proxy.host raise "No proxy host" unless proxy.host
host = proxy.host host = proxy.host
host = host[1...-1] if host[0] == '[' # for IPv6 address host = host[1...-1] if host[0] == '[' # for IPv6 address
config.x.http_client_proxy[:proxy] = { proxy_address: host, proxy_port: proxy.port, proxy_username: proxy.user, proxy_password: proxy.password }.compact
config.x.http_client_proxy[:proxy] = {
proxy_address: host,
proxy_port: proxy.port,
proxy_username: proxy.user,
proxy_password: proxy.password,
}.compact
end end
config.x.access_to_hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true' config.x.access_to_hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
end end
module Goldfinger
def self.finger(uri, opts = {})
to_hidden = /\.(onion|i2p)(:\d+)?$/.match(uri)
raise Mastodon::HostValidationError, 'Instance does not support hidden service connections' if !Rails.configuration.x.access_to_hidden_service && to_hidden
opts = { ssl: !to_hidden, headers: {} }.merge(Rails.configuration.x.http_client_proxy).merge(opts)
opts[:headers]['User-Agent'] ||= Mastodon::Version.user_agent
Goldfinger::Client.new(uri, opts).finger
end
end

@ -35,7 +35,7 @@ describe RemoteFollowController do
context 'when webfinger values are wrong' do context 'when webfinger values are wrong' do
it 'renders new when redirect url is nil' do it 'renders new when redirect url is nil' do
resource_with_nil_link = double(link: nil) resource_with_nil_link = double(link: nil)
allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_return(resource_with_nil_link) allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_nil_link)
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } } post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
expect(response).to render_template(:new) expect(response).to render_template(:new)
@ -45,7 +45,7 @@ describe RemoteFollowController do
it 'renders new when template is nil' do it 'renders new when template is nil' do
link_with_nil_template = double(template: nil) link_with_nil_template = double(template: nil)
resource_with_link = double(link: link_with_nil_template) resource_with_link = double(link: link_with_nil_template)
allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_return(resource_with_link) allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_link)
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } } post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
expect(response).to render_template(:new) expect(response).to render_template(:new)
@ -57,7 +57,7 @@ describe RemoteFollowController do
before do before do
link_with_template = double(template: 'http://example.com/follow_me?acct={uri}') link_with_template = double(template: 'http://example.com/follow_me?acct={uri}')
resource_with_link = double(link: link_with_template) resource_with_link = double(link: link_with_template)
allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_return(resource_with_link) allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_return(resource_with_link)
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } } post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
end end
@ -79,7 +79,7 @@ describe RemoteFollowController do
end end
it 'renders new with error when goldfinger fails' do it 'renders new with error when goldfinger fails' do
allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_raise(Goldfinger::Error) allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@example.com').and_raise(Goldfinger::Error)
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } } post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
expect(response).to render_template(:new) expect(response).to render_template(:new)
@ -87,7 +87,7 @@ describe RemoteFollowController do
end end
it 'renders new when occur HTTP::ConnectionError' do it 'renders new when occur HTTP::ConnectionError' do
allow(Goldfinger).to receive(:finger).with('acct:user@unknown').and_raise(HTTP::ConnectionError) allow_any_instance_of(WebfingerHelper).to receive(:webfinger!).with('acct:user@unknown').and_raise(HTTP::ConnectionError)
post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@unknown' } } post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@unknown' } }
expect(response).to render_template(:new) expect(response).to render_template(:new)

Loading…
Cancel
Save