Reduce usage of LD signatures (#9659)

* Do not LDS-sign Follow, Accept, Reject, Undo, Block

* Do not use LDS for Create activities of private toots

* Minor cleanup

* Ignore unsigned activities instead of misattributing them

* Use status.distributable? instead of querying visibility directly
This commit is contained in:
ThibG 2018-12-30 09:48:59 +01:00 committed by Eugen Rochko
parent fb08039de5
commit 290932602b
13 changed files with 40 additions and 34 deletions

View file

@ -28,7 +28,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity
end end
def reject_follow_request!(target_account) def reject_follow_request!(target_account)
json = Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new(FollowRequest.new(account: @account, target_account: target_account, uri: @json['id']), serializer: ActivityPub::RejectFollowSerializer, adapter: ActivityPub::Adapter).as_json).sign!(target_account)) json = ActiveModelSerializers::SerializableResource.new(FollowRequest.new(account: @account, target_account: target_account, uri: @json['id']), serializer: ActivityPub::RejectFollowSerializer, adapter: ActivityPub::Adapter).to_json
ActivityPub::DeliveryWorker.perform_async(json, target_account.id, @account.inbox_url) ActivityPub::DeliveryWorker.perform_async(json, target_account.id, @account.inbox_url)
end end
end end

View file

@ -27,7 +27,7 @@ class ActivityPub::ProcessCollectionService < BaseService
private private
def different_actor? def different_actor?
@json['actor'].present? && value_or_id(@json['actor']) != @account.uri && @json['signature'].present? @json['actor'].present? && value_or_id(@json['actor']) != @account.uri
end end
def process_items(items) def process_items(items)

View file

@ -31,11 +31,11 @@ class AfterBlockDomainFromAccountService < BaseService
return unless follow.account.activitypub? return unless follow.account.activitypub?
json = Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( json = ActiveModelSerializers::SerializableResource.new(
follow, follow,
serializer: ActivityPub::RejectFollowSerializer, serializer: ActivityPub::RejectFollowSerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(@account)) ).to_json
ActivityPub::DeliveryWorker.perform_async(json, @account.id, follow.account.inbox_url) ActivityPub::DeliveryWorker.perform_async(json, @account.id, follow.account.inbox_url)
end end

View file

@ -24,11 +24,11 @@ class AuthorizeFollowService < BaseService
end end
def build_json(follow_request) def build_json(follow_request)
Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
follow_request, follow_request,
serializer: ActivityPub::AcceptFollowSerializer, serializer: ActivityPub::AcceptFollowSerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(follow_request.target_account)) ).to_json
end end
def build_xml(follow_request) def build_xml(follow_request)

View file

@ -1,8 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class BlockService < BaseService class BlockService < BaseService
include StreamEntryRenderer
def call(account, target_account) def call(account, target_account)
return if account.id == target_account.id return if account.id == target_account.id
@ -27,11 +25,11 @@ class BlockService < BaseService
end end
def build_json(block) def build_json(block)
Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
block, block,
serializer: ActivityPub::BlockSerializer, serializer: ActivityPub::BlockSerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(block.account)) ).to_json
end end
def build_xml(block) def build_xml(block)

View file

@ -1,8 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class FollowService < BaseService class FollowService < BaseService
include StreamEntryRenderer
# Follow a remote user, notify remote user about the follow # Follow a remote user, notify remote user about the follow
# @param [Account] source_account From which to follow # @param [Account] source_account From which to follow
# @param [String, Account] uri User URI to follow in the form of username@domain (or account record) # @param [String, Account] uri User URI to follow in the form of username@domain (or account record)
@ -82,10 +80,10 @@ class FollowService < BaseService
end end
def build_json(follow_request) def build_json(follow_request)
Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
follow_request, follow_request,
serializer: ActivityPub::FollowSerializer, serializer: ActivityPub::FollowSerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(follow_request.account)) ).to_json
end end
end end

View file

