From 6a5307a5733e7872e7827f32b27111434e0307c4 Mon Sep 17 00:00:00 2001 From: ThibG Date: Wed, 13 Feb 2019 18:36:23 +0100 Subject: Alternative handling of private self-boosts (#9998) * When self-boosting, embed original toot into Announce serialization * Process unknown self-boosts from Announce object if it is more than an URI * Add some self-boost specs * Only serialize private toots in self-Announces --- app/lib/activitypub/activity.rb | 32 ++++++++++++++++++++++++++++++++ app/lib/activitypub/activity/announce.rb | 4 +--- app/lib/activitypub/activity/create.rb | 15 --------------- 3 files changed, 33 insertions(+), 18 deletions(-) (limited to 'app/lib/activitypub') diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index 919678618..7e4e19531 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -4,6 +4,9 @@ class ActivityPub::Activity include JsonLdHelper include Redisable + SUPPORTED_TYPES = %w(Note).freeze + CONVERTED_TYPES = %w(Image Video Article Page).freeze + def initialize(json, account, **options) @json = json @account = account @@ -71,6 +74,18 @@ class ActivityPub::Activity @object_uri ||= value_or_id(@object) end + def unsupported_object_type? + @object.is_a?(String) || !(supported_object_type? || converted_object_type?) + end + + def supported_object_type? + equals_or_includes_any?(@object['type'], SUPPORTED_TYPES) + end + + def converted_object_type? + equals_or_includes_any?(@object['type'], CONVERTED_TYPES) + end + def distribute(status) crawl_links(status) @@ -120,6 +135,23 @@ class ActivityPub::Activity redis.setex("delete_upon_arrival:#{@account.id}:#{uri}", 6.hours.seconds, uri) end + def status_from_object + # If the status is already known, return it + status = status_from_uri(object_uri) + return status unless status.nil? + + # If the boosted toot is embedded and it is a self-boost, handle it like a Create + unless unsupported_object_type? + actor_id = value_or_id(first_of_value(@object['attributedTo'])) || @account.uri + if actor_id == @account.uri + return ActivityPub::Activity.factory({ 'type' => 'Create', 'actor' => actor_id, 'object' => @object }, @account).perform + end + end + + # If the status is not from the actor, try to fetch it + return fetch_remote_original_status if value_or_id(first_of_value(@json['attributedTo'])) == @account.uri + end + def fetch_remote_original_status if object_uri.start_with?('http') return if ActivityPub::TagManager.instance.local_uri?(object_uri) diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index 34d1b7cbd..04afeea20 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -2,9 +2,7 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity def perform - original_status = status_from_uri(object_uri) - original_status ||= fetch_remote_original_status - + original_status = status_from_object return if original_status.nil? || delete_arrived_first?(@json['id']) || !announceable?(original_status) status = Status.find_by(account: @account, reblog: original_status) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index b49657d4b..9a3db51dd 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true class ActivityPub::Activity::Create < ActivityPub::Activity - SUPPORTED_TYPES = %w(Note).freeze - CONVERTED_TYPES = %w(Image Video Article Page).freeze - def perform return if unsupported_object_type? || invalid_origin?(@object['id']) return if Tombstone.exists?(uri: @object['id']) @@ -318,22 +315,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @object['nameMap'].is_a?(Hash) && !@object['nameMap'].empty? end - def unsupported_object_type? - @object.is_a?(String) || !(supported_object_type? || converted_object_type?) - end - def unsupported_media_type?(mime_type) mime_type.present? && !(MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES).include?(mime_type) end - def supported_object_type? - equals_or_includes_any?(@object['type'], SUPPORTED_TYPES) - end - - def converted_object_type? - equals_or_includes_any?(@object['type'], CONVERTED_TYPES) - end - def skip_download? return @skip_download if defined?(@skip_download) @skip_download ||= DomainBlock.find_by(domain: @account.domain)&.reject_media? -- cgit From dad339da6d19679f0361bfd49d9bcf3a3517af0c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 13 Feb 2019 18:42:47 +0100 Subject: Filter incoming Create activities by relation to local activity (#10005) Reject those from accounts with no local followers, from relays that are not enabled, which do not address local accounts and are not replies to accounts that do have local followers --- app/lib/activitypub/activity/create.rb | 34 ++++++++++++++++++++-- .../activitypub/process_collection_service.rb | 1 + app/workers/activitypub/processing_worker.rb | 2 +- 3 files changed, 34 insertions(+), 3 deletions(-) (limited to 'app/lib/activitypub') diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 9a3db51dd..1b31768d9 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -2,8 +2,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def perform - return if unsupported_object_type? || invalid_origin?(@object['id']) - return if Tombstone.exists?(uri: @object['id']) + return if unsupported_object_type? || invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity? RedisLock.acquire(lock_options) do |lock| if lock.acquired? @@ -337,6 +336,37 @@ class ActivityPub::Activity::Create < ActivityPub::Activity !replied_to_status.nil? && replied_to_status.account.local? end + def related_to_local_activity? + fetch? || followed_by_local_accounts? || requested_through_relay? || + responds_to_followed_account? || addresses_local_accounts? + end + + def fetch? + !@options[:delivery] + end + + def followed_by_local_accounts? + @account.passive_relationships.exists? + end + + def requested_through_relay? + @options[:relayed_through_account] && Relay.find_by(inbox_url: @options[:relayed_through_account].inbox_url)&.enabled? + end + + def responds_to_followed_account? + !replied_to_status.nil? && (replied_to_status.account.local? || replied_to_status.account.passive_relationships.exists?) + end + + def addresses_local_accounts? + return true if @options[:delivered_to_account_id] + + local_usernames = (as_array(@object['to']) + as_array(@object['cc'])).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) } + + return false if local_usernames.empty? + + Account.local.where(username: local_usernames).exists? + end + def forward_for_reply return unless @json['signature'].present? && reply_to_local? ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url]) diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb index 5c54aad89..881df478b 100644 --- a/app/services/activitypub/process_collection_service.rb +++ b/app/services/activitypub/process_collection_service.rb @@ -44,6 +44,7 @@ class ActivityPub::ProcessCollectionService < BaseService end def verify_account! + @options[:relayed_through_account] = @account @account = ActivityPub::LinkedDataSignature.new(@json).verify_account! rescue JSON::LD::JsonLdError => e Rails.logger.debug "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}" diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb index a8a3ebf0f..a3abe72cf 100644 --- a/app/workers/activitypub/processing_worker.rb +++ b/app/workers/activitypub/processing_worker.rb @@ -6,6 +6,6 @@ class ActivityPub::ProcessingWorker sidekiq_options backtrace: true def perform(account_id, body, delivered_to_account_id = nil) - ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id) + ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true) end end -- cgit