about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFire Demon <firedemon@creature.cafe>2020-08-17 13:06:21 -0500
committerFire Demon <firedemon@creature.cafe>2020-08-30 05:45:18 -0500
commit772fef7d30271d1451e11f4037ec7fdfbd44ccdd (patch)
tree9ea63f008b17f42e91753bbd90b0492600beee4d
parent2db84dda1c4353c16655c7b66facd32cb1772afb (diff)
[Federation] Allow passive federation from allowlisted servers
-rw-r--r--app/lib/activitypub/activity/announce.rb14
-rw-r--r--app/lib/activitypub/activity/create.rb60
-rw-r--r--app/lib/activitypub/activity/delete.rb7
3 files changed, 28 insertions, 53 deletions
diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb
index 9e108985a..c636d233d 100644
--- a/app/lib/activitypub/activity/announce.rb
+++ b/app/lib/activitypub/activity/announce.rb
@@ -2,7 +2,7 @@
 
 class ActivityPub::Activity::Announce < ActivityPub::Activity
   def perform
-    return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity?
+    return reject_payload! if delete_arrived_first?(@json['id'])
 
     RedisLock.acquire(lock_options) do |lock|
       if lock.acquired?
@@ -50,18 +50,6 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity
     status.account_id == @account.id || status.distributable?
   end
 
-  def related_to_local_activity?
-    followed_by_local_accounts? || requested_through_relay? || reblog_of_local_status?
-  end
-
-  def requested_through_relay?
-    super || Relay.find_by(inbox_url: @account.inbox_url)&.enabled?
-  end
-
-  def reblog_of_local_status?
-    status_from_uri(object_uri)&.account&.local?
-  end
-
   def lock_options
     { redis: Redis.current, key: "announce:#{@object['id']}" }
   end
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 91f0ab146..d37203c40 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -1,5 +1,6 @@
 # frozen_string_literal: true
 
+# rubocop:disable Metrics/ClassLength
 class ActivityPub::Activity::Create < ActivityPub::Activity
   include ImgProxyHelper
 
@@ -17,7 +18,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   private
 
   def create_encrypted_message
-    return reject_payload! if invalid_origin?(@object['id']) || @options[:delivered_to_account_id].blank?
+    return reject_payload! if invalid_origin?(object_uri) || @options[:delivered_to_account_id].blank?
 
     target_account = Account.find(@options[:delivered_to_account_id])
     target_device  = target_account.devices.find_by(device_id: @object.dig('to', 'deviceId'))
@@ -45,7 +46,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   end
 
   def create_status
-    return reject_payload! if unsupported_object_type? || invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity?
+    return reject_payload! if unsupported_object_type? || invalid_origin?(object_uri) || Tombstone.exists?(uri: object_uri)
 
     RedisLock.acquire(lock_options) do |lock|
       if lock.acquired?
@@ -74,6 +75,10 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     @object['cc'] || @json['cc']
   end
 
+  def object_uri
+    @object['id'] || super
+  end
+
   def process_status
     @tags     = []
     @mentions = []
@@ -116,8 +121,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   def process_status_params
     @params = begin
       {
-        uri: @object['id'],
-        url: object_url || @object['id'],
+        uri: object_uri,
+        url: object_url || object_uri,
         account: @account,
         text: text_from_content || '',
         language: detected_language,
@@ -356,7 +361,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     RedisLock.acquire(poll_lock_options) do |lock|
       if lock.acquired?
         already_voted = poll.votes.where(account: @account).exists?
-        poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: @object['id'])
+        poll.votes.create!(account: @account, choice: poll.options.index(@object['name']), uri: object_uri)
       else
         raise Mastodon::RaceConditionError
       end
@@ -373,7 +378,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   end
 
   def fetch_replies(status)
-    FetchReplyWorker.perform_async(@object['root']) unless @object['root'].blank? || [@object['id'], @object['url']].include?(@object['root']) || status_from_uri(@object['root'])
+    FetchReplyWorker.perform_async(@object['root']) unless @object['root'].blank? || [object_uri, @object['url']].include?(@object['root']) || status_from_uri(@object['root'])
 
     collection = @object['replies']
     return if collection.nil?
@@ -387,16 +392,23 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 
   def conversation_from_uri(uri)
     return nil if uri.nil?
+
     conversation = OStatus::TagManager.instance.local_id?(uri) ? Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) : nil
 
     begin
       conversation = Conversation.find_by(uri: uri) if conversation.blank?
 
       if @object['inReplyTo'].blank? && replied_to_status.blank?
+        params = {
+          uri: uri,
+          root: object_uri,
+          account: @account,
+          public: %i(public unlisted).include?(visibility_from_audience),
+        }.freeze
         if conversation.blank?
-          conversation = Conversation.create!(uri: uri, root: @object['id'], account: @account, public: %i(public unlisted).include?(visibility_from_audience))
+          conversation = Conversation.create!(params)
         elsif conversation.root.blank?
-          conversation.update!(root: @object['id'], account: @account, public: %i(public unlisted).include?(visibility_from_audience))
+          conversation.update!(params)
         end
       elsif conversation.blank?
         conversation = Conversation.create!(uri: uri, account_id: nil, public: false)
@@ -434,7 +446,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   def replied_to_status
     return @replied_to_status if defined?(@replied_to_status)
 
-    if in_reply_to_uri.blank?
+    if in_reply_to_uri.blank? || in_reply_to_uri == object_uri
       @replied_to_status = nil
     else
       @replied_to_status   = status_from_uri(in_reply_to_uri)
@@ -448,7 +460,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   end
 
   def text_from_content
-    return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || @object['id']].join(' ')) if converted_object_type?
+    return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || object_uri].join(' ')) if converted_object_type?
 
     if @object['content'].present?
       @object['type'] == 'Article' ? Formatter.instance.format_article(@object['content']) : @object['content']
@@ -536,35 +548,12 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
     @skip_download ||= DomainBlock.reject_media?(@account.domain)
   end
 
-  def reply_to_local?
-    !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 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(audience_to) + as_array(audience_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 check_for_spam
     SpamCheck.perform(@status)
   end
 
   def forward_for_reply
-    return unless @json['signature'].present? && reply_to_local?
+    return if @json['signature'].blank? || replied_to_status.blank?
 
     ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url])
   end
@@ -582,10 +571,11 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   end
 
   def lock_options
-    { redis: Redis.current, key: "create:#{@object['id']}" }
+    { redis: Redis.current, key: "create:#{object_uri}" }
   end
 
   def poll_lock_options
     { redis: Redis.current, key: "vote:#{replied_to_status.poll_id}:#{@account.id}" }
   end
 end
+# rubocop:enable Metrics/ClassLength
diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb
index dc9ff580c..1420c6aff 100644
--- a/app/lib/activitypub/activity/delete.rb
+++ b/app/lib/activitypub/activity/delete.rb
@@ -51,15 +51,12 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
 
   def replied_to_status
     return @replied_to_status if defined?(@replied_to_status)
-    @replied_to_status = @status.thread
-  end
 
-  def reply_to_local?
-    !replied_to_status.nil? && replied_to_status.account.local?
+    @replied_to_status = @status.thread
   end
 
   def forward_for_reply
-    return unless @json['signature'].present? && reply_to_local?
+    return if @json['signature'].blank? || replied_to_status.blank?
 
     inboxes = replied_to_status.account.followers.inboxes - [@account.preferred_inbox_url]