@ -60,11 +60,13 @@ class ProcessMentionsService < BaseService
end end
def activitypub_json def activitypub_json
@activitypub_json ||= Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( return @activitypub_json if defined?(@activitypub_json)
payload = ActiveModelSerializers::SerializableResource.new(
@status, @status,
serializer: ActivityPub::ActivitySerializer, serializer: ActivityPub::ActivitySerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(@status.account)) ).as_json
@activitypub_json = Oj.dump(@status.distributable? ? ActivityPub::LinkedDataSignature.new(payload).sign!(@status.account) : payload)
end end
def resolve_account_service def resolve_account_service

View file

@ -19,11 +19,11 @@ class RejectFollowService < BaseService
end end
def build_json(follow_request) def build_json(follow_request)
Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
follow_request, follow_request,
serializer: ActivityPub::RejectFollowSerializer, serializer: ActivityPub::RejectFollowSerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(follow_request.target_account)) ).to_json
end end
def build_xml(follow_request) def build_xml(follow_request)

View file

@ -20,11 +20,11 @@ class UnblockService < BaseService
end end
def build_json(unblock) def build_json(unblock)
Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
unblock, unblock,
serializer: ActivityPub::UndoBlockSerializer, serializer: ActivityPub::UndoBlockSerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(unblock.account)) ).to_json
end end
def build_xml(block) def build_xml(block)

View file

@ -43,11 +43,11 @@ class UnfollowService < BaseService
end end
def build_json(follow) def build_json(follow)
Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
follow, follow,
serializer: ActivityPub::UndoFollowSerializer, serializer: ActivityPub::UndoFollowSerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json).sign!(follow.account)) ).to_json
end end
def build_xml(follow) def build_xml(follow)

View file

@ -12,7 +12,7 @@ class ActivityPub::DistributionWorker
return if skip_distribution? return if skip_distribution?
ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
[signed_payload, @account.id, inbox_url] [payload, @account.id, inbox_url]
end end
relay! if relayable? relay! if relayable?
@ -35,20 +35,24 @@ class ActivityPub::DistributionWorker
end end
def signed_payload def signed_payload
@signed_payload ||= Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@account)) Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@account))
end end
def payload def unsigned_payload
@payload ||= ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
@status, @status,
serializer: ActivityPub::ActivitySerializer, serializer: ActivityPub::ActivitySerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json ).as_json
end end
def payload
@payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload)
end
def relay! def relay!
ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url| ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
[signed_payload, @account.id, inbox_url] [payload, @account.id, inbox_url]
end end
end end
end end

View file

@ -12,7 +12,7 @@ class ActivityPub::ReplyDistributionWorker
return unless @account.present? && @status.distributable? return unless @account.present? && @status.distributable?
ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url| ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
[signed_payload, @status.account_id, inbox_url] [payload, @status.account_id, inbox_url]
end end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
true true
@ -25,14 +25,18 @@ class ActivityPub::ReplyDistributionWorker
end end
def signed_payload def signed_payload
@signed_payload ||= Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@status.account)) Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@status.account))
end end
def payload def unsigned_payload
@payload ||= ActiveModelSerializers::SerializableResource.new( ActiveModelSerializers::SerializableResource.new(
@status, @status,
serializer: ActivityPub::ActivitySerializer, serializer: ActivityPub::ActivitySerializer,
adapter: ActivityPub::Adapter adapter: ActivityPub::Adapter
).as_json ).as_json
end end
def payload
@payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload)
end
end end

View file

@ -26,9 +26,9 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
context 'when actor differs from sender' do context 'when actor differs from sender' do
let(:forwarder) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/other_account') } let(:forwarder) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/other_account') }
it 'processes payload with sender if no signature exists' do it 'does not process payload if no signature exists' do
expect_any_instance_of(ActivityPub::LinkedDataSignature).not_to receive(:verify_account!) expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(nil)
expect(ActivityPub::Activity).to receive(:factory).with(instance_of(Hash), forwarder, instance_of(Hash)) expect(ActivityPub::Activity).not_to receive(:factory)
subject.call(json, forwarder) subject.call(json, forwarder)
end end