tuwunel_service/membership/
kick.rs1use ruma::{
2 RoomId, UserId,
3 events::room::member::{MembershipState, RoomMemberEventContent},
4};
5use tuwunel_core::{Err, Result, implement, pdu::PduBuilder};
6
7use super::Service;
8use crate::rooms::timeline::RoomMutexGuard;
9
10#[implement(Service)]
11#[tracing::instrument(
12 level = "debug",
13 skip_all,
14 fields(%sender_user, %room_id, %user_id)
15)]
16pub async fn kick(
17 &self,
18 room_id: &RoomId,
19 user_id: &UserId,
20 reason: Option<&String>,
21 sender_user: &UserId,
22 state_lock: &RoomMutexGuard,
23) -> Result {
24 let Ok(event) = self
26 .services
27 .state_accessor
28 .get_member(room_id, user_id)
29 .await
30 else {
31 return Ok(());
32 };
33
34 if !matches!(
36 event.membership,
37 MembershipState::Invite | MembershipState::Knock | MembershipState::Join,
38 ) {
39 return Err!(Request(Forbidden(
40 "Cannot kick a user who is not apart of the room (current membership: {})",
41 event.membership
42 )));
43 }
44
45 self.services
46 .timeline
47 .build_and_append_pdu(
48 PduBuilder::state(user_id.to_string(), &RoomMemberEventContent {
49 membership: MembershipState::Leave,
50 reason: reason.cloned(),
51 is_direct: None,
52 join_authorized_via_users_server: None,
53 third_party_invite: None,
54 ..event
55 }),
56 sender_user,
57 room_id,
58 state_lock,
59 )
60 .await?;
61
62 Ok(())
63}