tuwunel_api/client/admin/users/
username_available.rs1use axum::extract::State;
2use ruma::UserId;
3use synapse_admin_api::username_available::v1 as username_available;
4use tuwunel_core::{Err, Result, err};
5
6use crate::{Ruma, client::admin::require_admin};
7
8pub(crate) async fn admin_username_available_route(
13 State(services): State<crate::State>,
14 body: Ruma<username_available::Request>,
15) -> Result<username_available::Response> {
16 require_admin(&services, body.sender_user()).await?;
17
18 if services
19 .config
20 .forbidden_usernames
21 .is_match(&body.username)
22 {
23 return Err!(Request(InvalidUsername("Username is forbidden")));
24 }
25
26 let user_id = UserId::parse_with_server_name(&body.username, services.globals.server_name())
27 .map_err(|_| err!(Request(InvalidUsername("Username is not a valid localpart"))))?;
28
29 if user_id.validate_strict().is_err() {
30 return Err!(Request(InvalidUsername("Username contains disallowed characters")));
31 }
32
33 if services.users.exists(&user_id).await {
34 return Err!(Request(UserInUse("Username is not available")));
35 }
36
37 if services
38 .appservice
39 .is_exclusive_user_id(&user_id)
40 .await
41 {
42 return Err!(Request(Exclusive("Username is reserved by an appservice")));
43 }
44
45 Ok(username_available::Response::new(true))
46}