if key_id.start_with?('acct:')
ResolveRemoteAccountService.new.call(key_id.gsub(/\Aacct:/, ''))
elsif !ActivityPub::TagManager.instance.local_uri?(key_id)
- ActivityPub::FetchRemoteAccountService.new.call(key_id)
+ account = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account)
+ account ||= ActivityPub::FetchRemoteKeyService.new.call(key_id)
+ account
end
end
end
value.is_a?(Array) ? value.first : value
end
+ def value_or_id(value)
+ value.is_a?(String) ? value : value['id']
+ end
+
def supported_context?(json)
equals_or_includes?(json['@context'], ActivityPub::TagManager::CONTEXT)
end
end
def body_to_json(body)
- body.nil? ? nil : Oj.load(body, mode: :strict)
+ body.is_a?(String) ? Oj.load(body, mode: :strict) : body
rescue Oj::ParseError
nil
end
end
def object_uri
- @object_uri ||= @object.is_a?(String) ? @object : @object['id']
+ @object_uri ||= value_or_id(@object)
end
def redis
end
def target_uri
- @target_uri ||= @object['actor']
+ @target_uri ||= value_or_id(@object['actor'])
end
end
end
def target_uri
- @target_uri ||= @object['actor']
+ @target_uri ||= value_or_id(@object['actor'])
end
end
end
def target_uri
- @target_uri ||= @object['object'].is_a?(String) ? @object['object'] : @object['object']['id']
+ @target_uri ||= value_or_id(@object['object'])
end
end
elsif ::TagManager.instance.local_id?(uri)
klass.find_by(id: ::TagManager.instance.unique_tag_to_local_id(uri, klass.to_s))
else
- klass.find_by(uri: uri)
+ klass.find_by(uri: uri.split('#').first)
end
end
end
--- /dev/null
+# frozen_string_literal: true
+
+class ActivityPub::FetchRemoteKeyService < BaseService
+ include JsonLdHelper
+
+ # Returns account that owns the key
+ def call(uri, prefetched_json = nil)
+ @json = body_to_json(prefetched_json) || fetch_resource(uri)
+
+ return unless supported_context?(@json) && expected_type?
+ return find_account(uri, @json) if person?
+
+ @owner = fetch_resource(owner_uri)
+
+ return unless supported_context?(@owner) && confirmed_owner?
+
+ find_account(owner_uri, @owner)
+ end
+
+ private
+
+ def find_account(uri, prefetched_json)
+ account = ActivityPub::TagManager.instance.uri_to_resource(uri, Account)
+ account ||= ActivityPub::FetchRemoteAccountService.new.call(uri, prefetched_json)
+ account
+ end
+
+ def expected_type?
+ person? || public_key?
+ end
+
+ def person?
+ @json['type'] == 'Person'
+ end
+
+ def public_key?
+ @json['publicKeyPem'].present? && @json['owner'].present?
+ end
+
+ def owner_uri
+ @owner_uri ||= value_or_id(@json['owner'])
+ end
+
+ def confirmed_owner?
+ @owner['type'] == 'Person' && value_or_id(@owner['publicKey']) == @json['id']
+ end
+end