Skip to main content

tuwunel_api/client/admin/rooms/
join.rs

1use axum::extract::State;
2use synapse_admin_api::room_membership::join_room::v1::{Request, Response};
3use tuwunel_core::{Err, Result};
4use tuwunel_service::membership::Join;
5
6use crate::{Ruma, client::admin::require_admin};
7
8/// # `POST /_synapse/admin/v1/join/{room_id_or_alias}`
9///
10/// Joins a local user to a room on an admin's behalf, resolving an alias and
11/// using the supplied servers as remote-join candidates. When the join rule
12/// admits no one uninvited, the admin invites the user first, so the admin
13/// must be joined there with power to invite.
14pub(crate) async fn admin_join_room_route(
15	State(services): State<crate::State>,
16	body: Ruma<Request>,
17) -> Result<Response> {
18	let sender_user = body.sender_user();
19
20	require_admin(&services, sender_user).await?;
21
22	let user_id = &body.user_id;
23
24	if !services.globals.user_is_local(user_id) {
25		return Err!(Request(InvalidParam("User must be local to this server")));
26	}
27
28	if !services.users.exists(user_id).await {
29		return Err!(Request(NotFound("Unknown user")));
30	}
31
32	let (room_id, servers) = services
33		.alias
34		.maybe_resolve_with_servers(&body.room_id_or_alias, Some(body.server_name.as_slice()))
35		.await?;
36
37	if services
38		.membership
39		.join_needs_invite(&room_id, user_id)
40		.await
41	{
42		services
43			.membership
44			.invite(sender_user, user_id, &room_id, None, false)
45			.await?;
46	}
47
48	services
49		.membership
50		.join(Join {
51			sender_user: user_id,
52			room_id: &room_id,
53			orig_room_id: Some(&body.room_id_or_alias),
54			reason: None,
55			servers: &servers,
56			is_appservice: false,
57			extra_content: None,
58		})
59		.await?;
60
61	Ok(Response { room_id })
62}