about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFire Demon <firedemon@creature.cafe>2020-07-17 19:46:24 -0500
committerFire Demon <firedemon@creature.cafe>2020-08-30 05:41:03 -0500
commit120683f52266900d0fede7bd67c43133bbc26bea (patch)
tree8b6558858bc3928e96d0c11217155e95ebde92a1
parent78d33622a5b53a983e8d37777e8e56b9e3f3c29c (diff)
[Federation] Add support for signing fetches as the participating local user in various scenarios
-rw-r--r--app/lib/activitypub/activity.rb4
-rw-r--r--app/services/activitypub/fetch_featured_collection_service.rb3
-rw-r--r--app/services/activitypub/fetch_replies_service.rb4
-rw-r--r--app/services/fetch_remote_status_service.rb7
-rw-r--r--app/services/fetch_resource_service.rb6
-rw-r--r--app/services/resolve_url_service.rb4
-rw-r--r--app/workers/fetch_reply_worker.rb4
-rw-r--r--app/workers/thread_resolve_worker.rb4
8 files changed, 21 insertions, 15 deletions
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
index ab946470b..cff6b569a 100644
--- a/app/lib/activitypub/activity.rb
+++ b/app/lib/activitypub/activity.rb
@@ -196,9 +196,9 @@ class ActivityPub::Activity
   def fetch_remote_original_status
     if object_uri.start_with?('http')
       return if ActivityPub::TagManager.instance.local_uri?(object_uri)
-      ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first)
+      ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: signed_fetch_account)
     elsif @object['url'].present?
-      ::FetchRemoteStatusService.new.call(@object['url'])
+      ::FetchRemoteStatusService.new.call(@object['url'], nil, signed_fetch_account)
     end
   end
 
diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb
index 2c2770466..c8006afce 100644
--- a/app/services/activitypub/fetch_featured_collection_service.rb
+++ b/app/services/activitypub/fetch_featured_collection_service.rb
@@ -22,9 +22,10 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService
   private
 
   def process_items(items)
+    first_local_follower = @account.followers.local.first
     status_ids = items.map { |item| value_or_id(item) }
                       .reject { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
-                      .map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) }
+                      .map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: first_local_follower) }
                       .compact
                       .select { |status| status.account_id == @account.id }
                       .map(&:id)
diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb
index 8cb309e52..0145f25da 100644
--- a/app/services/activitypub/fetch_replies_service.rb
+++ b/app/services/activitypub/fetch_replies_service.rb
@@ -43,7 +43,7 @@ class ActivityPub::FetchRepliesService < BaseService
     # Only fetch replies to the same server as the original status to avoid
     # amplification attacks.
 
-    # Also limit to 5 fetched replies to limit potential for DoS.
-    @items.map { |item| value_or_id(item) }.reject { |uri| invalid_origin?(uri) }.take(5)
+    # Also limit to 25 fetched replies to limit potential for DoS.
+    @items.map { |item| value_or_id(item) }.reject { |uri| invalid_origin?(uri) }.take(25)
   end
 end
diff --git a/app/services/fetch_remote_status_service.rb b/app/services/fetch_remote_status_service.rb
index eafde4d4a..c5e8c5d0f 100644
--- a/app/services/fetch_remote_status_service.rb
+++ b/app/services/fetch_remote_status_service.rb
@@ -1,14 +1,17 @@
 # frozen_string_literal: true
 
 class FetchRemoteStatusService < BaseService
-  def call(url, prefetched_body = nil)
+  def call(url, prefetched_body = nil, on_behalf_of = nil)
     if prefetched_body.nil?
-      resource_url, resource_options = FetchResourceService.new.call(url)
+      resource_url, resource_options = FetchResourceService.new.call(url, on_behalf_of: on_behalf_of)
     else
       resource_url     = url
       resource_options = { prefetched_body: prefetched_body }
     end
 
+    resource_options ||= {}
+    resource_options[:on_behalf_of] = on_behalf_of
+
     ActivityPub::FetchRemoteStatusService.new.call(resource_url, **resource_options) unless resource_url.nil?
   end
 end
diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb
index 6c0093cd4..3264d14c2 100644
--- a/app/services/fetch_resource_service.rb
+++ b/app/services/fetch_resource_service.rb
@@ -7,9 +7,11 @@ class FetchResourceService < BaseService
 
   attr_reader :response_code
 
-  def call(url)
+  def call(url, on_behalf_of: nil)
     return if url.blank?
 
+    @on_behalf_of = on_behalf_of
+
     process(url)
   rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
     Rails.logger.debug "Error fetching resource #{@url}: #{e}"
@@ -35,7 +37,7 @@ class FetchResourceService < BaseService
       # and prevents even public resources from being fetched, so
       # don't do it
 
-      request.on_behalf_of(Account.representative) unless Rails.env.development?
+      request.on_behalf_of(@on_behalf_of || Account.representative) unless Rails.env.development?
     end.perform(&block)
   end
 
diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb
index 78080d878..bac41f961 100644
--- a/app/services/resolve_url_service.rb
+++ b/app/services/resolve_url_service.rb
@@ -23,7 +23,7 @@ class ResolveURLService < BaseService
     if equals_or_includes_any?(type, ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES)
       ActivityPub::FetchRemoteAccountService.new.call(resource_url, prefetched_body: body)
     elsif equals_or_includes_any?(type, ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
-      status = FetchRemoteStatusService.new.call(resource_url, body)
+      status = FetchRemoteStatusService.new.call(resource_url, body, @on_behalf_of)
       authorize_with @on_behalf_of, status, :show? unless status.nil?
       status
     end
@@ -42,7 +42,7 @@ class ResolveURLService < BaseService
   end
 
   def fetched_resource
-    @fetched_resource ||= fetch_resource_service.call(@url)
+    @fetched_resource ||= fetch_resource_service.call(@url, on_behalf_of: @on_behalf_of)
   end
 
   def fetch_resource_service
diff --git a/app/workers/fetch_reply_worker.rb b/app/workers/fetch_reply_worker.rb
index f7aa25e81..1490f283c 100644
--- a/app/workers/fetch_reply_worker.rb
+++ b/app/workers/fetch_reply_worker.rb
@@ -6,7 +6,7 @@ class FetchReplyWorker
 
   sidekiq_options queue: 'pull', retry: 3
 
-  def perform(child_url)
-    FetchRemoteStatusService.new.call(child_url)
+  def perform(child_url, on_behalf_of = nil)
+    FetchRemoteStatusService.new.call(child_url, nil, on_behalf_of)
   end
 end
diff --git a/app/workers/thread_resolve_worker.rb b/app/workers/thread_resolve_worker.rb
index 8bba9ca75..6516d1bc0 100644
--- a/app/workers/thread_resolve_worker.rb
+++ b/app/workers/thread_resolve_worker.rb
@@ -6,9 +6,9 @@ class ThreadResolveWorker
 
   sidekiq_options queue: 'pull', retry: 3
 
-  def perform(child_status_id, parent_url)
+  def perform(child_status_id, parent_url, on_behalf_of = nil)
     child_status  = Status.find(child_status_id)
-    parent_status = FetchRemoteStatusService.new.call(parent_url)
+    parent_status = FetchRemoteStatusService.new.call(parent_url, nil, on_behalf_of)
 
     return if parent_status.nil?