From 404bdd1db57b84f5002ba2969736f681d29fcdeb Mon Sep 17 00:00:00 2001 From: strawberry <strawberry@puppygock.gay> Date: Mon, 15 Apr 2024 20:32:52 -0400 Subject: [PATCH] allow ban-list-of-rooms to take room aliases Signed-off-by: strawberry <strawberry@puppygock.gay> --- src/service/admin/room_moderation.rs | 118 +++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 18 deletions(-) diff --git a/src/service/admin/room_moderation.rs b/src/service/admin/room_moderation.rs index e450a20c5..413186ff1 100644 --- a/src/service/admin/room_moderation.rs +++ b/src/service/admin/room_moderation.rs @@ -1,7 +1,9 @@ use std::fmt::Write as _; use clap::Subcommand; -use ruma::{events::room::message::RoomMessageEventContent, OwnedUserId, RoomAliasId, RoomId, RoomOrAliasId}; +use ruma::{ + events::room::message::RoomMessageEventContent, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, RoomOrAliasId, +}; use tracing::{debug, error, info}; use crate::{ @@ -37,8 +39,8 @@ pub(crate) enum RoomModerationCommand { room: Box<RoomOrAliasId>, }, - /// - Bans a list of rooms from a newline delimited codeblock similar to - /// `user deactivate-all` + /// - Bans a list of rooms (room IDs and room aliases) from a newline + /// delimited codeblock similar to `user deactivate-all` BanListOfRooms { #[arg(short, long)] /// Evicts admins out of the room and ignores any potential errors when @@ -236,41 +238,121 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) -> if body.len() > 2 && body[0].trim().starts_with("```") && body.last().unwrap().trim() == "```" { let rooms_s = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>(); + let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name()) + .try_into() + .expect("#admins:server_name is a valid alias name"); + let mut room_ban_count = 0; - let mut room_ids: Vec<&RoomId> = Vec::new(); + let mut room_ids: Vec<OwnedRoomId> = Vec::new(); - for &room_id in &rooms_s { - match <&RoomId>::try_from(room_id) { - Ok(owned_room_id) => { - // silently ignore deleting admin room + for &room in &rooms_s { + match <&RoomOrAliasId>::try_from(room) { + Ok(room_alias_or_id) => { if let Some(admin_room_id) = Service::get_admin_room()? { - if owned_room_id.eq(&admin_room_id) { + if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(&admin_room_alias) { info!("User specified admin room in bulk ban list, ignoring"); continue; } } - room_ids.push(owned_room_id); + if room_alias_or_id.is_room_id() { + let room_id = match RoomId::parse(room_alias_or_id) { + Ok(room_id) => room_id, + Err(e) => { + if force { + // ignore rooms we failed to parse if we're force banning + error!( + "Error parsing room \"{room}\" during bulk room banning, ignoring \ + error and logging here: {e}" + ); + continue; + } + + return Ok(RoomMessageEventContent::text_plain(format!( + "{room} is not a valid room ID or room alias, please fix the list and try \ + again: {e}" + ))); + }, + }; + + room_ids.push(room_id); + } + + if room_alias_or_id.is_room_alias_id() { + match RoomAliasId::parse(room_alias_or_id) { + Ok(room_alias) => { + let room_id = if let Some(room_id) = + services().rooms.alias.resolve_local_alias(&room_alias)? + { + room_id + } else { + debug!( + "We don't have this room alias to a room ID locally, attempting to \ + fetch room ID over federation" + ); + + match get_alias_helper(room_alias).await { + Ok(response) => { + debug!( + "Got federation response fetching room ID for room {room}: \ + {:?}", + response + ); + response.room_id + }, + Err(e) => { + if force { + format!( + "Failed to resolve room alias {room} to a room ID: {e}" + ); + } + + return Ok(RoomMessageEventContent::text_plain(format!( + "Failed to resolve room alias {room} to a room ID: {e}" + ))); + }, + } + }; + + room_ids.push(room_id); + }, + Err(e) => { + if force { + // ignore rooms we failed to parse if we're force deleting + error!( + "Error parsing room \"{room}\" during bulk room banning, ignoring \ + error and logging here: {e}" + ); + continue; + } + + return Ok(RoomMessageEventContent::text_plain(format!( + "{room} is not a valid room ID or room alias, please fix the list and try \ + again: {e}" + ))); + }, + } + } }, Err(e) => { if force { // ignore rooms we failed to parse if we're force deleting error!( - "Error parsing room ID {room_id} during bulk room banning, ignoring error and \ + "Error parsing room \"{room}\" during bulk room banning, ignoring error and \ logging here: {e}" ); continue; } return Ok(RoomMessageEventContent::text_plain(format!( - "{room_id} is not a valid room ID, please fix the list and try again: {e}" + "{room} is not a valid room ID or room alias, please fix the list and try again: {e}" ))); }, } } for room_id in room_ids { - if services().rooms.metadata.ban_room(room_id, true).is_ok() { + if services().rooms.metadata.ban_room(&room_id, true).is_ok() { debug!("Banned {room_id} successfully"); room_ban_count += 1; } @@ -280,7 +362,7 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) -> for local_user in services() .rooms .state_cache - .room_members(room_id) + .room_members(&room_id) .filter_map(|user| { user.ok().filter(|local_user| { local_user.server_name() == services().globals.server_name() @@ -306,13 +388,13 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) -> admins too)", &local_user, room_id ); - _ = leave_room(&local_user, room_id, None).await; + _ = leave_room(&local_user, &room_id, None).await; } } else { for local_user in services() .rooms .state_cache - .room_members(room_id) + .room_members(&room_id) .filter_map(|user| { user.ok().filter(|local_user| { local_user.server_name() == services().globals.server_name() @@ -329,7 +411,7 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) -> .collect::<Vec<OwnedUserId>>() { debug!("Attempting leave for user {} in room {}", &local_user, &room_id); - if let Err(e) = leave_room(&local_user, room_id, None).await { + if let Err(e) = leave_room(&local_user, &room_id, None).await { error!( "Error attempting to make local user {} leave room {} during bulk room banning: {}", &local_user, &room_id, e @@ -345,7 +427,7 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) -> } if disable_federation { - services().rooms.metadata.disable_room(room_id, true)?; + services().rooms.metadata.disable_room(&room_id, true)?; } } -- GitLab