tuwunel_admin/user/
force_demote.rs1use ruma::{
2 OwnedRoomOrAliasId,
3 events::{
4 StateEventType,
5 room::power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
6 },
7};
8use tuwunel_core::{
9 Err, Result,
10 matrix::{Event, pdu::PduBuilder},
11};
12
13use crate::{admin_command, utils::parse_local_user_id};
14
15#[admin_command]
16pub(super) async fn force_demote(&self, user_id: String, room_id: OwnedRoomOrAliasId) -> Result {
17 let user_id = parse_local_user_id(self.services, &user_id)?;
18 let room_id = self
19 .services
20 .alias
21 .maybe_resolve(&room_id)
22 .await?;
23
24 assert!(
25 self.services.globals.user_is_local(&user_id),
26 "Parsed user_id must be a local user"
27 );
28
29 let state_lock = self.services.state.mutex.lock(&room_id).await;
30
31 let room_power_levels: Option<RoomPowerLevels> = self
32 .services
33 .state_accessor
34 .get_power_levels(&room_id)
35 .await
36 .ok();
37
38 let user_can_change_self = room_power_levels
39 .as_ref()
40 .is_some_and(|power_levels| {
41 power_levels.user_can_change_user_power_level(&user_id, &user_id)
42 });
43
44 let user_can_demote_self = user_can_change_self
45 || self
46 .services
47 .state_accessor
48 .room_state_get(&room_id, &StateEventType::RoomCreate, "")
49 .await
50 .is_ok_and(|event| event.sender() == user_id);
51
52 if !user_can_demote_self {
53 return Err!("User is not allowed to modify their own power levels in the room.");
54 }
55
56 let mut power_levels_content: RoomPowerLevelsEventContent = room_power_levels
57 .map(TryInto::try_into)
58 .transpose()?
59 .unwrap_or_default();
60
61 power_levels_content.users.remove(&user_id);
62
63 let event_id = self
64 .services
65 .timeline
66 .build_and_append_pdu(
67 PduBuilder::state(String::new(), &power_levels_content),
68 &user_id,
69 &room_id,
70 &state_lock,
71 )
72 .await?;
73
74 write!(
75 self,
76 "User {user_id} demoted themselves to the room default power level in {room_id} - \
77 {event_id}"
78 )
79 .await
80}