Skip to main content

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