tuwunel_api_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, 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 .registration
21 .forbidden_usernames
22 .is_match(&body.username)
23 {
24 return Err!(Request(InvalidUsername("Username is forbidden")));
25 }
26
27 let user_id = UserId::parse_with_server_name(&body.username, services.globals.server_name())
28 .map_err(|_| err!(Request(InvalidUsername("Username is not a valid localpart"))))?;
29
30 if user_id.validate_strict().is_err() {
31 return Err!(Request(InvalidUsername("Username contains disallowed characters")));
32 }
33
34 if services.users.exists(&user_id).await {
35 return Err!(Request(UserInUse("Username is not available")));
36 }
37
38 if services
39 .appservice
40 .is_exclusive_user_id(&user_id)
41 .await
42 {
43 return Err!(Request(Exclusive("Username is reserved by an appservice")));
44 }
45
46 Ok(username_available::Response::new(true))
47}