Skip to main content

tuwunel_api/server/
make_leave.rs

1use axum::extract::State;
2use futures::TryFutureExt;
3use ruma::{
4	api::federation::membership::prepare_leave_event,
5	events::room::member::{MembershipState, RoomMemberEventContent},
6};
7use tuwunel_core::{Err, Result, at, matrix::pdu::PduBuilder};
8
9use super::utils::require_known_room;
10use crate::Ruma;
11
12/// # `GET /_matrix/federation/v1/make_leave/{roomId}/{eventId}`
13///
14/// Creates a leave template.
15pub(crate) async fn create_leave_event_template_route(
16	State(services): State<crate::State>,
17	body: Ruma<prepare_leave_event::v1::Request>,
18) -> Result<prepare_leave_event::v1::Response> {
19	require_known_room(&services, &body.room_id, body.origin()).await?;
20
21	if body.user_id.server_name() != body.origin() {
22		return Err!(Request(Forbidden(
23			"Not allowed to leave on behalf of another server/user."
24		)));
25	}
26
27	let room_version = services
28		.state
29		.get_room_version(&body.room_id)
30		.map_ok(Some)
31		.await?;
32
33	let state_lock = services.state.mutex.lock(&body.room_id).await;
34
35	let pdu_json = services
36		.timeline
37		.create_hash_and_sign_event(
38			PduBuilder::state(
39				body.user_id.to_string(),
40				&RoomMemberEventContent::new(MembershipState::Leave),
41			),
42			&body.user_id,
43			&body.room_id,
44			&state_lock,
45		)
46		.map_ok(at!(1))
47		.await?;
48
49	drop(state_lock);
50
51	let event = services
52		.federation
53		.format_pdu_into(pdu_json, room_version.as_ref())
54		.await;
55
56	Ok(prepare_leave_event::v1::Response { room_version, event })
57}