Commit 5b08b470 authored by Maxim Filippov's avatar Maxim Filippov 🌚
Browse files

Add "local" params to users search

parent adac7455
...@@ -20,13 +20,14 @@ Authentication is required and the user must be an admin. ...@@ -20,13 +20,14 @@ Authentication is required and the user must be an admin.
] ]
``` ```
## `/api/pleroma/admin/users/search?query={query}` ## `/api/pleroma/admin/users/search?query={query}&local={local}`
### Search users ### Search users by name or nickname
- Method `GET` - Method `GET`
- Params: - Params:
- `query` - `query`: **string** search term
- `local`: **bool** whether to return only local users
- Response: - Response:
```JSON ```JSON
......
...@@ -755,18 +755,25 @@ def get_recipients_from_activity(%Activity{recipients: to}) do ...@@ -755,18 +755,25 @@ def get_recipients_from_activity(%Activity{recipients: to}) do
Repo.all(query) Repo.all(query)
end end
def search(query, resolve \\ false, for_user \\ nil, limit \\ 20) do def search(term, options \\ %{}) do
# Strip the beginning @ off if there is a query # Strip the beginning @ off if there is a query
query = String.trim_leading(query, "@") term = String.trim_leading(term, "@")
query = options[:query] || User
if resolve, do: get_or_fetch(query) if options[:resolve], do: get_or_fetch(term)
fts_results = do_search(fts_search_subquery(query), for_user, %{limit: limit}) fts_results =
do_search(fts_search_subquery(term, query), options[:for_user], %{
limit: options[:limit]
})
{:ok, trigram_results} = {:ok, trigram_results} =
Repo.transaction(fn -> Repo.transaction(fn ->
Ecto.Adapters.SQL.query(Repo, "select set_limit(0.25)", []) Ecto.Adapters.SQL.query(Repo, "select set_limit(0.25)", [])
do_search(trigram_search_subquery(query), for_user, %{limit: limit})
do_search(trigram_search_subquery(term, query), options[:for_user], %{
limit: options[:limit]
})
end) end)
Enum.uniq_by(fts_results ++ trigram_results, & &1.id) Enum.uniq_by(fts_results ++ trigram_results, & &1.id)
...@@ -809,9 +816,9 @@ defp do_search(subquery, for_user, options) do ...@@ -809,9 +816,9 @@ defp do_search(subquery, for_user, options) do
boost_search_results(results, for_user) boost_search_results(results, for_user)
end end
defp fts_search_subquery(query) do defp fts_search_subquery(term, query) do
processed_query = processed_query =
query term
|> String.replace(~r/\W+/, " ") |> String.replace(~r/\W+/, " ")
|> String.trim() |> String.trim()
|> String.split() |> String.split()
...@@ -819,7 +826,7 @@ defp fts_search_subquery(query) do ...@@ -819,7 +826,7 @@ defp fts_search_subquery(query) do
|> Enum.join(" | ") |> Enum.join(" | ")
from( from(
u in User, u in query,
select_merge: %{ select_merge: %{
search_rank: search_rank:
fragment( fragment(
...@@ -849,19 +856,19 @@ defp fts_search_subquery(query) do ...@@ -849,19 +856,19 @@ defp fts_search_subquery(query) do
) )
end end
defp trigram_search_subquery(query) do defp trigram_search_subquery(term, query) do
from( from(
u in User, u in query,
select_merge: %{ select_merge: %{
search_rank: search_rank:
fragment( fragment(
"similarity(?, trim(? || ' ' || coalesce(?, '')))", "similarity(?, trim(? || ' ' || coalesce(?, '')))",
^query, ^term,
u.nickname, u.nickname,
u.name u.name
) )
}, },
where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^query) where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term)
) )
end end
...@@ -1018,6 +1025,14 @@ def unblock_domain(user, domain) do ...@@ -1018,6 +1025,14 @@ def unblock_domain(user, domain) do
update_and_set_cache(cng) update_and_set_cache(cng)
end end
def maybe_local_user_query(local) when local == true do
local_user_query()
end
def maybe_local_user_query(local) when local == false do
User
end
def local_user_query do def local_user_query do
from( from(
u in User, u in User,
......
...@@ -78,8 +78,14 @@ def list_users(%{assigns: %{user: admin}} = conn, %{"page" => page_string}) do ...@@ -78,8 +78,14 @@ def list_users(%{assigns: %{user: admin}} = conn, %{"page" => page_string}) do
) )
end end
def search_users(%{assigns: %{user: admin}} = conn, %{"query" => query}) do def search_users(%{assigns: %{user: admin}} = conn, %{"query" => term} = params) do
users = User.search(query, true, admin, @users_page_size) users =
User.search(term,
query: User.maybe_local_user_query(params["local"] == "true"),
resolve: true,
for_user: admin,
limit: @users_page_size
)
conn conn
|> json( |> json(
......
...@@ -894,7 +894,7 @@ def status_search(user, query) do ...@@ -894,7 +894,7 @@ def status_search(user, query) do
end end
def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
accounts = User.search(query, params["resolve"] == "true", user) accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user)
statuses = status_search(user, query) statuses = status_search(user, query)
...@@ -919,7 +919,7 @@ def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do ...@@ -919,7 +919,7 @@ def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
end end
def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
accounts = User.search(query, params["resolve"] == "true", user) accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user)
statuses = status_search(user, query) statuses = status_search(user, query)
...@@ -941,7 +941,7 @@ def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do ...@@ -941,7 +941,7 @@ def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
end end
def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
accounts = User.search(query, params["resolve"] == "true", user) accounts = User.search(query, resolve: params["resolve"] == "true", for_user: user)
res = AccountView.render("accounts.json", users: accounts, for: user, as: :user) res = AccountView.render("accounts.json", users: accounts, for: user, as: :user)
......
...@@ -702,7 +702,7 @@ def search(%{assigns: %{user: user}} = conn, %{"q" => _query} = params) do ...@@ -702,7 +702,7 @@ def search(%{assigns: %{user: user}} = conn, %{"q" => _query} = params) do
end end
def search_user(%{assigns: %{user: user}} = conn, %{"query" => query}) do def search_user(%{assigns: %{user: user}} = conn, %{"query" => query}) do
users = User.search(query, true, user) users = User.search(query, resolve: true, for_user: user)
conn conn
|> put_view(UserView) |> put_view(UserView)
......
...@@ -388,25 +388,51 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do ...@@ -388,25 +388,51 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
} }
end end
test "GET /api/pleroma/admin/users/search" do describe "GET /api/pleroma/admin/users/search" do
admin = insert(:user, info: %{is_admin: true}) test "regular search" do
user = insert(:user, nickname: "bob") admin = insert(:user, info: %{is_admin: true})
user = insert(:user, nickname: "bob")
conn = conn =
build_conn() build_conn()
|> assign(:user, admin) |> assign(:user, admin)
|> get("/api/pleroma/admin/users/search?query=bo") |> get("/api/pleroma/admin/users/search?query=bo")
assert json_response(conn, 200) == %{ assert json_response(conn, 200) == %{
"count" => 1, "count" => 1,
"page_size" => 50, "page_size" => 50,
"users" => [ "users" => [
%{ %{
"deactivated" => user.info.deactivated, "deactivated" => user.info.deactivated,
"id" => user.id, "id" => user.id,
"nickname" => user.nickname "nickname" => user.nickname
} }
] ]
} }
end
test "only local users" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user, nickname: "bob")
insert(:user, nickname: "bobb", local: false)
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users/search?query=bo&local=true")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname
}
]
}
end
end end
end end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment