Skip to main content

tuwunel_api/client/admin/users/
login_as.rs

1use std::time::{Duration, SystemTime};
2
3use axum::extract::State;
4use ruma::MilliSecondsSinceUnixEpoch;
5use synapse_admin_api::users::login_as::v1::{Request, Response};
6use tuwunel_core::{Err, Result};
7
8use crate::{
9	Ruma,
10	client::admin::{refuse_server_user, require_admin},
11};
12
13/// # `POST /_synapse/admin/v1/users/{user_id}/login`
14///
15/// Mints a token through a visible device on the target account. The target's
16/// logout revokes it, and an optional expiry is enforced during authentication.
17/// This route is unavailable while Matrix Authentication Service is active.
18pub(crate) async fn admin_login_as_route(
19	State(services): State<crate::State>,
20	body: Ruma<Request>,
21) -> Result<Response> {
22	require_admin(&services, body.sender_user()).await?;
23
24	if !services.globals.user_is_local(&body.user_id) {
25		return Err!(Request(InvalidParam("Only local users can be logged in as")));
26	}
27
28	refuse_server_user(services, &body.user_id)?;
29
30	if body.sender_user() == body.user_id {
31		return Err!(Request(InvalidParam("Cannot use admin API to login as self")));
32	}
33
34	if !services.users.exists(&body.user_id).await {
35		return Err!(Request(NotFound("User not found")));
36	}
37
38	let expires_in = body
39		.valid_until_ms
40		.and_then(MilliSecondsSinceUnixEpoch::to_system_time)
41		.map(|valid_until| {
42			valid_until
43				.duration_since(SystemTime::now())
44				.unwrap_or(Duration::ZERO)
45		});
46
47	let (access_token, _) = services.users.generate_access_token(false);
48
49	services
50		.users
51		.create_device(
52			&body.user_id,
53			None,
54			(Some(&access_token), expires_in),
55			None,
56			Some("Admin login"),
57			None,
58		)
59		.await?;
60
61	Ok(Response::new(access_token))
62}