about summary refs log tree commit diff
path: root/app/services/activitypub
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/activitypub')
-rw-r--r--app/services/activitypub/fetch_featured_collection_service.rb2
-rw-r--r--app/services/activitypub/fetch_featured_tags_collection_service.rb14
-rw-r--r--app/services/activitypub/fetch_remote_account_service.rb2
-rw-r--r--app/services/activitypub/fetch_remote_actor_service.rb8
-rw-r--r--app/services/activitypub/fetch_remote_key_service.rb2
-rw-r--r--app/services/activitypub/fetch_remote_status_service.rb26
-rw-r--r--app/services/activitypub/fetch_replies_service.rb5
-rw-r--r--app/services/activitypub/process_account_service.rb2
-rw-r--r--app/services/activitypub/process_collection_service.rb6
-rw-r--r--app/services/activitypub/process_status_update_service.rb6
10 files changed, 40 insertions, 33 deletions
diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb
index a746ef4d6..1208820df 100644
--- a/app/services/activitypub/fetch_featured_collection_service.rb
+++ b/app/services/activitypub/fetch_featured_collection_service.rb
@@ -53,7 +53,7 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService
 
       status.id
     rescue ActiveRecord::RecordInvalid => e
-      Rails.logger.debug "Invalid pinned status #{uri}: #{e.message}"
+      Rails.logger.debug { "Invalid pinned status #{uri}: #{e.message}" }
       nil
     end
 
diff --git a/app/services/activitypub/fetch_featured_tags_collection_service.rb b/app/services/activitypub/fetch_featured_tags_collection_service.rb
index ab047a0f8..ff1a88aa1 100644
--- a/app/services/activitypub/fetch_featured_tags_collection_service.rb
+++ b/app/services/activitypub/fetch_featured_tags_collection_service.rb
@@ -22,14 +22,12 @@ class ActivityPub::FetchFeaturedTagsCollectionService < BaseService
     collection = fetch_collection(collection['first']) if collection['first'].present?
 
     while collection.is_a?(Hash)
-      items = begin
-        case collection['type']
-        when 'Collection', 'CollectionPage'
-          collection['items']
-        when 'OrderedCollection', 'OrderedCollectionPage'
-          collection['orderedItems']
-        end
-      end
+      items = case collection['type']
+              when 'Collection', 'CollectionPage'
+                collection['items']
+              when 'OrderedCollection', 'OrderedCollectionPage'
+                collection['orderedItems']
+              end
 
       break if items.blank?
 
diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb
index 7aba8269e..567dd8a14 100644
--- a/app/services/activitypub/fetch_remote_account_service.rb
+++ b/app/services/activitypub/fetch_remote_account_service.rb
@@ -6,7 +6,7 @@ class ActivityPub::FetchRemoteAccountService < ActivityPub::FetchRemoteActorServ
     actor = super
     return actor if actor.nil? || actor.is_a?(Account)
 
-    Rails.logger.debug "Fetching account #{uri} failed: Expected Account, got #{actor.class.name}"
+    Rails.logger.debug { "Fetching account #{uri} failed: Expected Account, got #{actor.class.name}" }
     raise Error, "Expected Account, got #{actor.class.name}" unless suppress_errors
   end
 end
diff --git a/app/services/activitypub/fetch_remote_actor_service.rb b/app/services/activitypub/fetch_remote_actor_service.rb
index a25fa54c4..c29570086 100644
--- a/app/services/activitypub/fetch_remote_actor_service.rb
+++ b/app/services/activitypub/fetch_remote_actor_service.rb
@@ -28,6 +28,7 @@ class ActivityPub::FetchRemoteActorService < BaseService
     raise Error, "Unsupported JSON-LD context for document #{uri}" unless supported_context?
     raise Error, "Unexpected object type for actor #{uri} (expected any of: #{SUPPORTED_TYPES})" unless expected_type?
     raise Error, "Actor #{uri} has moved to #{@json['movedTo']}" if break_on_redirect && @json['movedTo'].present?
