Add pagination to search
[akkoma] / lib / pleroma / user.ex
index cfb44ebaa4cb9d306bd9588bc0e983152dcb6927..230155c3375f24b9f054b8b397ac9f77ea04a5c8 100644 (file)
@@ -273,7 +273,7 @@ defmodule Pleroma.User do
          Pleroma.Config.get([:instance, :account_activation_required]) do
       user
       |> Pleroma.UserEmail.account_confirmation_email()
-      |> Pleroma.Mailer.deliver()
+      |> Pleroma.Mailer.deliver_async()
     else
       {:ok, :noop}
     end
@@ -547,11 +547,8 @@ defmodule Pleroma.User do
   end
 
   def get_followers_query(user, page) do
-    from(
-      u in get_followers_query(user, nil),
-      limit: 20,
-      offset: ^((page - 1) * 20)
-    )
+    from(u in get_followers_query(user, nil))
+    |> paginate(page, 20)
   end
 
   def get_followers_query(user), do: get_followers_query(user, nil)
@@ -577,11 +574,8 @@ defmodule Pleroma.User do
   end
 
   def get_friends_query(user, page) do
-    from(
-      u in get_friends_query(user, nil),
-      limit: 20,
-      offset: ^((page - 1) * 20)
-    )
+    from(u in get_friends_query(user, nil))
+    |> paginate(page, 20)
   end
 
   def get_friends_query(user), do: get_friends_query(user, nil)
@@ -755,6 +749,46 @@ defmodule Pleroma.User do
     Repo.all(query)
   end
 
+  @spec search_for_admin(binary(), %{
+          admin: Pleroma.User.t(),
+          local: boolean(),
+          page: number(),
+          page_size: number()
+        }) :: {:ok, [Pleroma.User.t()], number()}
+  def search_for_admin(term, %{admin: admin, local: local, page: page, page_size: page_size}) do
+    term = String.trim_leading(term, "@")
+
+    local_paginated_query =
+      User
+      |> maybe_local_user_query(local)
+      |> paginate(page, page_size)
+
+    search_query = fts_search_subquery(term, local_paginated_query)
+
+    count =
+      term
+      |> fts_search_subquery()
+      |> maybe_local_user_query(local)
+      |> Repo.aggregate(:count, :id)
+
+    {:ok, do_search(search_query, admin), count}
+  end
+
+  @spec all_for_admin(number(), number()) :: {:ok, [Pleroma.User.t()], number()}
+  def all_for_admin(page, page_size) do
+    query = from(u in User, order_by: u.id)
+
+    paginated_query =
+      query
+      |> paginate(page, page_size)
+
+    count =
+      query
+      |> Repo.aggregate(:count, :id)
+
+    {:ok, Repo.all(paginated_query), count}
+  end
+
   def search(query, resolve \\ false, for_user \\ nil) do
     # Strip the beginning @ off if there is a query
     query = String.trim_leading(query, "@")
@@ -788,9 +822,9 @@ defmodule Pleroma.User do
     boost_search_results(results, for_user)
   end
 
-  defp fts_search_subquery(query) do
+  defp fts_search_subquery(term, query \\ User) do
     processed_query =
-      query
+      term
       |> String.replace(~r/\W+/, " ")
       |> String.trim()
       |> String.split()
@@ -798,7 +832,7 @@ defmodule Pleroma.User do
       |> Enum.join(" | ")
 
     from(
-      u in User,
+      u in query,
       select_merge: %{
         search_rank:
           fragment(
@@ -828,19 +862,19 @@ defmodule Pleroma.User do
     )
   end
 
-  defp trigram_search_subquery(query) do
+  defp trigram_search_subquery(term) do
     from(
       u in User,
       select_merge: %{
         search_rank:
           fragment(
             "similarity(?, trim(? || ' ' || coalesce(?, '')))",
-            ^query,
+            ^term,
             u.nickname,
             u.name
           )
       },
-      where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^query)
+      where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term)
     )
   end
 
