about summary refs log tree commit diff
path: root/app/services
diff options
context:
space:
mode:
Diffstat (limited to 'app/services')
-rw-r--r--app/services/delete_account_service.rb5
-rw-r--r--app/services/import_service.rb45
-rw-r--r--app/services/resolve_account_service.rb25
-rw-r--r--app/services/suspend_account_service.rb2
-rw-r--r--app/services/unsuspend_account_service.rb2
5 files changed, 69 insertions, 10 deletions
diff --git a/app/services/delete_account_service.rb b/app/services/delete_account_service.rb
index de6488c78..778d064de 100644
--- a/app/services/delete_account_service.rb
+++ b/app/services/delete_account_service.rb
@@ -41,6 +41,7 @@ class DeleteAccountService < BaseService
   # @option [Boolean] :reserve_email Keep user record. Only applicable for local accounts
   # @option [Boolean] :reserve_username Keep account record
   # @option [Boolean] :skip_side_effects Side effects are ActivityPub and streaming API payloads
+  # @option [Boolean] :skip_activitypub Skip sending ActivityPub payloads. Implied by :skip_side_effects
   # @option [Time]    :suspended_at Only applicable when :reserve_username is true
   def call(account, **options)
     @account = account
@@ -52,6 +53,8 @@ class DeleteAccountService < BaseService
       @options[:skip_side_effects] = true
     end
 
+    @options[:skip_activitypub] = true if @options[:skip_side_effects]
+
     reject_follows!
     purge_user!
     purge_profile!
@@ -62,7 +65,7 @@ class DeleteAccountService < BaseService
   private
 
   def reject_follows!
-    return if @account.local? || !@account.activitypub?
+    return if @account.local? || !@account.activitypub? || @options[:skip_activitypub]
 
     # When deleting a remote account, the account obviously doesn't
     # actually become deleted on its origin server, i.e. unlike a
diff --git a/app/services/import_service.rb b/app/services/import_service.rb
index 7e55452de..288e47f1e 100644
--- a/app/services/import_service.rb
+++ b/app/services/import_service.rb
@@ -18,6 +18,8 @@ class ImportService < BaseService
       import_mutes!
     when 'domain_blocking'
       import_domain_blocks!
+    when 'bookmarks'
+      import_bookmarks!
     end
   end
 
@@ -88,6 +90,39 @@ class ImportService < BaseService
     end
   end
 
+  def import_bookmarks!
+    parse_import_data!(['#uri'])
+    items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#uri'].strip }
+
+    if @import.overwrite?
+      presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true }
+
+      @account.bookmarks.find_each do |bookmark|
+        if presence_hash[bookmark.status.uri]
+          items.delete(bookmark.status.uri)
+        else
+          bookmark.destroy!
+        end
+      end
+    end
+
+    statuses = items.map do |uri|
+      status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
+      next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri)
+
+      status || ActivityPub::FetchRemoteStatusService.new.call(uri)
+    end.compact
+
+    account_ids         = statuses.map(&:account_id)
+    preloaded_relations = relations_map_for_account(@account, account_ids)
+
+    statuses.keep_if { |status| StatusPolicy.new(@account, status, preloaded_relations).show? }
+
+    statuses.each do |status|
+      @account.bookmarks.find_or_create_by!(account: @account, status: status)
+    end
+  end
+
   def parse_import_data!(default_headers)
     data = CSV.parse(import_data, headers: true)
     data = CSV.parse(import_data, headers: default_headers) unless data.headers&.first&.strip&.include?(' ')
@@ -101,4 +136,14 @@ class ImportService < BaseService
   def follow_limit
     FollowLimitValidator.limit_for_account(@account)
   end
+
+  def relations_map_for_account(account, account_ids)
+    {
+      blocking: {},
+      blocked_by: Account.blocked_by_map(account_ids, account.id),
+      muting: {},
+      following: Account.following_map(account_ids, account.id),
+      domain_blocking_by_domain: {},
+    }
+  end
 end
diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb
index 4783e6d33..74b0b82d0 100644
--- a/app/services/resolve_account_service.rb
+++ b/app/services/resolve_account_service.rb
@@ -29,6 +29,7 @@ class ResolveAccountService < BaseService
     # At this point we are in need of a Webfinger query, which may
     # yield us a different username/domain through a redirect
     process_webfinger!(@uri)
+    @domain = nil if TagManager.instance.local_domain?(@domain)
 
     # Because the username/domain pair may be different than what
     # we already checked, we need to check if we've already got
@@ -78,25 +79,31 @@ class ResolveAccountService < BaseService
     @uri = [@username, @domain].compact.join('@')
   end
 
-  def process_webfinger!(uri, redirected = false)
+  def process_webfinger!(uri)
     @webfinger                           = webfinger!("acct:#{uri}")
-    confirmed_username, confirmed_domain = @webfinger.subject.gsub(/\Aacct:/, '').split('@')
+    confirmed_username, confirmed_domain = split_acct(@webfinger.subject)
 
     if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
       @username = confirmed_username
       @domain   = confirmed_domain
-      @uri      = uri
-    elsif !redirected
-      return process_webfinger!("#{confirmed_username}@#{confirmed_domain}", true)
-    else
-      raise Webfinger::RedirectError, "The URI #{uri} tries to hijack #{@username}@#{@domain}"
+      return
     end
 
-    @domain = nil if TagManager.instance.local_domain?(@domain)
+    # Account doesn't match, so it may have been redirected
+    @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, "The URI #{uri} tries to hijack #{@username}@#{@domain}"
+    end
   rescue Webfinger::GoneError
     @gone = true
   end
 
+  def split_acct(acct)
+    acct.gsub(/\Aacct:/, '').split('@')
+  end
+
   def process_account!
     return unless activitypub_ready?
 
@@ -145,7 +152,7 @@ class ResolveAccountService < BaseService
   end
 
   def queue_deletion!
-    AccountDeletionWorker.perform_async(@account.id, reserve_username: false)
+    AccountDeletionWorker.perform_async(@account.id, reserve_username: false, skip_activitypub: true)
   end
 
   def lock_options
diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb
index 9bf94bb2b..52fed7c26 100644
--- a/app/services/suspend_account_service.rb
+++ b/app/services/suspend_account_service.rb
@@ -80,6 +80,8 @@ class SuspendAccountService < BaseService
               Rails.logger.warn "Tried to change permission on non-existent file #{attachment.path(style)}"
             end
           end
+
+          CacheBusterWorker.perform_async(attachment.path(style)) if Rails.configuration.x.cache_buster_enabled
         end
       end
     end
diff --git a/app/services/unsuspend_account_service.rb b/app/services/unsuspend_account_service.rb
index a81d1ac4f..f07a3f053 100644
--- a/app/services/unsuspend_account_service.rb
+++ b/app/services/unsuspend_account_service.rb
@@ -69,6 +69,8 @@ class UnsuspendAccountService < BaseService
               Rails.logger.warn "Tried to change permission on non-existent file #{attachment.path(style)}"
             end
           end
+
+          CacheBusterWorker.perform_async(attachment.path(style)) if Rails.configuration.x.cache_buster_enabled
         end
       end
     end