logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/

database_search.ex (3923B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Search.DatabaseSearch do
  5. alias Pleroma.Activity
  6. alias Pleroma.Config
  7. alias Pleroma.Object.Fetcher
  8. alias Pleroma.Pagination
  9. alias Pleroma.User
  10. alias Pleroma.Web.ActivityPub.Visibility
  11. require Pleroma.Constants
  12. import Ecto.Query
  13. @behaviour Pleroma.Search.SearchBackend
  14. @impl true
  15. def search(user, search_query, options \\ []) do
  16. index_type = if Config.get([:database, :rum_enabled]), do: :rum, else: :gin
  17. limit = Enum.min([Keyword.get(options, :limit), 40])
  18. offset = Keyword.get(options, :offset, 0)
  19. author = Keyword.get(options, :author)
  20. try do
  21. Activity
  22. |> Activity.with_preloaded_object()
  23. |> Activity.restrict_deactivated_users()
  24. |> restrict_public(user)
  25. |> query_with(index_type, search_query)
  26. |> maybe_restrict_local(user)
  27. |> maybe_restrict_author(author)
  28. |> maybe_restrict_blocked(user)
  29. |> Pagination.fetch_paginated(
  30. %{"offset" => offset, "limit" => limit, "skip_order" => index_type == :rum},
  31. :offset
  32. )
  33. |> maybe_fetch(user, search_query)
  34. rescue
  35. _ -> maybe_fetch([], user, search_query)
  36. end
  37. end
  38. @impl true
  39. def add_to_index(_activity), do: :ok
  40. @impl true
  41. def remove_from_index(_object), do: :ok
  42. @impl true
  43. def create_index, do: :ok
  44. @impl true
  45. def drop_index, do: :ok
  46. @impl true
  47. def healthcheck_endpoints, do: nil
  48. def maybe_restrict_author(query, %User{} = author) do
  49. Activity.Queries.by_author(query, author)
  50. end
  51. def maybe_restrict_author(query, _), do: query
  52. def maybe_restrict_blocked(query, %User{} = user) do
  53. Activity.Queries.exclude_authors(query, User.blocked_users_ap_ids(user))
  54. end
  55. def maybe_restrict_blocked(query, _), do: query
  56. defp restrict_public(q, user) when not is_nil(user) do
  57. intended_recipients = [
  58. Pleroma.Constants.as_public(),
  59. Pleroma.Web.ActivityPub.Utils.as_local_public()
  60. ]
  61. from([a, o] in q,
  62. where: fragment("?->>'type' = 'Create'", a.data),
  63. where: fragment("? && ?", ^intended_recipients, a.recipients)
  64. )
  65. end
  66. defp restrict_public(q, _user) do
  67. from([a, o] in q,
  68. where: fragment("?->>'type' = 'Create'", a.data),
  69. where: ^Pleroma.Constants.as_public() in a.recipients
  70. )
  71. end
  72. defp query_with(q, :gin, search_query) do
  73. %{rows: [[tsc]]} =
  74. Ecto.Adapters.SQL.query!(
  75. Pleroma.Repo,
  76. "select current_setting('default_text_search_config')::regconfig::oid;"
  77. )
  78. from([a, o] in q,
  79. where:
  80. fragment(
  81. "to_tsvector(?::oid::regconfig, ?->>'content') @@ websearch_to_tsquery(?)",
  82. ^tsc,
  83. o.data,
  84. ^search_query
  85. )
  86. )
  87. end
  88. defp query_with(q, :rum, search_query) do
  89. from([a, o] in q,
  90. where:
  91. fragment(
  92. "? @@ websearch_to_tsquery(?)",
  93. o.fts_content,
  94. ^search_query
  95. ),
  96. order_by: [fragment("? <=> now()::date", o.inserted_at)]
  97. )
  98. end
  99. def maybe_restrict_local(q, user) do
  100. limit = Config.get([:instance, :limit_to_local_content], :unauthenticated)
  101. case {limit, user} do
  102. {:all, _} -> restrict_local(q)
  103. {:unauthenticated, %User{}} -> q
  104. {:unauthenticated, _} -> restrict_local(q)
  105. {false, _} -> q
  106. end
  107. end
  108. defp restrict_local(q), do: where(q, local: true)
  109. def maybe_fetch(activities, user, search_query) do
  110. with true <- Regex.match?(~r/https?:/, search_query),
  111. {:ok, object} <- Fetcher.fetch_object_from_id(search_query),
  112. %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
  113. true <- Visibility.visible_for_user?(activity, user) do
  114. [activity | activities]
  115. else
  116. _ -> activities
  117. end
  118. end
  119. end