From 6b28bd5ae725bf063115b5393b61261bea4d8343 Mon Sep 17 00:00:00 2001 From: strawberry Date: Sat, 20 Apr 2024 17:59:54 -0400 Subject: [PATCH] refactor more of admin code, add unfinished fsck command Signed-off-by: strawberry --- src/service/admin/{ => debug}/debug.rs | 79 +------------------------ src/service/admin/debug/mod.rs | 80 ++++++++++++++++++++++++++ src/service/admin/fsck.rs | 18 ++++++ src/service/admin/mod.rs | 9 +-- src/service/admin/query/mod.rs | 52 ++++++++++++++++- src/service/admin/query/query.rs | 48 ---------------- src/service/admin/user/mod.rs | 63 ++++++++++++++++++++ src/service/admin/{ => user}/user.rs | 61 +------------------- 8 files changed, 219 insertions(+), 191 deletions(-) rename src/service/admin/{ => debug}/debug.rs (82%) create mode 100644 src/service/admin/debug/mod.rs create mode 100644 src/service/admin/fsck.rs delete mode 100644 src/service/admin/query/query.rs create mode 100644 src/service/admin/user/mod.rs rename src/service/admin/{ => user}/user.rs (86%) diff --git a/src/service/admin/debug.rs b/src/service/admin/debug/debug.rs similarity index 82% rename from src/service/admin/debug.rs rename to src/service/admin/debug/debug.rs index c27f5900..0f77b2fd 100644 --- a/src/service/admin/debug.rs +++ b/src/service/admin/debug/debug.rs @@ -1,91 +1,16 @@ use std::{collections::BTreeMap, sync::Arc, time::Instant}; -use clap::Subcommand; use ruma::{ api::client::error::ErrorKind, events::room::message::RoomMessageEventContent, CanonicalJsonObject, EventId, - RoomId, RoomVersionId, ServerName, + RoomId, RoomVersionId, }; use tokio::sync::RwLock; use tracing::{debug, error, info, warn}; use tracing_subscriber::EnvFilter; +use super::DebugCommand; use crate::{api::server_server::parse_incoming_pdu, services, utils::HtmlEscape, Error, PduEvent, Result}; -#[cfg_attr(test, derive(Debug))] -#[derive(Subcommand)] -pub(crate) enum DebugCommand { - /// - Get the auth_chain of a PDU - GetAuthChain { - /// An event ID (the $ character followed by the base64 reference hash) - event_id: Box, - }, - - /// - Parse and print a PDU from a JSON - /// - /// The PDU event is only checked for validity and is not added to the - /// database. - /// - /// This command needs a JSON blob provided in a Markdown code block below - /// the command. - ParsePdu, - - /// - Retrieve and print a PDU by ID from the conduwuit database - GetPdu { - /// An event ID (a $ followed by the base64 reference hash) - event_id: Box, - }, - - /// - Attempts to retrieve a PDU from a remote server. Inserts it into our - /// database/timeline if found and we do not have this PDU already - /// (following normal event auth rules, handles it as an incoming PDU). - GetRemotePdu { - /// An event ID (a $ followed by the base64 reference hash) - event_id: Box, - - /// Argument for us to attempt to fetch the event from the - /// specified remote server. - server: Box, - }, - - /// - Gets all the room state events for the specified room. - /// - /// This is functionally equivalent to `GET - /// /_matrix/client/v3/rooms/{roomid}/state`, except the admin command does - /// *not* check if the sender user is allowed to see state events. This is - /// done because it's implied that server admins here have database access - /// and can see/get room info themselves anyways if they were malicious - /// admins. - /// - /// Of course the check is still done on the actual client API. - GetRoomState { - /// Room ID - room_id: Box, - }, - - /// - Sends a federation request to the remote server's - /// `/_matrix/federation/v1/version` endpoint and measures the latency it - /// took for the server to respond - Ping { - server: Box, - }, - - /// - Forces device lists for all local and remote users to be updated (as - /// having new keys available) - ForceDeviceListUpdates, - - /// - Change tracing log level/filter on the fly - /// - /// This accepts the same format as the `log` config option. - ChangeLogLevel { - /// Log level/filter - filter: Option, - - /// Resets the log level/filter to the one in your config - #[arg(short, long)] - reset: bool, - }, -} - pub(crate) async fn process(command: DebugCommand, body: Vec<&str>) -> Result { Ok(match command { DebugCommand::GetAuthChain { diff --git a/src/service/admin/debug/mod.rs b/src/service/admin/debug/mod.rs new file mode 100644 index 00000000..43823175 --- /dev/null +++ b/src/service/admin/debug/mod.rs @@ -0,0 +1,80 @@ +use clap::Subcommand; +use ruma::{EventId, RoomId, ServerName}; + +#[allow(clippy::module_inception)] +pub(crate) mod debug; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +pub(crate) enum DebugCommand { + /// - Get the auth_chain of a PDU + GetAuthChain { + /// An event ID (the $ character followed by the base64 reference hash) + event_id: Box, + }, + + /// - Parse and print a PDU from a JSON + /// + /// The PDU event is only checked for validity and is not added to the + /// database. + /// + /// This command needs a JSON blob provided in a Markdown code block below + /// the command. + ParsePdu, + + /// - Retrieve and print a PDU by ID from the conduwuit database + GetPdu { + /// An event ID (a $ followed by the base64 reference hash) + event_id: Box, + }, + + /// - Attempts to retrieve a PDU from a remote server. Inserts it into our + /// database/timeline if found and we do not have this PDU already + /// (following normal event auth rules, handles it as an incoming PDU). + GetRemotePdu { + /// An event ID (a $ followed by the base64 reference hash) + event_id: Box, + + /// Argument for us to attempt to fetch the event from the + /// specified remote server. + server: Box, + }, + + /// - Gets all the room state events for the specified room. + /// + /// This is functionally equivalent to `GET + /// /_matrix/client/v3/rooms/{roomid}/state`, except the admin command does + /// *not* check if the sender user is allowed to see state events. This is + /// done because it's implied that server admins here have database access + /// and can see/get room info themselves anyways if they were malicious + /// admins. + /// + /// Of course the check is still done on the actual client API. + GetRoomState { + /// Room ID + room_id: Box, + }, + + /// - Sends a federation request to the remote server's + /// `/_matrix/federation/v1/version` endpoint and measures the latency it + /// took for the server to respond + Ping { + server: Box, + }, + + /// - Forces device lists for all local and remote users to be updated (as + /// having new keys available) + ForceDeviceListUpdates, + + /// - Change tracing log level/filter on the fly + /// + /// This accepts the same format as the `log` config option. + ChangeLogLevel { + /// Log level/filter + filter: Option, + + /// Resets the log level/filter to the one in your config + #[arg(short, long)] + reset: bool, + }, +} diff --git a/src/service/admin/fsck.rs b/src/service/admin/fsck.rs new file mode 100644 index 00000000..054976d4 --- /dev/null +++ b/src/service/admin/fsck.rs @@ -0,0 +1,18 @@ +use clap::Subcommand; +use ruma::events::room::message::RoomMessageEventContent; + +use crate::{services, Result}; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +pub(crate) enum FsckCommand { + Register, +} + +pub(crate) async fn fsck(command: FsckCommand, body: Vec<&str>) -> Result { + match command { + FsckCommand::Register => { + todo!() + }, + } +} diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 244df85f..da5a77c4 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -30,7 +30,7 @@ use super::pdu::PduBuilder; use crate::{ service::admin::{ appservice::AppserviceCommand, debug::DebugCommand, federation::FederationCommand, media::MediaCommand, - query::query::QueryCommand, room::RoomCommand, server::ServerCommand, user::UserCommand, + query::QueryCommand, room::RoomCommand, server::ServerCommand, user::UserCommand, }, services, Error, Result, }; @@ -38,6 +38,7 @@ use crate::{ pub(crate) mod appservice; pub(crate) mod debug; pub(crate) mod federation; +pub(crate) mod fsck; pub(crate) mod media; pub(crate) mod query; pub(crate) mod room; @@ -279,12 +280,12 @@ impl Service { let reply_message_content = match command { AdminCommand::Appservices(command) => appservice::process(command, body).await?, AdminCommand::Media(command) => media::process(command, body).await?, - AdminCommand::Users(command) => user::process(command, body).await?, + AdminCommand::Users(command) => user::user::process(command, body).await?, AdminCommand::Rooms(command) => room::process(command, body).await?, AdminCommand::Federation(command) => federation::process(command, body).await?, AdminCommand::Server(command) => server::process(command, body).await?, - AdminCommand::Debug(command) => debug::process(command, body).await?, - AdminCommand::Query(command) => query::query::process(command, body).await?, + AdminCommand::Debug(command) => debug::debug::process(command, body).await?, + AdminCommand::Query(command) => query::process(command, body).await?, }; Ok(reply_message_content) diff --git a/src/service/admin/query/mod.rs b/src/service/admin/query/mod.rs index 998bf756..fc10c1c9 100644 --- a/src/service/admin/query/mod.rs +++ b/src/service/admin/query/mod.rs @@ -1,8 +1,54 @@ -#[allow(clippy::module_inception)] -pub(crate) mod query; - pub(crate) mod account_data; pub(crate) mod appservice; pub(crate) mod globals; pub(crate) mod presence; pub(crate) mod room_alias; + +use clap::Subcommand; +use ruma::events::room::message::RoomMessageEventContent; + +use self::{ + account_data::{account_data, AccountData}, + appservice::{appservice, Appservice}, + globals::{globals, Globals}, + presence::{presence, Presence}, + room_alias::{room_alias, RoomAlias}, +}; +use crate::Result; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +/// Query tables from database +pub(crate) enum QueryCommand { + /// - account_data.rs iterators and getters + #[command(subcommand)] + AccountData(AccountData), + + /// - appservice.rs iterators and getters + #[command(subcommand)] + Appservice(Appservice), + + /// - presence.rs iterators and getters + #[command(subcommand)] + Presence(Presence), + + /// - rooms/alias.rs iterators and getters + #[command(subcommand)] + RoomAlias(RoomAlias), + + /// - globals.rs iterators and getters + #[command(subcommand)] + Globals(Globals), +} + +/// Processes admin query commands +#[allow(non_snake_case)] +pub(crate) async fn process(command: QueryCommand, _body: Vec<&str>) -> Result { + match command { + QueryCommand::AccountData(AccountData) => account_data(AccountData).await, + QueryCommand::Appservice(Appservice) => appservice(Appservice).await, + QueryCommand::Presence(Presence) => presence(Presence).await, + QueryCommand::RoomAlias(RoomAlias) => room_alias(RoomAlias).await, + QueryCommand::Globals(Globals) => globals(Globals).await, + } +} diff --git a/src/service/admin/query/query.rs b/src/service/admin/query/query.rs deleted file mode 100644 index 8a979aee..00000000 --- a/src/service/admin/query/query.rs +++ /dev/null @@ -1,48 +0,0 @@ -use clap::Subcommand; -use ruma::events::room::message::RoomMessageEventContent; - -use super::{ - account_data::{account_data, AccountData}, - appservice::{appservice, Appservice}, - globals::{globals, Globals}, - presence::{presence, Presence}, - room_alias::{room_alias, RoomAlias}, -}; -use crate::Result; - -#[cfg_attr(test, derive(Debug))] -#[derive(Subcommand)] -/// Query tables from database -pub(crate) enum QueryCommand { - /// - account_data.rs iterators and getters - #[command(subcommand)] - AccountData(AccountData), - - /// - appservice.rs iterators and getters - #[command(subcommand)] - Appservice(Appservice), - - /// - presence.rs iterators and getters - #[command(subcommand)] - Presence(Presence), - - /// - rooms/alias.rs iterators and getters - #[command(subcommand)] - RoomAlias(RoomAlias), - - /// - globals.rs iterators and getters - #[command(subcommand)] - Globals(Globals), -} - -/// Processes admin query commands -#[allow(non_snake_case)] -pub(crate) async fn process(command: QueryCommand, _body: Vec<&str>) -> Result { - match command { - QueryCommand::AccountData(AccountData) => account_data(AccountData).await, - QueryCommand::Appservice(Appservice) => appservice(Appservice).await, - QueryCommand::Presence(Presence) => presence(Presence).await, - QueryCommand::RoomAlias(RoomAlias) => room_alias(RoomAlias).await, - QueryCommand::Globals(Globals) => globals(Globals).await, - } -} diff --git a/src/service/admin/user/mod.rs b/src/service/admin/user/mod.rs new file mode 100644 index 00000000..7ac30043 --- /dev/null +++ b/src/service/admin/user/mod.rs @@ -0,0 +1,63 @@ +#[allow(clippy::module_inception)] +pub(crate) mod user; + +use clap::Subcommand; +use ruma::UserId; + +#[cfg_attr(test, derive(Debug))] +#[derive(Subcommand)] +pub(crate) enum UserCommand { + /// - Create a new user + Create { + /// Username of the new user + username: String, + /// Password of the new user, if unspecified one is generated + password: Option, + }, + + /// - Reset user password + ResetPassword { + /// Username of the user for whom the password should be reset + username: String, + }, + + /// - Deactivate a user + /// + /// User will not be removed from all rooms by default. + /// Use --leave-rooms to force the user to leave all rooms + Deactivate { + #[arg(short, long)] + leave_rooms: bool, + user_id: Box, + }, + + /// - Deactivate a list of users + /// + /// Recommended to use in conjunction with list-local-users. + /// + /// Users will not be removed from joined rooms by default. + /// Can be overridden with --leave-rooms flag. + /// Removing a mass amount of users from a room may cause a significant + /// amount of leave events. The time to leave rooms may depend significantly + /// on joined rooms and servers. + /// + /// This command needs a newline separated list of users provided in a + /// Markdown code block below the command. + DeactivateAll { + #[arg(short, long)] + /// Remove users from their joined rooms + leave_rooms: bool, + #[arg(short, long)] + /// Also deactivate admin accounts + force: bool, + }, + + /// - List local users in the database + List, + + /// - Lists all the rooms (local and remote) that the specified user is + /// joined in + ListJoinedRooms { + user_id: Box, + }, +} diff --git a/src/service/admin/user.rs b/src/service/admin/user/user.rs similarity index 86% rename from src/service/admin/user.rs rename to src/service/admin/user/user.rs index 11441e86..73273590 100644 --- a/src/service/admin/user.rs +++ b/src/service/admin/user/user.rs @@ -1,74 +1,17 @@ use std::{fmt::Write as _, sync::Arc}; -use clap::Subcommand; use itertools::Itertools; use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomId, UserId}; use tracing::{error, info, warn}; +use super::UserCommand; + use crate::{ api::client_server::{join_room_by_id_helper, leave_all_rooms, AUTO_GEN_PASSWORD_LENGTH}, service::admin::{escape_html, get_room_info}, services, utils, Result, }; -#[cfg_attr(test, derive(Debug))] -#[derive(Subcommand)] -pub(crate) enum UserCommand { - /// - Create a new user - Create { - /// Username of the new user - username: String, - /// Password of the new user, if unspecified one is generated - password: Option, - }, - - /// - Reset user password - ResetPassword { - /// Username of the user for whom the password should be reset - username: String, - }, - - /// - Deactivate a user - /// - /// User will not be removed from all rooms by default. - /// Use --leave-rooms to force the user to leave all rooms - Deactivate { - #[arg(short, long)] - leave_rooms: bool, - user_id: Box, - }, - - /// - Deactivate a list of users - /// - /// Recommended to use in conjunction with list-local-users. - /// - /// Users will not be removed from joined rooms by default. - /// Can be overridden with --leave-rooms flag. - /// Removing a mass amount of users from a room may cause a significant - /// amount of leave events. The time to leave rooms may depend significantly - /// on joined rooms and servers. - /// - /// This command needs a newline separated list of users provided in a - /// Markdown code block below the command. - DeactivateAll { - #[arg(short, long)] - /// Remove users from their joined rooms - leave_rooms: bool, - #[arg(short, long)] - /// Also deactivate admin accounts - force: bool, - }, - - /// - List local users in the database - List, - - /// - Lists all the rooms (local and remote) that the specified user is - /// joined in - ListJoinedRooms { - user_id: Box, - }, -} - pub(crate) async fn process(command: UserCommand, body: Vec<&str>) -> Result { match command { UserCommand::List => match services().users.list_local_users() {