tuwunel_admin/user/
force_promote.rs1use futures::StreamExt;
2use ruma::{
3 Int, OwnedRoomOrAliasId,
4 events::room::power_levels::{RoomPowerLevelsEventContent, UserPowerLevel},
5};
6use tuwunel_core::{Err, Result, info, matrix::pdu::PduBuilder, utils::ReadyExt};
7
8use crate::{admin_command, utils::parse_user_id};
9
10#[admin_command]
11pub(super) async fn force_promote(
12 &self,
13 target_id: String,
14 room_id: OwnedRoomOrAliasId,
15) -> Result {
16 let target_id = parse_user_id(self.services, &target_id)?;
17 let room_id = self
18 .services
19 .alias
20 .maybe_resolve(&room_id)
21 .await?;
22
23 let state_lock = self.services.state.mutex.lock(&room_id).await;
24
25 let room_power_levels = self
26 .services
27 .state_accessor
28 .get_power_levels(&room_id)
29 .await?;
30
31 let privileged_member = self
32 .services
33 .state_cache
34 .room_members(&room_id)
35 .ready_filter(|member_id| {
36 self.services.globals.user_is_local(member_id)
37 && room_power_levels.user_can_change_user_power_level(member_id, &target_id)
38 })
39 .map(ToOwned::to_owned)
40 .ready_fold_default(|selected_user, member_id| match selected_user {
41 | None => Some(member_id),
42 | Some(selected_user) => Some(
43 if room_power_levels.for_user(&selected_user)
44 > room_power_levels.for_user(&member_id)
45 {
46 selected_user
47 } else {
48 member_id
49 },
50 ),
51 })
52 .await;
53
54 let Some(privileged_member) = privileged_member else {
55 return Err!("No privileged user exists in room, cannot promote.");
56 };
57
58 info!("Selected privileged member {privileged_member}");
59
60 let power_level: Int = match room_power_levels.for_user(&privileged_member) {
61 | UserPowerLevel::Infinite => Int::MAX,
62 | UserPowerLevel::Int(x) => x,
63 };
64
65 let mut power_levels_content: RoomPowerLevelsEventContent = room_power_levels.try_into()?;
66
67 power_levels_content
68 .users
69 .insert(target_id.clone(), power_level);
70
71 let event_id = self
72 .services
73 .timeline
74 .build_and_append_pdu(
75 PduBuilder::state(String::new(), &power_levels_content),
76 &privileged_member,
77 &room_id,
78 &state_lock,
79 )
80 .await?;
81
82 drop(state_lock);
83
84 write!(
85 self,
86 "User {privileged_member} promoted {target_id} to {power_level} power level in \
87 {room_id} - {event_id}"
88 )
89 .await?;
90
91 Ok(())
92}