+    raise Error, "Actor #{uri} has no 'preferredUsername', which is a requirement for Mastodon compatibility" if @json['preferredUsername'].blank?
 
     @uri      = @json['id']
     @username = @json['preferredUsername']
@@ -37,7 +38,7 @@ class ActivityPub::FetchRemoteActorService < BaseService
 
     ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key, verified_webfinger: !only_key, request_id: request_id)
   rescue Error => e
-    Rails.logger.debug "Fetching actor #{uri} failed: #{e.message}"
+    Rails.logger.debug { "Fetching actor #{uri} failed: #{e.message}" }
     raise unless suppress_errors
   end
 
@@ -49,15 +50,14 @@ class ActivityPub::FetchRemoteActorService < BaseService
 
     if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
       raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri
+
       return
     end
 
     webfinger                            = webfinger!("acct:#{confirmed_username}@#{confirmed_domain}")
     @username, @domain                   = split_acct(webfinger.subject)
 
-    unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
-      raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{@uri} (stopped at #{@username}@#{@domain})"
-    end
+    raise Webfinger::RedirectError, "Too many webfinger redirects for URI #{@uri} (stopped at #{@username}@#{@domain})" unless confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
 
     raise Error, "Webfinger response for #{@username}@#{@domain} does not loop back to #{@uri}" if webfinger.link('self', 'href') != @uri
   rescue Webfinger::RedirectError => e
diff --git a/app/services/activitypub/fetch_remote_key_service.rb b/app/services/activitypub/fetch_remote_key_service.rb
index 32e82b47a..8eb97c1e6 100644
--- a/app/services/activitypub/fetch_remote_key_service.rb
+++ b/app/services/activitypub/fetch_remote_key_service.rb
@@ -38,7 +38,7 @@ class ActivityPub::FetchRemoteKeyService < BaseService
 
     find_actor(owner_uri, @owner, suppress_errors)
   rescue Error => e
-    Rails.logger.debug "Fetching key #{uri} failed: #{e.message}"
+    Rails.logger.debug { "Fetching key #{uri} failed: #{e.message}" }
     raise unless suppress_errors
   end
 
diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb
index 21b9242f8..ab0acf7f0 100644
--- a/app/services/activitypub/fetch_remote_status_service.rb
+++ b/app/services/activitypub/fetch_remote_status_service.rb
@@ -2,17 +2,18 @@
 
 class ActivityPub::FetchRemoteStatusService < BaseService
   include JsonLdHelper
+  include Redisable
+
+  DISCOVERIES_PER_REQUEST = 1000
 
   # Should be called when uri has already been checked for locality
   def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil, expected_actor_uri: nil, request_id: nil)
-    @request_id = request_id
-    @json = begin
-      if prefetched_body.nil?
-        fetch_resource(uri, id, on_behalf_of)
-      else
-        body_to_json(prefetched_body, compare_id: id ? uri : nil)
-      end
-    end
+    @request_id = request_id || "#{Time.now.utc.to_i}-status-#{uri}"
+    @json = if prefetched_body.nil?
+              fetch_resource(uri, id, on_behalf_of)
+            else
+              body_to_json(prefetched_body, compare_id: id ? uri : nil)
+            end
 
     return unless supported_context?
 
@@ -42,13 +43,20 @@ class ActivityPub::FetchRemoteStatusService < BaseService
     # activity as an update rather than create
     activity_json['type'] = 'Update' if equals_or_includes_any?(activity_json['type'], %w(Create)) && Status.where(uri: object_uri, account_id: actor.id).exists?
 
-    ActivityPub::Activity.factory(activity_json, actor, request_id: request_id).perform
+    with_redis do |redis|
+      discoveries = redis.incr("status_discovery_per_request:#{@request_id}")
+      redis.expire("status_discovery_per_request:#{@request_id}", 5.minutes.seconds)
+      return nil if discoveries > DISCOVERIES_PER_REQUEST
+    end
+
+    ActivityPub::Activity.factory(activity_json, actor, request_id: @request_id).perform
   end
 
   private
 
   def trustworthy_attribution?(uri, attributed_to)
     return false if uri.nil? || attributed_to.nil?
