0
0
Fork 0

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`
This commit is contained in:
Claire 2022-09-21 22:45:57 +02:00 committed by GitHub
parent 84aff598ea
commit 8cf7006d4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 436 additions and 180 deletions

View file

@ -116,12 +116,12 @@ class ActivityPub::Activity
def dereference_object!
return unless @object.is_a?(String)
dereferencer = ActivityPub::Dereferencer.new(@object, permitted_origin: @account.uri, signature_account: signed_fetch_account)
dereferencer = ActivityPub::Dereferencer.new(@object, permitted_origin: @account.uri, signature_actor: signed_fetch_actor)
@object = dereferencer.object unless dereferencer.object.nil?
end
def signed_fetch_account
def signed_fetch_actor
return Account.find(@options[:delivered_to_account_id]) if @options[:delivered_to_account_id].present?
first_mentioned_local_account || first_local_follower
@ -163,15 +163,15 @@ class ActivityPub::Activity
end
def followed_by_local_accounts?
@account.passive_relationships.exists? || @options[:relayed_through_account]&.passive_relationships&.exists?
@account.passive_relationships.exists? || (@options[:relayed_through_actor].is_a?(Account) && @options[:relayed_through_actor].passive_relationships&.exists?)
end
def requested_through_relay?
@options[:relayed_through_account] && Relay.find_by(inbox_url: @options[:relayed_through_account].inbox_url)&.enabled?
@options[:relayed_through_actor] && Relay.find_by(inbox_url: @options[:relayed_through_actor].inbox_url)&.enabled?
end
def reject_payload!
Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_account] && "via #{@options[:relayed_through_account].uri}"}")
Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_actor] && "via #{@options[:relayed_through_actor].uri}"}")
nil
end
end

View file

@ -3,10 +3,10 @@
class ActivityPub::Dereferencer
include JsonLdHelper
def initialize(uri, permitted_origin: nil, signature_account: nil)
def initialize(uri, permitted_origin: nil, signature_actor: nil)
@uri = uri
@permitted_origin = permitted_origin
@signature_account = signature_account
@signature_actor = signature_actor
end
def object
@ -46,7 +46,7 @@ class ActivityPub::Dereferencer
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.on_behalf_of(@signature_actor) if @signature_actor
req.perform do |res|
if res.code == 200

View file

@ -9,7 +9,7 @@ class ActivityPub::LinkedDataSignature
@json = json.with_indifferent_access
end
def verify_account!
def verify_actor!
return unless @json['signature'].is_a?(Hash)
type = @json['signature']['type']
@ -18,7 +18,7 @@ class ActivityPub::LinkedDataSignature
return unless type == 'RsaSignature2017'
creator = ActivityPub::TagManager.instance.uri_to_resource(creator_uri, Account)
creator = ActivityPub::TagManager.instance.uri_to_actor(creator_uri)
creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false)
return if creator.nil?
@ -35,7 +35,7 @@ class ActivityPub::LinkedDataSignature
def sign!(creator, sign_with: nil)
options = {
'type' => 'RsaSignature2017',
'creator' => [ActivityPub::TagManager.instance.uri_for(creator), '#main-key'].join,
'creator' => ActivityPub::TagManager.instance.key_uri_for(creator),
'created' => Time.now.utc.iso8601,
}

View file

@ -44,6 +44,10 @@ class ActivityPub::TagManager
end
end
def key_uri_for(target)
[uri_for(target), '#main-key'].join
end
def uri_for_username(username)
account_url(username: username)
end
@ -155,6 +159,10 @@ class ActivityPub::TagManager
path_params[param]
end
def uri_to_actor(uri)
uri_to_resource(uri, Account)
end
def uri_to_resource(uri, klass)
return if uri.nil?

View file

@ -40,12 +40,11 @@ class Request
set_digest! if options.key?(:body)
end
def on_behalf_of(account, key_id_format = :uri, sign_with: nil)
raise ArgumentError, 'account must not be nil' if account.nil?
def on_behalf_of(actor, sign_with: nil)
raise ArgumentError, 'actor must not be nil' if actor.nil?
@account = account
@keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : @account.keypair
@key_id_format = key_id_format
@actor = actor
@keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : @actor.keypair
self
end
@ -79,7 +78,7 @@ class Request
end
def headers
(@account ? @headers.merge('Signature' => signature) : @headers).without(REQUEST_TARGET)
(@actor ? @headers.merge('Signature' => signature) : @headers).without(REQUEST_TARGET)
end
class << self
@ -128,12 +127,7 @@ class Request
end
def key_id
case @key_id_format
when :acct
@account.to_webfinger_s
when :uri
[ActivityPub::TagManager.instance.uri_for(@account), '#main-key'].join
end
ActivityPub::TagManager.instance.key_uri_for(@actor)
end
def http_client