diff options
Diffstat (limited to 'app/lib/activitypub/dereferencer.rb')
-rw-r--r-- | app/lib/activitypub/dereferencer.rb | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/app/lib/activitypub/dereferencer.rb b/app/lib/activitypub/dereferencer.rb new file mode 100644 index 000000000..bea69608f --- /dev/null +++ b/app/lib/activitypub/dereferencer.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +class ActivityPub::Dereferencer + include JsonLdHelper + + def initialize(uri, permitted_origin: nil, signature_account: nil) + @uri = uri + @permitted_origin = permitted_origin + @signature_account = signature_account + end + + def object + @object ||= fetch_object! + end + + private + + def bear_cap? + @uri.start_with?('bear:') + end + + def fetch_object! + if bear_cap? + fetch_with_token! + else + fetch_with_signature! + end + end + + def fetch_with_token! + perform_request(bear_cap['u'], headers: { 'Authorization' => "Bearer #{bear_cap['t']}" }) + end + + def fetch_with_signature! + perform_request(@uri) + end + + def bear_cap + @bear_cap ||= Addressable::URI.parse(@uri).query_values + end + + def perform_request(uri, headers: nil) + return if invalid_origin?(uri) + + req = Request.new(:get, uri) + + req.add_headers('Accept' => 'application/activity+json, application/ld+json') + req.add_headers(headers) if headers + req.on_behalf_of(@signature_account) if @signature_account + + req.perform do |res| + if res.code == 200 + json = body_to_json(res.body_with_limit) + json if json.present? && json['id'] == uri + else + raise Mastodon::UnexpectedResponseError, res unless response_successful?(res) || response_error_unsalvageable?(res) + end + end + end + + def invalid_origin?(uri) + return true if unsupported_uri_scheme?(uri) + + needle = Addressable::URI.parse(uri).host + haystack = Addressable::URI.parse(@permitted_origin).host + + !haystack.casecmp(needle).zero? + end +end |