Skip to main content

arminius_server_client/handlers/
user_directory.rs

1// SPDX-FileCopyrightText: 2025 BWI GmbH
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! Implements API for user directory search from the matrix spec
6
7mod tests;
8
9use arminius_lib_component::{
10	Component, ServerState,
11	error::{InternalServerError, ResultExt as _},
12	ruma_requests::ArminiusResponse,
13};
14use arminius_lib_db::DefaultDb;
15use arminius_lib_db_user::UserQueries as _;
16use axum::{Router, extract::State, routing::post};
17use ruma::api::client::user_directory::search_users::v3::User;
18
19use crate::client_request::AuthenticatedClientRequest;
20
21/// Handler for `POST /_matrix/client/v3/user_directory/search` (See
22/// <https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3user_directorysearch>).
23///
24/// Search the user directory. Currently, this consists of all local users
25/// whose user ID or display name contains the search term.
26///
27/// Warning: No limits of user visibility or maximum result count are
28/// implemented. Unexpected matches may occur if the search query contains
29/// characters SQL interprets as wildcards.
30async fn search_users_handler(
31	mut database: State<DefaultDb>,
32	AuthenticatedClientRequest(_, request): AuthenticatedClientRequest<
33		ruma::api::client::user_directory::search_users::v3::Request,
34	>,
35) -> Result<
36	ArminiusResponse<ruma::api::client::user_directory::search_users::v3::Response>,
37	InternalServerError,
38> {
39	let user_list = database
40		.fetch_all_users_by_term(&request.search_term)
41		.await
42		.unrecoverable_error("Fetch users by term")?;
43
44	let result = user_list
45		.into_iter()
46		.map(|record| {
47			let mut user = User::new(record.user_id);
48			user.avatar_url = record
49				.avatar_id
50				.as_ref()
51				.map(|id| crate::avatar_id_to_mxc(user.user_id.server_name(), id));
52			user.display_name = record.display_name;
53			Ok::<_, InternalServerError>(user)
54		})
55		.collect::<Result<_, _>>()?;
56
57	Ok(ruma::api::client::user_directory::search_users::v3::Response::new(result, false).into())
58}
59
60/// Component implementing endpoints for account management
61#[derive(Debug)]
62pub struct UserDirectoryComponent;
63
64impl Component for UserDirectoryComponent {
65	fn router() -> Router<ServerState> {
66		Router::new().route("/_matrix/client/v3/user_directory/search", post(search_users_handler))
67	}
68}