+
     Addressable::URI.parse(uri).normalized_host.casecmp(Addressable::URI.parse(attributed_to).normalized_host).zero?
   end
 
diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb
index 8cb309e52..3fe150ba2 100644
--- a/app/services/activitypub/fetch_replies_service.rb
+++ b/app/services/activitypub/fetch_replies_service.rb
@@ -3,14 +3,14 @@
 class ActivityPub::FetchRepliesService < BaseService
   include JsonLdHelper
 
-  def call(parent_status, collection_or_uri, allow_synchronous_requests = true)
+  def call(parent_status, collection_or_uri, allow_synchronous_requests: true, request_id: nil)
     @account = parent_status.account
     @allow_synchronous_requests = allow_synchronous_requests
 
     @items = collection_items(collection_or_uri)
     return if @items.nil?
 
-    FetchReplyWorker.push_bulk(filtered_replies)
+    FetchReplyWorker.push_bulk(filtered_replies) { |reply_uri| [reply_uri, { 'request_id' => request_id }] }
 
     @items
   end
@@ -36,6 +36,7 @@ class ActivityPub::FetchRepliesService < BaseService
     return collection_or_uri if collection_or_uri.is_a?(Hash)
     return unless @allow_synchronous_requests
     return if invalid_origin?(collection_or_uri)
+
     fetch_resource_without_id_validation(collection_or_uri, nil, true)
   end
 
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index 2da9096c7..603e4cf48 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -226,6 +226,7 @@ class ActivityPub::ProcessAccountService < BaseService
 
   def property_values
     return unless @json['attachment'].is_a?(Array)
+
     as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
   end
 
@@ -289,6 +290,7 @@ class ActivityPub::ProcessAccountService < BaseService
 
   def domain_block
     return @domain_block if defined?(@domain_block)
+
     @domain_block = DomainBlock.rule_for(@domain)
   end
 
diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb
index fffe30195..52f48bd49 100644
--- a/app/services/activitypub/process_collection_service.rb
+++ b/app/services/activitypub/process_collection_service.rb
@@ -11,7 +11,7 @@ class ActivityPub::ProcessCollectionService < BaseService
     begin
       @json = compact(@json) if @json['signature'].is_a?(Hash)
     rescue JSON::LD::JsonLdError => e
-      Rails.logger.debug "Error when compacting JSON-LD document for #{value_or_id(@json['actor'])}: #{e.message}"
+      Rails.logger.debug { "Error when compacting JSON-LD document for #{value_or_id(@json['actor'])}: #{e.message}" }
       @json = original_json.without('signature')
     end
 
@@ -71,8 +71,8 @@ class ActivityPub::ProcessCollectionService < BaseService
     @account = ActivityPub::LinkedDataSignature.new(@json).verify_actor!
     @account = nil unless @account.is_a?(Account)
     @account
-  rescue JSON::LD::JsonLdError => e
-    Rails.logger.debug "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}"
+  rescue JSON::LD::JsonLdError, RDF::WriterError => e
+    Rails.logger.debug { "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}" }
     nil
   end
 end
diff --git a/app/services/activitypub/process_status_update_service.rb b/app/services/activitypub/process_status_update_service.rb
index 11b38ab92..ac7372f74 100644
--- a/app/services/activitypub/process_status_update_service.rb
+++ b/app/services/activitypub/process_status_update_service.rb
@@ -80,9 +80,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
 
         # If a previously existing media attachment was significantly updated, mark
         # media attachments as changed even if none were added or removed
-        if media_attachment_parser.significantly_changes?(media_attachment)
-          @media_attachments_changed = true
-        end
+        @media_attachments_changed = true if media_attachment_parser.significantly_changes?(media_attachment)
 
         media_attachment.description          = media_attachment_parser.description
         media_attachment.focus                = media_attachment_parser.focus
@@ -94,7 +92,7 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
 
         @next_media_attachments << media_attachment
       rescue Addressable::URI::InvalidURIError => e
-        Rails.logger.debug "Invalid URL in attachment: #{e}"
+        Rails.logger.debug { "Invalid URL in attachment: #{e}" }
       end
     end