Skip to main content

tuwunel_admin/user/
force_demote.rs

1use 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}