]> cat aescling's git repositories - mastodon.git/commitdiff
Filter incoming Create activities by relation to local activity (#10005)
authorEugen Rochko <eugen@zeonfederated.com>
Wed, 13 Feb 2019 17:42:47 +0000 (18:42 +0100)
committerGitHub <noreply@github.com>
Wed, 13 Feb 2019 17:42:47 +0000 (18:42 +0100)
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
app/services/activitypub/process_collection_service.rb
app/workers/activitypub/processing_worker.rb

index 9a3db51dd9e6bd1d12d717b67dd7297e859f18e5..1b31768d964a61dc8b649823e2b27e9a3f54fcc8 100644 (file)
@@ -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])
index 5c54aad89f18407d6c05d51481717296e066b8d1..881df478bf53c7b265df09c1cf01917c4a9ae382 100644 (file)
@@ -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}"
index a8a3ebf0f56987c433c8ccc67d7bfe45543318e9..a3abe72cf66eed1b4ee038906d4075c35bcc2f8c 100644 (file)
@@ -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