Skip to main content

tuwunel_api_admin/
mod.rs

1mod get_nonce;
2mod is_user_locked;
3mod is_user_suspended;
4mod lock_user;
5mod register;
6mod suspend_user;
7
8pub(crate) mod devices;
9pub(crate) mod federation;
10pub(crate) mod media;
11pub(crate) mod misc;
12pub(crate) mod rooms;
13/// Provides the administrator route builder.
14///
15/// It groups administrator endpoints for the configured authentication mode.
16pub mod routes;
17pub(crate) mod tokens;
18pub(crate) mod users;
19
20use futures::future::join3;
21use log as _;
22use ruma::UserId;
23pub(crate) use tuwunel_api::router::require_admin;
24use tuwunel_api::router::{ClientIp, Ruma, RumaAdmin, RumaResponse, State};
25use tuwunel_core::{Config, Err, Result};
26
27pub(crate) use self::{
28	get_nonce::admin_register_nonce_route, is_user_locked::is_user_locked_route,
29	is_user_suspended::is_user_suspended_route, lock_user::lock_user_route,
30	register::admin_register_route, suspend_user::suspend_user_route,
31};
32
33/// MSC4323: authorization is checked before account lookups
34/// (anti-enumeration) per spec.
35async fn authorize(services: &State, caller: &UserId, target: &UserId) -> Result {
36	if caller == target {
37		return Err!(Request(Forbidden("You cannot suspend or lock your own account")));
38	}
39
40	if !services.globals.user_is_local(target) {
41		return Err!(Request(InvalidParam("User is not local to this server")));
42	}
43
44	let (caller_admin, target_active, target_admin) = join3(
45		services.admin.user_is_admin(caller),
46		services.users.is_active(target),
47		services.admin.user_is_admin(target),
48	)
49	.await;
50
51	if !caller_admin {
52		return Err!(Request(Forbidden("Only server administrators can use this endpoint")));
53	}
54
55	if !target_active {
56		return Err!(Request(NotFound("Unknown user")));
57	}
58
59	if target_admin {
60		return Err!(Request(Forbidden(
61			"You cannot suspend or lock another server administrator"
62		)));
63	}
64
65	Ok(())
66}
67
68/// Refuses the server user as the target of a user endpoint.
69///
70/// Its password comes only from the `authentication.emergency_password` option,
71/// whose removal
72/// signs it out again; a password, session or status set here would outlast
73/// that.
74pub(crate) fn refuse_server_user(services: State, user_id: &UserId) -> Result {
75	if user_id == services.globals.server_user {
76		return Err!(Request(InvalidParam(
77			"The server user cannot be changed through this endpoint."
78		)));
79	}
80
81	Ok(())
82}
83
84/// True when Matrix Authentication Service delegation is active, in which case
85/// the Synapse-mirrored admin routes MAS owns (user admin, login-as,
86/// reset_password, registration tokens) are left unregistered and answer 404,
87/// mirroring Synapse's de-registration of those servlets.
88pub(crate) fn mas_active(config: &Config) -> bool {
89	config
90		.authentication
91		.mas_secret
92		.as_deref()
93		.is_some_and(|secret| !secret.is_empty())
94}
95
96tuwunel_core::mod_ctor! {}
97tuwunel_core::mod_dtor! {}