@@ -889,21 +923,27 @@ defmodule Pleroma.User do
   end
 
   def mute(muter, %User{ap_id: ap_id}) do
-    mutes = muter.info["mutes"] || []
-    new_mutes = Enum.uniq([ap_id | mutes])
-    new_info = Map.put(muter.info, "mutes", new_mutes)
+    info_cng =
+      muter.info
+      |> User.Info.add_to_mutes(ap_id)
+
+    cng =
+      change(muter)
+      |> put_embed(:info, info_cng)
 
-    User.info_changeset(muter, %{info: new_info})
-    |> update_and_set_cache()
+    update_and_set_cache(cng)
   end
 
-  def unmute(user, %{ap_id: ap_id}) do
-    mutes = user.info["mutes"] || []
-    new_mutes = List.delete(mutes, ap_id)
-    new_info = Map.put(user.info, "mutes", new_mutes)
+  def unmute(muter, %{ap_id: ap_id}) do
+    info_cng =
+      muter.info
+      |> User.Info.remove_from_mutes(ap_id)
+
+    cng =
+      change(muter)
+      |> put_embed(:info, info_cng)
 
-    User.info_changeset(user, %{info: new_info})
-    |> update_and_set_cache()
+    update_and_set_cache(cng)
   end
 
   def block(blocker, %User{ap_id: ap_id} = blocked) do
@@ -948,7 +988,7 @@ defmodule Pleroma.User do
     update_and_set_cache(cng)
   end
 
-  def mutes?(user, %{ap_id: ap_id}), do: Enum.member?(user.info["mutes"] || [], ap_id)
+  def mutes?(user, %{ap_id: ap_id}), do: Enum.member?(user.info.mutes, ap_id)
 
   def blocks?(user, %{ap_id: ap_id}) do
     blocks = user.info.blocks
@@ -961,6 +1001,9 @@ defmodule Pleroma.User do
       end)
   end
 
+  def muted_users(user),
+    do: Repo.all(from(u in User, where: u.ap_id in ^user.info.mutes))
+
   def blocked_users(user),
     do: Repo.all(from(u in User, where: u.ap_id in ^user.info.blocks))
 
@@ -988,9 +1031,13 @@ defmodule Pleroma.User do
     update_and_set_cache(cng)
   end
 
-  def local_user_query do
+  def maybe_local_user_query(query, local) do
+    if local, do: local_user_query(query), else: query
+  end
+
+  def local_user_query(query \\ User) do
     from(
-      u in User,
+      u in query,
       where: u.local == true,
       where: not is_nil(u.nickname)
     )
@@ -1178,9 +1225,6 @@ defmodule Pleroma.User do
   def parse_bio(bio, _user) when bio == "", do: bio
 
   def parse_bio(bio, user) do
-    mentions = Formatter.parse_mentions(bio)
-    tags = Formatter.parse_tags(bio)
-
     emoji =
       (user.info.source_data["tag"] || [])
       |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
@@ -1189,7 +1233,8 @@ defmodule Pleroma.User do
       end)
 
     bio
-    |> CommonUtils.format_input(mentions, tags, "text/plain", user_links: [format: :full])
+    |> CommonUtils.format_input("text/plain", mentions_format: :full)
+    |> elem(0)
     |> Formatter.emojify(emoji)
   end
 
@@ -1275,4 +1320,20 @@ defmodule Pleroma.User do
       inserted_at: NaiveDateTime.utc_now()
     }
   end
+
+  def all_superusers do
+    from(
+      u in User,
+      where: u.local == true,
+      where: fragment("?->'is_admin' @> 'true' OR ?->'is_moderator' @> 'true'", u.info, u.info)
+    )
+    |> Repo.all()
+  end
+
+  defp paginate(query, page, page_size) do
+    from(u in query,
+      limit: ^page_size,
+      offset: ^((page - 1) * page_size)
+    )
+  end
 end