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 crate::Ruma;
10
11pub(crate) async fn create_leave_event_template_route(
15 State(services): State<crate::State>,
16 body: Ruma<prepare_leave_event::v1::Request>,
17) -> Result<prepare_leave_event::v1::Response> {
18 if !services.metadata.exists(&body.room_id).await {
19 return Err!(Request(NotFound("Room is unknown to this server.")));
20 }
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 services
30 .event_handler
31 .acl_check(body.origin(), &body.room_id)
32 .await?;
33
34 let room_version = services
35 .state
36 .get_room_version(&body.room_id)
37 .map_ok(Some)
38 .await?;
39
40 let state_lock = services.state.mutex.lock(&body.room_id).await;
41
42 let pdu_json = services
43 .timeline
44 .create_hash_and_sign_event(
45 PduBuilder::state(
46 body.user_id.to_string(),
47 &RoomMemberEventContent::new(MembershipState::Leave),
48 ),
49 &body.user_id,
50 &body.room_id,
51 &state_lock,
52 )
53 .map_ok(at!(1))
54 .await?;
55
56 drop(state_lock);
57
58 let event = services
59 .federation
60 .format_pdu_into(pdu_json, room_version.as_ref())
61 .await;
62
63 Ok(prepare_leave_event::v1::Response { room_version, event })
64}