de-global services from admin
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
7a3cc3941e
commit
7e50db4193
37 changed files with 1131 additions and 1127 deletions
|
@ -1,12 +1,49 @@
|
|||
use std::fmt::Write;
|
||||
|
||||
use ruma::{events::room::message::RoomMessageEventContent, RoomAliasId};
|
||||
use clap::Subcommand;
|
||||
use conduit::Result;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, RoomAliasId, RoomId};
|
||||
|
||||
use super::RoomAliasCommand;
|
||||
use crate::{escape_html, services, Result};
|
||||
use crate::{escape_html, Command};
|
||||
|
||||
pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
let server_user = &services().globals.server_user;
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(crate) enum RoomAliasCommand {
|
||||
/// - Make an alias point to a room.
|
||||
Set {
|
||||
#[arg(short, long)]
|
||||
/// Set the alias even if a room is already using it
|
||||
force: bool,
|
||||
|
||||
/// The room id to set the alias on
|
||||
room_id: Box<RoomId>,
|
||||
|
||||
/// The alias localpart to use (`alias`, not `#alias:servername.tld`)
|
||||
room_alias_localpart: String,
|
||||
},
|
||||
|
||||
/// - Remove a local alias
|
||||
Remove {
|
||||
/// The alias localpart to remove (`alias`, not `#alias:servername.tld`)
|
||||
room_alias_localpart: String,
|
||||
},
|
||||
|
||||
/// - Show which room is using an alias
|
||||
Which {
|
||||
/// The alias localpart to look up (`alias`, not
|
||||
/// `#alias:servername.tld`)
|
||||
room_alias_localpart: String,
|
||||
},
|
||||
|
||||
/// - List aliases currently being used
|
||||
List {
|
||||
/// If set, only list the aliases for this room
|
||||
room_id: Option<Box<RoomId>>,
|
||||
},
|
||||
}
|
||||
|
||||
pub(super) async fn process(command: RoomAliasCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
let server_user = &services.globals.server_user;
|
||||
|
||||
match command {
|
||||
RoomAliasCommand::Set {
|
||||
|
@ -19,7 +56,7 @@ pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
|||
| RoomAliasCommand::Which {
|
||||
ref room_alias_localpart,
|
||||
} => {
|
||||
let room_alias_str = format!("#{}:{}", room_alias_localpart, services().globals.server_name());
|
||||
let room_alias_str = format!("#{}:{}", room_alias_localpart, services.globals.server_name());
|
||||
let room_alias = match RoomAliasId::parse_box(room_alias_str) {
|
||||
Ok(alias) => alias,
|
||||
Err(err) => return Ok(RoomMessageEventContent::text_plain(format!("Failed to parse alias: {err}"))),
|
||||
|
@ -29,8 +66,8 @@ pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
|||
force,
|
||||
room_id,
|
||||
..
|
||||
} => match (force, services().rooms.alias.resolve_local_alias(&room_alias)) {
|
||||
(true, Ok(Some(id))) => match services()
|
||||
} => match (force, services.rooms.alias.resolve_local_alias(&room_alias)) {
|
||||
(true, Ok(Some(id))) => match services
|
||||
.rooms
|
||||
.alias
|
||||
.set_alias(&room_alias, &room_id, server_user)
|
||||
|
@ -43,7 +80,7 @@ pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
|||
(false, Ok(Some(id))) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||
"Refusing to overwrite in use alias for {id}, use -f or --force to overwrite"
|
||||
))),
|
||||
(_, Ok(None)) => match services()
|
||||
(_, Ok(None)) => match services
|
||||
.rooms
|
||||
.alias
|
||||
.set_alias(&room_alias, &room_id, server_user)
|
||||
|
@ -55,8 +92,8 @@ pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
|||
},
|
||||
RoomAliasCommand::Remove {
|
||||
..
|
||||
} => match services().rooms.alias.resolve_local_alias(&room_alias) {
|
||||
Ok(Some(id)) => match services()
|
||||
} => match services.rooms.alias.resolve_local_alias(&room_alias) {
|
||||
Ok(Some(id)) => match services
|
||||
.rooms
|
||||
.alias
|
||||
.remove_alias(&room_alias, server_user)
|
||||
|
@ -70,7 +107,7 @@ pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
|||
},
|
||||
RoomAliasCommand::Which {
|
||||
..
|
||||
} => match services().rooms.alias.resolve_local_alias(&room_alias) {
|
||||
} => match services.rooms.alias.resolve_local_alias(&room_alias) {
|
||||
Ok(Some(id)) => Ok(RoomMessageEventContent::text_plain(format!("Alias resolves to {id}"))),
|
||||
Ok(None) => Ok(RoomMessageEventContent::text_plain("Alias isn't in use.")),
|
||||
Err(err) => Ok(RoomMessageEventContent::text_plain(format!("Unable to lookup alias: {err}"))),
|
||||
|
@ -84,7 +121,7 @@ pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
|||
room_id,
|
||||
} => {
|
||||
if let Some(room_id) = room_id {
|
||||
let aliases = services()
|
||||
let aliases = services
|
||||
.rooms
|
||||
.alias
|
||||
.local_aliases_for_room(&room_id)
|
||||
|
@ -109,14 +146,14 @@ pub(super) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
|||
Err(err) => Ok(RoomMessageEventContent::text_plain(format!("Unable to list aliases: {err}"))),
|
||||
}
|
||||
} else {
|
||||
let aliases = services()
|
||||
let aliases = services
|
||||
.rooms
|
||||
.alias
|
||||
.all_local_aliases()
|
||||
.collect::<Result<Vec<_>, _>>();
|
||||
match aliases {
|
||||
Ok(aliases) => {
|
||||
let server_name = services().globals.server_name();
|
||||
let server_name = services.globals.server_name();
|
||||
let plain_list = aliases
|
||||
.iter()
|
||||
.fold(String::new(), |mut output, (alias, id)| {
|
|
@ -1,15 +1,18 @@
|
|||
use std::fmt::Write;
|
||||
|
||||
use conduit::Result;
|
||||
use ruma::events::room::message::RoomMessageEventContent;
|
||||
|
||||
use crate::{escape_html, get_room_info, services, Result, PAGE_SIZE};
|
||||
use crate::{admin_command, escape_html, get_room_info, PAGE_SIZE};
|
||||
|
||||
pub(super) async fn list(
|
||||
_body: Vec<&str>, page: Option<usize>, exclude_disabled: bool, exclude_banned: bool,
|
||||
#[admin_command]
|
||||
pub(super) async fn list_rooms(
|
||||
&self, page: Option<usize>, exclude_disabled: bool, exclude_banned: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
// TODO: i know there's a way to do this with clap, but i can't seem to find it
|
||||
let page = page.unwrap_or(1);
|
||||
let mut rooms = services()
|
||||
let mut rooms = self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.iter_ids()
|
||||
|
@ -18,7 +21,8 @@ pub(super) async fn list(
|
|||
.ok()
|
||||
.filter(|room_id| {
|
||||
if exclude_disabled
|
||||
&& services()
|
||||
&& self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.is_disabled(room_id)
|
||||
|
@ -28,7 +32,8 @@ pub(super) async fn list(
|
|||
}
|
||||
|
||||
if exclude_banned
|
||||
&& services()
|
||||
&& self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.is_banned(room_id)
|
||||
|
@ -39,7 +44,7 @@ pub(super) async fn list(
|
|||
|
||||
true
|
||||
})
|
||||
.map(|room_id| get_room_info(services(), &room_id))
|
||||
.map(|room_id| get_room_info(self.services, &room_id))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
rooms.sort_by_key(|r| r.1);
|
|
@ -1,21 +1,43 @@
|
|||
use std::fmt::Write;
|
||||
|
||||
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomId};
|
||||
use clap::Subcommand;
|
||||
use conduit::Result;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomId, RoomId};
|
||||
|
||||
use super::RoomDirectoryCommand;
|
||||
use crate::{escape_html, get_room_info, services, Result, PAGE_SIZE};
|
||||
use crate::{escape_html, get_room_info, Command, PAGE_SIZE};
|
||||
|
||||
pub(super) async fn process(command: RoomDirectoryCommand, _body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(crate) enum RoomDirectoryCommand {
|
||||
/// - Publish a room to the room directory
|
||||
Publish {
|
||||
/// The room id of the room to publish
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
|
||||
/// - Unpublish a room to the room directory
|
||||
Unpublish {
|
||||
/// The room id of the room to unpublish
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
|
||||
/// - List rooms that are published
|
||||
List {
|
||||
page: Option<usize>,
|
||||
},
|
||||
}
|
||||
|
||||
pub(super) async fn process(command: RoomDirectoryCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
|
||||
let services = context.services;
|
||||
match command {
|
||||
RoomDirectoryCommand::Publish {
|
||||
room_id,
|
||||
} => match services().rooms.directory.set_public(&room_id) {
|
||||
} => match services.rooms.directory.set_public(&room_id) {
|
||||
Ok(()) => Ok(RoomMessageEventContent::text_plain("Room published")),
|
||||
Err(err) => Ok(RoomMessageEventContent::text_plain(format!("Unable to update room: {err}"))),
|
||||
},
|
||||
RoomDirectoryCommand::Unpublish {
|
||||
room_id,
|
||||
} => match services().rooms.directory.set_not_public(&room_id) {
|
||||
} => match services.rooms.directory.set_not_public(&room_id) {
|
||||
Ok(()) => Ok(RoomMessageEventContent::text_plain("Room unpublished")),
|
||||
Err(err) => Ok(RoomMessageEventContent::text_plain(format!("Unable to update room: {err}"))),
|
||||
},
|
||||
|
@ -24,12 +46,12 @@ pub(super) async fn process(command: RoomDirectoryCommand, _body: Vec<&str>) ->
|
|||
} => {
|
||||
// TODO: i know there's a way to do this with clap, but i can't seem to find it
|
||||
let page = page.unwrap_or(1);
|
||||
let mut rooms = services()
|
||||
let mut rooms = services
|
||||
.rooms
|
||||
.directory
|
||||
.public_rooms()
|
||||
.filter_map(Result::ok)
|
||||
.map(|id: OwnedRoomId| get_room_info(services(), &id))
|
||||
.map(|id: OwnedRoomId| get_room_info(services, &id))
|
||||
.collect::<Vec<_>>();
|
||||
rooms.sort_by_key(|r| r.1);
|
||||
rooms.reverse();
|
|
@ -1,22 +1,30 @@
|
|||
use clap::Subcommand;
|
||||
use conduit::Result;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, RoomId};
|
||||
use service::services;
|
||||
|
||||
use super::RoomInfoCommand;
|
||||
use crate::Result;
|
||||
use crate::{admin_command, admin_command_dispatch};
|
||||
|
||||
pub(super) async fn process(command: RoomInfoCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
match command {
|
||||
RoomInfoCommand::ListJoinedMembers {
|
||||
room_id,
|
||||
} => list_joined_members(body, room_id).await,
|
||||
RoomInfoCommand::ViewRoomTopic {
|
||||
room_id,
|
||||
} => view_room_topic(body, room_id).await,
|
||||
}
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(crate) enum RoomInfoCommand {
|
||||
/// - List joined members in a room
|
||||
ListJoinedMembers {
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
|
||||
/// - Displays room topic
|
||||
///
|
||||
/// Room topics can be huge, so this is in its
|
||||
/// own separate command
|
||||
ViewRoomTopic {
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
}
|
||||
|
||||
async fn list_joined_members(_body: Vec<&str>, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
|
||||
let room_name = services()
|
||||
#[admin_command]
|
||||
async fn list_joined_members(&self, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
|
||||
let room_name = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_name(&room_id)
|
||||
|
@ -24,7 +32,8 @@ async fn list_joined_members(_body: Vec<&str>, room_id: Box<RoomId>) -> Result<R
|
|||
.flatten()
|
||||
.unwrap_or_else(|| room_id.to_string());
|
||||
|
||||
let members = services()
|
||||
let members = self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
|
@ -35,7 +44,7 @@ async fn list_joined_members(_body: Vec<&str>, room_id: Box<RoomId>) -> Result<R
|
|||
.map(|user_id| {
|
||||
(
|
||||
user_id.clone(),
|
||||
services()
|
||||
self.services
|
||||
.users
|
||||
.displayname(&user_id)
|
||||
.unwrap_or(None)
|
||||
|
@ -58,8 +67,14 @@ async fn list_joined_members(_body: Vec<&str>, room_id: Box<RoomId>) -> Result<R
|
|||
Ok(RoomMessageEventContent::notice_markdown(output_plain))
|
||||
}
|
||||
|
||||
async fn view_room_topic(_body: Vec<&str>, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
|
||||
let Some(room_topic) = services().rooms.state_accessor.get_room_topic(&room_id)? else {
|
||||
#[admin_command]
|
||||
async fn view_room_topic(&self, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
|
||||
let Some(room_topic) = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_room_topic(&room_id)?
|
||||
else {
|
||||
return Ok(RoomMessageEventContent::text_plain("Room does not have a room topic set."));
|
||||
};
|
||||
|
|
@ -1,19 +1,23 @@
|
|||
mod room_alias_commands;
|
||||
mod room_commands;
|
||||
mod room_directory_commands;
|
||||
mod room_info_commands;
|
||||
mod room_moderation_commands;
|
||||
mod alias;
|
||||
mod commands;
|
||||
mod directory;
|
||||
mod info;
|
||||
mod moderation;
|
||||
|
||||
use clap::Subcommand;
|
||||
use conduit::Result;
|
||||
use ruma::{events::room::message::RoomMessageEventContent, RoomId, RoomOrAliasId};
|
||||
|
||||
use self::room_commands::list;
|
||||
use self::{
|
||||
alias::RoomAliasCommand, directory::RoomDirectoryCommand, info::RoomInfoCommand, moderation::RoomModerationCommand,
|
||||
};
|
||||
use crate::admin_command_dispatch;
|
||||
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(super) enum RoomCommand {
|
||||
/// - List all rooms the server knows about
|
||||
List {
|
||||
#[clap(alias = "list")]
|
||||
ListRooms {
|
||||
page: Option<usize>,
|
||||
|
||||
/// Excludes rooms that we have federation disabled with
|
||||
|
@ -41,149 +45,3 @@ pub(super) enum RoomCommand {
|
|||
/// - Manage the room directory
|
||||
Directory(RoomDirectoryCommand),
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(super) enum RoomInfoCommand {
|
||||
/// - List joined members in a room
|
||||
ListJoinedMembers {
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
|
||||
/// - Displays room topic
|
||||
///
|
||||
/// Room topics can be huge, so this is in its
|
||||
/// own separate command
|
||||
ViewRoomTopic {
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(super) enum RoomAliasCommand {
|
||||
/// - Make an alias point to a room.
|
||||
Set {
|
||||
#[arg(short, long)]
|
||||
/// Set the alias even if a room is already using it
|
||||
force: bool,
|
||||
|
||||
/// The room id to set the alias on
|
||||
room_id: Box<RoomId>,
|
||||
|
||||
/// The alias localpart to use (`alias`, not `#alias:servername.tld`)
|
||||
room_alias_localpart: String,
|
||||
},
|
||||
|
||||
/// - Remove a local alias
|
||||
Remove {
|
||||
/// The alias localpart to remove (`alias`, not `#alias:servername.tld`)
|
||||
room_alias_localpart: String,
|
||||
},
|
||||
|
||||
/// - Show which room is using an alias
|
||||
Which {
|
||||
/// The alias localpart to look up (`alias`, not
|
||||
/// `#alias:servername.tld`)
|
||||
room_alias_localpart: String,
|
||||
},
|
||||
|
||||
/// - List aliases currently being used
|
||||
List {
|
||||
/// If set, only list the aliases for this room
|
||||
room_id: Option<Box<RoomId>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(super) enum RoomDirectoryCommand {
|
||||
/// - Publish a room to the room directory
|
||||
Publish {
|
||||
/// The room id of the room to publish
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
|
||||
/// - Unpublish a room to the room directory
|
||||
Unpublish {
|
||||
/// The room id of the room to unpublish
|
||||
room_id: Box<RoomId>,
|
||||
},
|
||||
|
||||
/// - List rooms that are published
|
||||
List {
|
||||
page: Option<usize>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(super) enum RoomModerationCommand {
|
||||
/// - Bans a room from local users joining and evicts all our local users
|
||||
/// from the room. Also blocks any invites (local and remote) for the
|
||||
/// banned room.
|
||||
///
|
||||
/// Server admins (users in the conduwuit admin room) will not be evicted
|
||||
/// and server admins can still join the room. To evict admins too, use
|
||||
/// --force (also ignores errors) To disable incoming federation of the
|
||||
/// room, use --disable-federation
|
||||
BanRoom {
|
||||
#[arg(short, long)]
|
||||
/// Evicts admins out of the room and ignores any potential errors when
|
||||
/// making our local users leave the room
|
||||
force: bool,
|
||||
|
||||
#[arg(long)]
|
||||
/// Disables incoming federation of the room after banning and evicting
|
||||
/// users
|
||||
disable_federation: bool,
|
||||
|
||||
/// The room in the format of `!roomid:example.com` or a room alias in
|
||||
/// the format of `#roomalias:example.com`
|
||||
room: Box<RoomOrAliasId>,
|
||||
},
|
||||
|
||||
/// - 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
|
||||
/// making our local users leave the room
|
||||
force: bool,
|
||||
|
||||
#[arg(long)]
|
||||
/// Disables incoming federation of the room after banning and evicting
|
||||
/// users
|
||||
disable_federation: bool,
|
||||
},
|
||||
|
||||
/// - Unbans a room to allow local users to join again
|
||||
///
|
||||
/// To re-enable incoming federation of the room, use --enable-federation
|
||||
UnbanRoom {
|
||||
#[arg(long)]
|
||||
/// Enables incoming federation of the room after unbanning
|
||||
enable_federation: bool,
|
||||
|
||||
/// The room in the format of `!roomid:example.com` or a room alias in
|
||||
/// the format of `#roomalias:example.com`
|
||||
room: Box<RoomOrAliasId>,
|
||||
},
|
||||
|
||||
/// - List of all rooms we have banned
|
||||
ListBannedRooms,
|
||||
}
|
||||
|
||||
pub(super) async fn process(command: RoomCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
Ok(match command {
|
||||
RoomCommand::Info(command) => room_info_commands::process(command, body).await?,
|
||||
|
||||
RoomCommand::Alias(command) => room_alias_commands::process(command, body).await?,
|
||||
|
||||
RoomCommand::Directory(command) => room_directory_commands::process(command, body).await?,
|
||||
|
||||
RoomCommand::Moderation(command) => room_moderation_commands::process(command, body).await?,
|
||||
|
||||
RoomCommand::List {
|
||||
page,
|
||||
exclude_disabled,
|
||||
exclude_banned,
|
||||
} => list(body, page, exclude_disabled, exclude_banned).await?,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,37 +1,77 @@
|
|||
use api::client::leave_room;
|
||||
use clap::Subcommand;
|
||||
use conduit::{debug, error, info, warn, Result};
|
||||
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomId, RoomAliasId, RoomId, RoomOrAliasId};
|
||||
|
||||
use super::RoomModerationCommand;
|
||||
use crate::{get_room_info, services};
|
||||
use crate::{admin_command, admin_command_dispatch, get_room_info};
|
||||
|
||||
pub(super) async fn process(command: RoomModerationCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
match command {
|
||||
RoomModerationCommand::BanRoom {
|
||||
force,
|
||||
room,
|
||||
disable_federation,
|
||||
} => ban_room(body, force, room, disable_federation).await,
|
||||
RoomModerationCommand::BanListOfRooms {
|
||||
force,
|
||||
disable_federation,
|
||||
} => ban_list_of_rooms(body, force, disable_federation).await,
|
||||
RoomModerationCommand::UnbanRoom {
|
||||
room,
|
||||
enable_federation,
|
||||
} => unban_room(body, room, enable_federation).await,
|
||||
RoomModerationCommand::ListBannedRooms => list_banned_rooms(body).await,
|
||||
}
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub(crate) enum RoomModerationCommand {
|
||||
/// - Bans a room from local users joining and evicts all our local users
|
||||
/// from the room. Also blocks any invites (local and remote) for the
|
||||
/// banned room.
|
||||
///
|
||||
/// Server admins (users in the conduwuit admin room) will not be evicted
|
||||
/// and server admins can still join the room. To evict admins too, use
|
||||
/// --force (also ignores errors) To disable incoming federation of the
|
||||
/// room, use --disable-federation
|
||||
BanRoom {
|
||||
#[arg(short, long)]
|
||||
/// Evicts admins out of the room and ignores any potential errors when
|
||||
/// making our local users leave the room
|
||||
force: bool,
|
||||
|
||||
#[arg(long)]
|
||||
/// Disables incoming federation of the room after banning and evicting
|
||||
/// users
|
||||
disable_federation: bool,
|
||||
|
||||
/// The room in the format of `!roomid:example.com` or a room alias in
|
||||
/// the format of `#roomalias:example.com`
|
||||
room: Box<RoomOrAliasId>,
|
||||
},
|
||||
|
||||
/// - 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
|
||||
/// making our local users leave the room
|
||||
force: bool,
|
||||
|
||||
#[arg(long)]
|
||||
/// Disables incoming federation of the room after banning and evicting
|
||||
/// users
|
||||
disable_federation: bool,
|
||||
},
|
||||
|
||||
/// - Unbans a room to allow local users to join again
|
||||
///
|
||||
/// To re-enable incoming federation of the room, use --enable-federation
|
||||
UnbanRoom {
|
||||
#[arg(long)]
|
||||
/// Enables incoming federation of the room after unbanning
|
||||
enable_federation: bool,
|
||||
|
||||
/// The room in the format of `!roomid:example.com` or a room alias in
|
||||
/// the format of `#roomalias:example.com`
|
||||
room: Box<RoomOrAliasId>,
|
||||
},
|
||||
|
||||
/// - List of all rooms we have banned
|
||||
ListBannedRooms,
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn ban_room(
|
||||
_body: Vec<&str>, force: bool, room: Box<RoomOrAliasId>, disable_federation: bool,
|
||||
&self, force: bool, disable_federation: bool, room: Box<RoomOrAliasId>,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
debug!("Got room alias or ID: {}", room);
|
||||
|
||||
let admin_room_alias = &services().globals.admin_alias;
|
||||
let admin_room_alias = &self.services.globals.admin_alias;
|
||||
|
||||
if let Some(admin_room_id) = services().admin.get_admin_room()? {
|
||||
if let Some(admin_room_id) = self.services.admin.get_admin_room()? {
|
||||
if room.to_string().eq(&admin_room_id) || room.to_string().eq(admin_room_alias) {
|
||||
return Ok(RoomMessageEventContent::text_plain("Not allowed to ban the admin room."));
|
||||
}
|
||||
|
@ -50,7 +90,7 @@ async fn ban_room(
|
|||
|
||||
debug!("Room specified is a room ID, banning room ID");
|
||||
|
||||
services().rooms.metadata.ban_room(&room_id, true)?;
|
||||
self.services.rooms.metadata.ban_room(&room_id, true)?;
|
||||
|
||||
room_id
|
||||
} else if room.is_room_alias_id() {
|
||||
|
@ -69,12 +109,13 @@ async fn ban_room(
|
|||
get_alias_helper to fetch room ID remotely"
|
||||
);
|
||||
|
||||
let room_id = if let Some(room_id) = services().rooms.alias.resolve_local_alias(&room_alias)? {
|
||||
let room_id = if let Some(room_id) = self.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 services()
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_alias(&room_alias, None)
|
||||
|
@ -92,7 +133,7 @@ async fn ban_room(
|
|||
}
|
||||
};
|
||||
|
||||
services().rooms.metadata.ban_room(&room_id, true)?;
|
||||
self.services.rooms.metadata.ban_room(&room_id, true)?;
|
||||
|
||||
room_id
|
||||
} else {
|
||||
|
@ -104,20 +145,21 @@ async fn ban_room(
|
|||
|
||||
debug!("Making all users leave the room {}", &room);
|
||||
if force {
|
||||
for local_user in services()
|
||||
for local_user in self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.filter_map(|user| {
|
||||
user.ok().filter(|local_user| {
|
||||
services().globals.user_is_local(local_user)
|
||||
self.services.globals.user_is_local(local_user)
|
||||
// additional wrapped check here is to avoid adding remote users
|
||||
// who are in the admin room to the list of local users (would
|
||||
// fail auth check)
|
||||
&& (services().globals.user_is_local(local_user)
|
||||
&& (self.services.globals.user_is_local(local_user)
|
||||
// since this is a force operation, assume user is an admin
|
||||
// if somehow this fails
|
||||
&& services()
|
||||
&& self.services
|
||||
.users
|
||||
.is_admin(local_user)
|
||||
.unwrap_or(true))
|
||||
|
@ -128,30 +170,31 @@ async fn ban_room(
|
|||
&local_user, &room_id
|
||||
);
|
||||
|
||||
if let Err(e) = leave_room(services(), &local_user, &room_id, None).await {
|
||||
if let Err(e) = leave_room(self.services, &local_user, &room_id, None).await {
|
||||
warn!(%e, "Failed to leave room");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for local_user in services()
|
||||
for local_user in self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.filter_map(|user| {
|
||||
user.ok().filter(|local_user| {
|
||||
local_user.server_name() == services().globals.server_name()
|
||||
local_user.server_name() == self.services.globals.server_name()
|
||||
// additional wrapped check here is to avoid adding remote users
|
||||
// who are in the admin room to the list of local users (would fail auth check)
|
||||
&& (local_user.server_name()
|
||||
== services().globals.server_name()
|
||||
&& !services()
|
||||
== self.services.globals.server_name()
|
||||
&& !self.services
|
||||
.users
|
||||
.is_admin(local_user)
|
||||
.unwrap_or(false))
|
||||
})
|
||||
}) {
|
||||
debug!("Attempting leave for user {} in room {}", &local_user, &room_id);
|
||||
if let Err(e) = leave_room(services(), &local_user, &room_id, None).await {
|
||||
if let Err(e) = leave_room(self.services, &local_user, &room_id, None).await {
|
||||
error!(
|
||||
"Error attempting to make local user {} leave room {} during room banning: {}",
|
||||
&local_user, &room_id, e
|
||||
|
@ -166,7 +209,7 @@ async fn ban_room(
|
|||
}
|
||||
|
||||
if disable_federation {
|
||||
services().rooms.metadata.disable_room(&room_id, true)?;
|
||||
self.services.rooms.metadata.disable_room(&room_id, true)?;
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Room banned, removed all our local users, and disabled incoming federation with room.",
|
||||
));
|
||||
|
@ -178,19 +221,22 @@ async fn ban_room(
|
|||
))
|
||||
}
|
||||
|
||||
async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: bool) -> Result<RoomMessageEventContent> {
|
||||
if body.len() < 2 || !body[0].trim().starts_with("```") || body.last().unwrap_or(&"").trim() != "```" {
|
||||
#[admin_command]
|
||||
async fn ban_list_of_rooms(&self, force: bool, disable_federation: bool) -> Result<RoomMessageEventContent> {
|
||||
if self.body.len() < 2 || !self.body[0].trim().starts_with("```") || self.body.last().unwrap_or(&"").trim() != "```"
|
||||
{
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"Expected code block in command body. Add --help for details.",
|
||||
));
|
||||
}
|
||||
|
||||
let rooms_s = body
|
||||
.clone()
|
||||
.drain(1..body.len().saturating_sub(1))
|
||||
let rooms_s = self
|
||||
.body
|
||||
.to_vec()
|
||||
.drain(1..self.body.len().saturating_sub(1))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let admin_room_alias = &services().globals.admin_alias;
|
||||
let admin_room_alias = &self.services.globals.admin_alias;
|
||||
|
||||
let mut room_ban_count: usize = 0;
|
||||
let mut room_ids: Vec<OwnedRoomId> = Vec::new();
|
||||
|
@ -198,7 +244,7 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
|||
for &room in &rooms_s {
|
||||
match <&RoomOrAliasId>::try_from(room) {
|
||||
Ok(room_alias_or_id) => {
|
||||
if let Some(admin_room_id) = services().admin.get_admin_room()? {
|
||||
if let Some(admin_room_id) = self.services.admin.get_admin_room()? {
|
||||
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;
|
||||
|
@ -231,7 +277,7 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
|||
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)? {
|
||||
if let Some(room_id) = self.services.rooms.alias.resolve_local_alias(&room_alias)? {
|
||||
room_id
|
||||
} else {
|
||||
debug!(
|
||||
|
@ -239,7 +285,8 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
|||
ID over federation"
|
||||
);
|
||||
|
||||
match services()
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_alias(&room_alias, None)
|
||||
|
@ -303,28 +350,35 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
|||
}
|
||||
|
||||
for room_id in room_ids {
|
||||
if services().rooms.metadata.ban_room(&room_id, true).is_ok() {
|
||||
if self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.ban_room(&room_id, true)
|
||||
.is_ok()
|
||||
{
|
||||
debug!("Banned {room_id} successfully");
|
||||
room_ban_count = room_ban_count.saturating_add(1);
|
||||
}
|
||||
|
||||
debug!("Making all users leave the room {}", &room_id);
|
||||
if force {
|
||||
for local_user in services()
|
||||
for local_user in self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.filter_map(|user| {
|
||||
user.ok().filter(|local_user| {
|
||||
local_user.server_name() == services().globals.server_name()
|
||||
local_user.server_name() == self.services.globals.server_name()
|
||||
// additional wrapped check here is to avoid adding remote
|
||||
// users who are in the admin room to the list of local
|
||||
// users (would fail auth check)
|
||||
&& (local_user.server_name()
|
||||
== services().globals.server_name()
|
||||
== self.services.globals.server_name()
|
||||
// since this is a force operation, assume user is an
|
||||
// admin if somehow this fails
|
||||
&& services()
|
||||
&& self.services
|
||||
.users
|
||||
.is_admin(local_user)
|
||||
.unwrap_or(true))
|
||||
|
@ -334,31 +388,32 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
|||
"Attempting leave for user {} in room {} (forced, ignoring all errors, evicting admins too)",
|
||||
&local_user, room_id
|
||||
);
|
||||
if let Err(e) = leave_room(services(), &local_user, &room_id, None).await {
|
||||
if let Err(e) = leave_room(self.services, &local_user, &room_id, None).await {
|
||||
warn!(%e, "Failed to leave room");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for local_user in services()
|
||||
for local_user in self
|
||||
.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.filter_map(|user| {
|
||||
user.ok().filter(|local_user| {
|
||||
local_user.server_name() == services().globals.server_name()
|
||||
local_user.server_name() == self.services.globals.server_name()
|
||||
// additional wrapped check here is to avoid adding remote
|
||||
// users who are in the admin room to the list of local
|
||||
// users (would fail auth check)
|
||||
&& (local_user.server_name()
|
||||
== services().globals.server_name()
|
||||
&& !services()
|
||||
== self.services.globals.server_name()
|
||||
&& !self.services
|
||||
.users
|
||||
.is_admin(local_user)
|
||||
.unwrap_or(false))
|
||||
})
|
||||
}) {
|
||||
debug!("Attempting leave for user {} in room {}", &local_user, &room_id);
|
||||
if let Err(e) = leave_room(services(), &local_user, &room_id, None).await {
|
||||
if let Err(e) = leave_room(self.services, &local_user, &room_id, None).await {
|
||||
error!(
|
||||
"Error attempting to make local user {} leave room {} during bulk room banning: {}",
|
||||
&local_user, &room_id, e
|
||||
|
@ -374,7 +429,7 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
|||
}
|
||||
|
||||
if disable_federation {
|
||||
services().rooms.metadata.disable_room(&room_id, true)?;
|
||||
self.services.rooms.metadata.disable_room(&room_id, true)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,9 +445,8 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
|||
}
|
||||
}
|
||||
|
||||
async fn unban_room(
|
||||
_body: Vec<&str>, room: Box<RoomOrAliasId>, enable_federation: bool,
|
||||
) -> Result<RoomMessageEventContent> {
|
||||
#[admin_command]
|
||||
async fn unban_room(&self, enable_federation: bool, room: Box<RoomOrAliasId>) -> Result<RoomMessageEventContent> {
|
||||
let room_id = if room.is_room_id() {
|
||||
let room_id = match RoomId::parse(&room) {
|
||||
Ok(room_id) => room_id,
|
||||
|
@ -406,7 +460,7 @@ async fn unban_room(
|
|||
|
||||
debug!("Room specified is a room ID, unbanning room ID");
|
||||
|
||||
services().rooms.metadata.ban_room(&room_id, false)?;
|
||||
self.services.rooms.metadata.ban_room(&room_id, false)?;
|
||||
|
||||
room_id
|
||||
} else if room.is_room_alias_id() {
|
||||
|
@ -425,12 +479,13 @@ async fn unban_room(
|
|||
get_alias_helper to fetch room ID remotely"
|
||||
);
|
||||
|
||||
let room_id = if let Some(room_id) = services().rooms.alias.resolve_local_alias(&room_alias)? {
|
||||
let room_id = if let Some(room_id) = self.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 services()
|
||||
match self
|
||||
.services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_alias(&room_alias, None)
|
||||
|
@ -448,7 +503,7 @@ async fn unban_room(
|
|||
}
|
||||
};
|
||||
|
||||
services().rooms.metadata.ban_room(&room_id, false)?;
|
||||
self.services.rooms.metadata.ban_room(&room_id, false)?;
|
||||
|
||||
room_id
|
||||
} else {
|
||||
|
@ -459,7 +514,7 @@ async fn unban_room(
|
|||
};
|
||||
|
||||
if enable_federation {
|
||||
services().rooms.metadata.disable_room(&room_id, false)?;
|
||||
self.services.rooms.metadata.disable_room(&room_id, false)?;
|
||||
return Ok(RoomMessageEventContent::text_plain("Room unbanned."));
|
||||
}
|
||||
|
||||
|
@ -469,8 +524,10 @@ async fn unban_room(
|
|||
))
|
||||
}
|
||||
|
||||
async fn list_banned_rooms(_body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
let rooms = services()
|
||||
#[admin_command]
|
||||
async fn list_banned_rooms(&self) -> Result<RoomMessageEventContent> {
|
||||
let rooms = self
|
||||
.services
|
||||
.rooms
|
||||
.metadata
|
||||
.list_banned_rooms()
|
||||
|
@ -484,7 +541,7 @@ async fn list_banned_rooms(_body: Vec<&str>) -> Result<RoomMessageEventContent>
|
|||
|
||||
let mut rooms = room_ids
|
||||
.into_iter()
|
||||
.map(|room_id| get_room_info(services(), &room_id))
|
||||
.map(|room_id| get_room_info(self.services, &room_id))
|
||||
.collect::<Vec<_>>();
|
||||
rooms.sort_by_key(|r| r.1);
|
||||
rooms.reverse();
|
Loading…
Add table
Add a link
Reference in a new issue