refactor more of admin code, add unfinished fsck command
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
7cbe82668b
commit
6b28bd5ae7
8 changed files with 219 additions and 191 deletions
|
@ -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<EventId>,
|
||||
},
|
||||
|
||||
/// - 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<EventId>,
|
||||
},
|
||||
|
||||
/// - 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<EventId>,
|
||||
|
||||
/// Argument for us to attempt to fetch the event from the
|
||||
/// specified remote server.
|
||||
server: Box<ServerName>,
|
||||
},
|
||||
|
||||
/// - 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<RoomId>,
|
||||
},
|
||||
|
||||
/// - 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<ServerName>,
|
||||
},
|
||||
|
||||
/// - 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<String>,
|
||||
|
||||
/// 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<RoomMessageEventContent> {
|
||||
Ok(match command {
|
||||
DebugCommand::GetAuthChain {
|
80
src/service/admin/debug/mod.rs
Normal file
80
src/service/admin/debug/mod.rs
Normal file
|
@ -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<EventId>,
|
||||
},
|
||||
|
||||
/// - 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<EventId>,
|
||||
},
|
||||
|
||||
/// - 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<EventId>,
|
||||
|
||||
/// Argument for us to attempt to fetch the event from the
|
||||
/// specified remote server.
|
||||
server: Box<ServerName>,
|
||||
},
|
||||
|
||||
/// - 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<RoomId>,
|
||||
},
|
||||
|
||||
/// - 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<ServerName>,
|
||||
},
|
||||
|
||||
/// - 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<String>,
|
||||
|
||||
/// Resets the log level/filter to the one in your config
|
||||
#[arg(short, long)]
|
||||
reset: bool,
|
||||
},
|
||||
}
|
18
src/service/admin/fsck.rs
Normal file
18
src/service/admin/fsck.rs
Normal file
|
@ -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<RoomMessageEventContent> {
|
||||
match command {
|
||||
FsckCommand::Register => {
|
||||
todo!()
|
||||
},
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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<RoomMessageEventContent> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RoomMessageEventContent> {
|
||||
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,
|
||||
}
|
||||
}
|
63
src/service/admin/user/mod.rs
Normal file
63
src/service/admin/user/mod.rs
Normal file
|
@ -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<String>,
|
||||
},
|
||||
|
||||
/// - 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<UserId>,
|
||||
},
|
||||
|
||||
/// - 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<UserId>,
|
||||
},
|
||||
}
|
|
@ -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<String>,
|
||||
},
|
||||
|
||||
/// - 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<UserId>,
|
||||
},
|
||||
|
||||
/// - 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<UserId>,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) async fn process(command: UserCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||
match command {
|
||||
UserCommand::List => match services().users.list_local_users() {
|
Loading…
Add table
Reference in a new issue