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.

140 lines
3.1 KiB

  1. # frozen_string_literal: true
  2. class AccountFilter
  3. KEYS = %i(
  4. origin
  5. status
  6. role_ids
  7. username
  8. by_domain
  9. display_name
  10. email
  11. ip
  12. invited_by
  13. order
  14. ).freeze
  15. attr_reader :params
  16. def initialize(params)
  17. @params = params.to_h.symbolize_keys
  18. end
  19. def results
  20. scope = Account.includes(:account_stat, user: [:ips, :invite_request]).without_instance_actor.reorder(nil)
  21. relevant_params.each do |key, value|
  22. next if key.to_s == 'page'
  23. scope.merge!(scope_for(key, value)) if value.present?
  24. end
  25. scope
  26. end
  27. private
  28. def relevant_params
  29. params.tap do |args|
  30. args.delete(:origin) if origin_is_remote_and_domain_present?
  31. end
  32. end
  33. def origin_is_remote_and_domain_present?
  34. params[:origin] == 'remote' && params[:by_domain].present?
  35. end
  36. def scope_for(key, value)
  37. case key.to_s
  38. when 'origin'
  39. origin_scope(value)
  40. when 'role_ids'
  41. role_scope(value)
  42. when 'status'
  43. status_scope(value)
  44. when 'by_domain'
  45. Account.where(domain: value.to_s.strip)
  46. when 'username'
  47. Account.matches_username(value.to_s.strip)
  48. when 'display_name'
  49. Account.matches_display_name(value.to_s.strip)
  50. when 'email'
  51. accounts_with_users.merge(User.matches_email(value.to_s.strip))
  52. when 'ip'
  53. valid_ip?(value) ? accounts_with_users.merge(User.matches_ip(value).group('users.id, accounts.id')) : Account.none
  54. when 'invited_by'
  55. invited_by_scope(value)
  56. when 'order'
  57. order_scope(value)
  58. else
  59. raise Mastodon::InvalidParameterError, "Unknown filter: #{key}"
  60. end
  61. end
  62. def origin_scope(value)
  63. case value.to_s
  64. when 'local'
  65. Account.local
  66. when 'remote'
  67. Account.remote
  68. else
  69. raise Mastodon::InvalidParameterError, "Unknown origin: #{value}"
  70. end
  71. end
  72. def status_scope(value)
  73. case value.to_s
  74. when 'active'
  75. Account.without_suspended
  76. when 'pending'
  77. accounts_with_users.merge(User.pending)
  78. when 'suspended'
  79. Account.suspended
  80. when 'disabled'
  81. accounts_with_users.merge(User.disabled).without_suspended
  82. when 'silenced'
  83. Account.silenced
  84. when 'sensitized'
  85. Account.sensitized
  86. else
  87. raise Mastodon::InvalidParameterError, "Unknown status: #{value}"
  88. end
  89. end
  90. def order_scope(value)
  91. case value.to_s
  92. when 'active'
  93. accounts_with_users
  94. .left_joins(:account_stat)
  95. .order(
  96. Arel.sql(
  97. <<~SQL.squish
  98. COALESCE(users.current_sign_in_at, account_stats.last_status_at, to_timestamp(0)) DESC, accounts.id DESC
  99. SQL
  100. )
  101. )
  102. when 'recent'
  103. Account.recent
  104. else
  105. raise Mastodon::InvalidParameterError, "Unknown order: #{value}"
  106. end
  107. end
  108. def invited_by_scope(value)
  109. Account.left_joins(user: :invite).merge(Invite.where(user_id: value.to_s))
  110. end
  111. def role_scope(value)
  112. accounts_with_users.merge(User.where(role_id: Array(value).map(&:to_s)))
  113. end
  114. def accounts_with_users
  115. Account.left_joins(:user)
  116. end
  117. def valid_ip?(value)
  118. IPAddr.new(value.to_s) && true
  119. rescue IPAddr::InvalidAddressError
  120. false
  121. end
  122. end