Force promotion (closes #136)
This commit is contained in:
@@ -2,11 +2,11 @@ use std::{collections::BTreeMap, fmt::Write as _};
|
|||||||
|
|
||||||
use futures::{FutureExt, StreamExt};
|
use futures::{FutureExt, StreamExt};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedUserId, UserId,
|
Int, OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedUserId, UserId,
|
||||||
events::{
|
events::{
|
||||||
RoomAccountDataEventType, StateEventType,
|
RoomAccountDataEventType, StateEventType,
|
||||||
room::{
|
room::{
|
||||||
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
|
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent, UserPowerLevel},
|
||||||
redaction::RoomRedactionEventContent,
|
redaction::RoomRedactionEventContent,
|
||||||
},
|
},
|
||||||
tag::{TagEvent, TagEventContent, TagInfo},
|
tag::{TagEvent, TagEventContent, TagInfo},
|
||||||
@@ -22,7 +22,7 @@ use tuwunel_service::Services;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
admin_command, get_room_info,
|
admin_command, get_room_info,
|
||||||
utils::{parse_active_local_user_id, parse_local_user_id},
|
utils::{parse_active_local_user_id, parse_local_user_id, parse_user_id},
|
||||||
};
|
};
|
||||||
|
|
||||||
const AUTO_GEN_PASSWORD_LENGTH: usize = 25;
|
const AUTO_GEN_PASSWORD_LENGTH: usize = 25;
|
||||||
@@ -737,6 +737,85 @@ pub(super) async fn force_demote(&self, user_id: String, room_id: OwnedRoomOrAli
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[admin_command]
|
||||||
|
pub(super) async fn force_promote(
|
||||||
|
&self,
|
||||||
|
target_id: String,
|
||||||
|
room_id: OwnedRoomOrAliasId,
|
||||||
|
) -> Result {
|
||||||
|
let target_id = parse_user_id(self.services, &target_id)?;
|
||||||
|
let room_id = self.services.alias.resolve(&room_id).await?;
|
||||||
|
|
||||||
|
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||||
|
|
||||||
|
let room_power_levels = self
|
||||||
|
.services
|
||||||
|
.state_accessor
|
||||||
|
.get_power_levels(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let privileged_member = self
|
||||||
|
.services
|
||||||
|
.state_cache
|
||||||
|
.room_members(&room_id)
|
||||||
|
.ready_filter(|member_id| {
|
||||||
|
self.services.globals.user_is_local(member_id)
|
||||||
|
&& room_power_levels.user_can_change_user_power_level(member_id, &target_id)
|
||||||
|
})
|
||||||
|
.map(ToOwned::to_owned)
|
||||||
|
.ready_fold_default(|selected_user, member_id| match selected_user {
|
||||||
|
| None => Some(member_id),
|
||||||
|
| Some(selected_user) => Some(
|
||||||
|
if room_power_levels.for_user(&selected_user)
|
||||||
|
> room_power_levels.for_user(&member_id)
|
||||||
|
{
|
||||||
|
selected_user
|
||||||
|
} else {
|
||||||
|
member_id
|
||||||
|
},
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let Some(privileged_member) = privileged_member else {
|
||||||
|
return Err!("No privileged user exists in room, cannot promote.");
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("Selected privileged member {privileged_member}");
|
||||||
|
|
||||||
|
let power_level: Int = match room_power_levels.for_user(&privileged_member) {
|
||||||
|
| UserPowerLevel::Infinite => Int::MAX,
|
||||||
|
| UserPowerLevel::Int(x) => x,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut power_levels_content: RoomPowerLevelsEventContent = room_power_levels.try_into()?;
|
||||||
|
|
||||||
|
power_levels_content
|
||||||
|
.users
|
||||||
|
.insert(target_id.clone(), power_level);
|
||||||
|
|
||||||
|
let event_id = self
|
||||||
|
.services
|
||||||
|
.timeline
|
||||||
|
.build_and_append_pdu(
|
||||||
|
PduBuilder::state(String::new(), &power_levels_content),
|
||||||
|
&privileged_member,
|
||||||
|
&room_id,
|
||||||
|
&state_lock,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
drop(state_lock);
|
||||||
|
|
||||||
|
self.write_str(&format!(
|
||||||
|
"User {privileged_member} promoted {target_id} to {power_level} power level in \
|
||||||
|
{room_id} - {event_id}"
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn make_user_admin(&self, user_id: String) -> Result {
|
pub(super) async fn make_user_admin(&self, user_id: String) -> Result {
|
||||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||||
|
|||||||
@@ -88,6 +88,12 @@ pub(super) enum UserCommand {
|
|||||||
room_id: OwnedRoomOrAliasId,
|
room_id: OwnedRoomOrAliasId,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// - Force promote
|
||||||
|
ForcePromote {
|
||||||
|
user_id: String,
|
||||||
|
room_id: OwnedRoomOrAliasId,
|
||||||
|
},
|
||||||
|
|
||||||
/// - Grant server-admin privileges to a user.
|
/// - Grant server-admin privileges to a user.
|
||||||
MakeUserAdmin {
|
MakeUserAdmin {
|
||||||
user_id: String,
|
user_id: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user