Skip to main content

tuwunel_api/client/admin/
mod.rs

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