You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
3.3 KiB

  1. # frozen_string_literal: true
  2. class SuspendAccountService < BaseService
  3. include Payloadable
  4. def call(account)
  5. @account = account
  6. suspend!
  7. reject_remote_follows!
  8. distribute_update_actor!
  9. unmerge_from_home_timelines!
  10. unmerge_from_list_timelines!
  11. privatize_media_attachments!
  12. end
  13. private
  14. def suspend!
  15. @account.suspend! unless @account.suspended?
  16. end
  17. def reject_remote_follows!
  18. return if @account.local? || !@account.activitypub?
  19. # When suspending a remote account, the account obviously doesn't
  20. # actually become suspended on its origin server, i.e. unlike a
  21. # locally suspended account it continues to have access to its home
  22. # feed and other content. To prevent it from being able to continue
  23. # to access toots it would receive because it follows local accounts,
  24. # we have to force it to unfollow them. Unfortunately, there is no
  25. # counterpart to this operation, i.e. you can't then force a remote
  26. # account to re-follow you, so this part is not reversible.
  27. follows = Follow.where(account: @account).to_a
  28. ActivityPub::DeliveryWorker.push_bulk(follows) do |follow|
  29. [Oj.dump(serialize_payload(follow, ActivityPub::RejectFollowSerializer)), follow.target_account_id, @account.inbox_url]
  30. end
  31. follows.each(&:destroy)
  32. end
  33. def distribute_update_actor!
  34. return unless @account.local?
  35. account_reach_finder = AccountReachFinder.new(@account)
  36. ActivityPub::DeliveryWorker.push_bulk(account_reach_finder.inboxes) do |inbox_url|
  37. [signed_activity_json, @account.id, inbox_url]
  38. end
  39. end
  40. def unmerge_from_home_timelines!
  41. @account.followers_for_local_distribution.find_each do |follower|
  42. FeedManager.instance.unmerge_from_home(@account, follower)
  43. end
  44. end
  45. def unmerge_from_list_timelines!
  46. @account.lists_for_local_distribution.find_each do |list|
  47. FeedManager.instance.unmerge_from_list(@account, list)
  48. end
  49. end
  50. def privatize_media_attachments!
  51. attachment_names = MediaAttachment.attachment_definitions.keys
  52. @account.media_attachments.find_each do |media_attachment|
  53. attachment_names.each do |attachment_name|
  54. attachment = media_attachment.public_send(attachment_name)
  55. styles = [:original] | attachment.styles.keys
  56. next if attachment.blank?
  57. styles.each do |style|
  58. case Paperclip::Attachment.default_options[:storage]
  59. when :s3
  60. begin
  61. attachment.s3_object(style).acl.put(acl: 'private')
  62. rescue Aws::S3::Errors::NoSuchKey
  63. Rails.logger.warn "Tried to change acl on non-existent key #{attachment.s3_object(style).key}"
  64. end
  65. when :fog
  66. # Not supported
  67. when :filesystem
  68. begin
  69. FileUtils.chmod(0o600 & ~File.umask, attachment.path(style)) unless attachment.path(style).nil?
  70. rescue Errno::ENOENT
  71. Rails.logger.warn "Tried to change permission on non-existent file #{attachment.path(style)}"
  72. end
  73. end
  74. CacheBusterWorker.perform_async(attachment.path(style)) if Rails.configuration.x.cache_buster_enabled
  75. end
  76. end
  77. end
  78. end
  79. def signed_activity_json
  80. @signed_activity_json ||= Oj.dump(serialize_payload(@account, ActivityPub::UpdateSerializer, signer: @account))
  81. end
  82. end