tuwunel_api/server/
make_leave.rs1use 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
12pub(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}