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)
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)
Repo.all(query)
end
- def search(term, options \\ %{}) do
- # Strip the beginning @ off if there is a query
+ @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, "@")
- query = options[:query] || User
- if options[:resolve], do: get_or_fetch(term)
+ local_paginated_query =
+ User
+ |> maybe_local_user_query(local)
+ |> paginate(page, page_size)
- fts_results =
- do_search(fts_search_subquery(term, query), options[:for_user], limit: options[:limit])
+ search_query = fts_search_subquery(term, local_paginated_query)
- {:ok, trigram_results} =
- Repo.transaction(fn ->
- Ecto.Adapters.SQL.query(Repo, "select set_limit(0.25)", [])
-
- do_search(trigram_search_subquery(term, query), options[:for_user], limit: options[:limit])
- end)
+ count =
+ term
+ |> fts_search_subquery()
+ |> maybe_local_user_query(local)
+ |> Repo.aggregate(:count, :id)
- Enum.uniq_by(fts_results ++ trigram_results, & &1.id)
+ {:ok, do_search(search_query, admin), count}
end
- def all(page, page_size) do
- from(
- u in User,
- limit: ^page_size,
- offset: ^((page - 1) * page_size),
- order_by: u.id
- )
- |> Repo.all()
+ @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 count_all_except_one(user) do
- query =
- from(
- u in User,
- where: u.id != ^user.id
- )
+ def search(query, resolve \\ false, for_user \\ nil) do
+ # Strip the beginning @ off if there is a query
+ query = String.trim_leading(query, "@")
+
+ if resolve, do: get_or_fetch(query)
+
+ fts_results = do_search(fts_search_subquery(query), for_user)
+
+ {:ok, trigram_results} =
+ Repo.transaction(fn ->
+ Ecto.Adapters.SQL.query(Repo, "select set_limit(0.25)", [])
+ do_search(trigram_search_subquery(query), for_user)
+ end)
- Repo.aggregate(query, :count, :id)
+ Enum.uniq_by(fts_results ++ trigram_results, & &1.id)
end
- defp do_search(subquery, for_user, options) do
+ defp do_search(subquery, for_user, options \\ []) do
q =
from(
s in subquery(subquery),
boost_search_results(results, for_user)
end
- defp fts_search_subquery(term, query) do
+ defp fts_search_subquery(term, query \\ User) do
processed_query =
term
|> String.replace(~r/\W+/, " ")
)
end
- defp trigram_search_subquery(term, query) do
+ defp trigram_search_subquery(term) do
from(
- u in query,
+ u in User,
select_merge: %{
search_rank:
fragment(
update_and_set_cache(cng)
end
- def maybe_local_user_query(local) do
- if local, do: local_user_query(), else: User
+ def maybe_local_user_query(query, local) do
+ if local, do: local_user_query(query), else: query
end
- def local_user_query do
+ def local_user_query(query \\ User) do
from(
- u in User,
+ u in query,
where: u.local == true,
where: not is_nil(u.nickname)
)
)
|> Repo.all()
end
+
+ defp paginate(query, page, page_size) do
+ from(u in query,
+ limit: ^page_size,
+ offset: ^((page - 1) * page_size)
+ )
+ end
end
do: json_response(conn, :no_content, "")
end
- def list_users(%{assigns: %{user: admin}} = conn, %{"page" => page_string}) do
- with {page, _} <- Integer.parse(page_string),
- users <- User.all(page, @users_page_size),
- count <- User.count_all_except_one(admin),
+ def list_users(conn, params) do
+ {page, page_size} = page_params(params)
+
+ with {:ok, users, count} <- User.all_for_admin(page, page_size),
do:
conn
|> json(
AccountView.render("index.json",
users: users,
count: count,
- page_size: @users_page_size
+ page_size: page_size
)
)
end
- def search_users(%{assigns: %{user: admin}} = conn, %{"query" => term} = params) do
- users =
- User.search(term,
- query: User.maybe_local_user_query(params["local"] == "true"),
- resolve: true,
- for_user: admin,
- limit: @users_page_size
- )
+ def search_users(%{assigns: %{user: admin}} = conn, %{"query" => query} = params) do
+ {page, page_size} = page_params(params)
- conn
- |> json(
- AccountView.render("index.json",
- users: users,
- count: length(users),
- page_size: @users_page_size
- )
- )
+ with {:ok, users, count} <-
+ User.search_for_admin(query, %{
+ admin: admin,
+ local: params["local"] == "true",
+ page: page,
+ page_size: page_size
+ }),
+ do:
+ conn
+ |> json(
+ AccountView.render("index.json",
+ users: users,
+ count: count,
+ page_size: page_size
+ )
+ )
end
def right_add(conn, %{"permission_group" => permission_group, "nickname" => nickname})
|> put_status(500)
|> json("Something went wrong")
end
+
+ defp page_params(params) do
+ {get_page(params["page"]), get_page_size(params["page_size"])}
+ end
+
+ defp get_page(page_string) when is_nil(page_string), do: 1
+
+ defp get_page(page_string) do
+ case Integer.parse(page_string) do
+ {page, _} -> page
+ :error -> 1
+ end
+ end
+
+ defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
+
+ defp get_page_size(page_size_string) do
+ case Integer.parse(page_size_string) do
+ {page_size, _} -> page_size
+ :error -> @users_page_size
+ end
+ end
end
|> get("/api/pleroma/admin/users?page=1")
assert json_response(conn, 200) == %{
- "count" => 1,
+ "count" => 2,
"page_size" => 50,
"users" => [
%{
|> get("/api/pleroma/admin/users?page=2")
assert json_response(conn, 200) == %{
- "count" => 1,
+ "count" => 2,
"page_size" => 50,
"users" => []
}
}
end
- test "only local users" do
+ test "regular search with page size" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user, nickname: "bob")
+ user2 = insert(:user, nickname: "bo")
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> get("/api/pleroma/admin/users/search?query=bo&page_size=1&page=1")
+
+ assert json_response(conn, 200) == %{
+ "count" => 2,
+ "page_size" => 1,
+ "users" => [
+ %{
+ "deactivated" => user.info.deactivated,
+ "id" => user.id,
+ "nickname" => user.nickname
+ }
+ ]
+ }
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> get("/api/pleroma/admin/users/search?query=bo&page_size=1&page=2")
+
+ assert json_response(conn, 200) == %{
+ "count" => 2,
+ "page_size" => 1,
+ "users" => [
+ %{
+ "deactivated" => user2.info.deactivated,
+ "id" => user2.id,
+ "nickname" => user2.nickname
+ }
+ ]
+ }
+ end
+
+ test "only local users" do
+ admin = insert(:user, info: %{is_admin: true}, nickname: "john")
+ user = insert(:user, nickname: "bob")
insert(:user, nickname: "bobb", local: false)