masto-fe/app/lib/activitypub/dereferencer.rb
Claire 8cf7006d4e
Refactor ActivityPub handling to prepare for non-Account actors (#19212)
* Move ActivityPub::FetchRemoteAccountService to ActivityPub::FetchRemoteActorService

ActivityPub::FetchRemoteAccountService is kept as a wrapper for when the actor is
specifically required to be an Account

* Refactor SignatureVerification to allow non-Account actors

* fixup! Move ActivityPub::FetchRemoteAccountService to ActivityPub::FetchRemoteActorService

* Refactor ActivityPub::FetchRemoteKeyService to potentially return non-Account actors

* Refactor inbound ActivityPub payload processing to accept non-Account actors

* Refactor inbound ActivityPub processing to accept activities relayed through non-Account

* Refactor how Account key URIs are built

* Refactor Request and drop unused key_id_format parameter

* Rename ActivityPub::Dereferencer `signature_account` to `signature_actor`
2022-09-21 22:45:57 +02:00

70 lines
1.6 KiB
Ruby

# frozen_string_literal: true
class ActivityPub::Dereferencer
include JsonLdHelper
def initialize(uri, permitted_origin: nil, signature_actor: nil)
@uri = uri
@permitted_origin = permitted_origin
@signature_actor = signature_actor
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_actor) if @signature_actor
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