tuwunel_api_federation/
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};
8use tuwunel_matrix::pdu::PduBuilder;
9
10use super::utils::require_known_room;
11use crate::Ruma;
12
13pub(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}