Skip to content
Snippets Groups Projects
Commit 7e50db41 authored by Jason Volk's avatar Jason Volk
Browse files

de-global services from admin


Signed-off-by: default avatarJason Volk <jason@zemos.net>
parent 7a3cc394
No related branches found
No related tags found
1 merge request!530de-global services
Showing
with 427 additions and 549 deletions
......@@ -3,14 +3,14 @@
use ruma::events::room::message::RoomMessageEventContent;
use crate::{
appservice, appservice::AppserviceCommand, check, check::CheckCommand, debug, debug::DebugCommand, federation,
federation::FederationCommand, media, media::MediaCommand, query, query::QueryCommand, room, room::RoomCommand,
server, server::ServerCommand, user, user::UserCommand,
appservice, appservice::AppserviceCommand, check, check::CheckCommand, command::Command, debug,
debug::DebugCommand, federation, federation::FederationCommand, media, media::MediaCommand, query,
query::QueryCommand, room, room::RoomCommand, server, server::ServerCommand, user, user::UserCommand,
};
#[derive(Debug, Parser)]
#[command(name = "admin", version = env!("CARGO_PKG_VERSION"))]
pub(crate) enum AdminCommand {
pub(super) enum AdminCommand {
#[command(subcommand)]
/// - Commands for managing appservices
Appservices(AppserviceCommand),
......@@ -49,18 +49,18 @@ pub(crate) enum AdminCommand {
}
#[tracing::instrument(skip_all, name = "command")]
pub(crate) async fn process(command: AdminCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
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::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::process(command, body).await?,
AdminCommand::Check(command) => check::process(command, body).await?,
};
pub(super) async fn process(command: AdminCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
use AdminCommand::*;
Ok(reply_message_content)
Ok(match command {
Appservices(command) => appservice::process(command, context).await?,
Media(command) => media::process(command, context).await?,
Users(command) => user::process(command, context).await?,
Rooms(command) => room::process(command, context).await?,
Federation(command) => federation::process(command, context).await?,
Server(command) => server::process(command, context).await?,
Debug(command) => debug::process(command, context).await?,
Query(command) => query::process(command, context).await?,
Check(command) => check::process(command, context).await?,
})
}
use ruma::{api::appservice::Registration, events::room::message::RoomMessageEventContent};
use crate::{services, Result};
use crate::{admin_command, Result};
pub(super) async fn register(body: Vec<&str>) -> Result<RoomMessageEventContent> {
if body.len() < 2 || !body[0].trim().starts_with("```") || body.last().unwrap_or(&"").trim() != "```" {
#[admin_command]
pub(super) async fn register(&self) -> 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 appservice_config = body[1..body.len().checked_sub(1).unwrap()].join("\n");
let appservice_config = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n");
let parsed_config = serde_yaml::from_str::<Registration>(&appservice_config);
match parsed_config {
Ok(yaml) => match services().appservice.register_appservice(yaml).await {
Ok(yaml) => match self.services.appservice.register_appservice(yaml).await {
Ok(id) => Ok(RoomMessageEventContent::text_plain(format!(
"Appservice registered with ID: {id}."
))),
......@@ -26,8 +28,10 @@ pub(super) async fn register(body: Vec<&str>) -> Result<RoomMessageEventContent>
}
}
pub(super) async fn unregister(_body: Vec<&str>, appservice_identifier: String) -> Result<RoomMessageEventContent> {
match services()
#[admin_command]
pub(super) async fn unregister(&self, appservice_identifier: String) -> Result<RoomMessageEventContent> {
match self
.services
.appservice
.unregister_appservice(&appservice_identifier)
.await
......@@ -39,8 +43,10 @@ pub(super) async fn unregister(_body: Vec<&str>, appservice_identifier: String)
}
}
pub(super) async fn show(_body: Vec<&str>, appservice_identifier: String) -> Result<RoomMessageEventContent> {
match services()
#[admin_command]
pub(super) async fn show_appservice_config(&self, appservice_identifier: String) -> Result<RoomMessageEventContent> {
match self
.services
.appservice
.get_registration(&appservice_identifier)
.await
......@@ -54,8 +60,9 @@ pub(super) async fn show(_body: Vec<&str>, appservice_identifier: String) -> Res
}
}
pub(super) async fn list(_body: Vec<&str>) -> Result<RoomMessageEventContent> {
let appservices = services().appservice.iter_ids().await;
#[admin_command]
pub(super) async fn list_registered(&self) -> Result<RoomMessageEventContent> {
let appservices = self.services.appservice.iter_ids().await;
let output = format!("Appservices ({}): {}", appservices.len(), appservices.join(", "));
Ok(RoomMessageEventContent::text_plain(output))
}
......@@ -2,11 +2,11 @@
use clap::Subcommand;
use conduit::Result;
use ruma::events::room::message::RoomMessageEventContent;
use self::commands::*;
use crate::admin_command_dispatch;
#[derive(Debug, Subcommand)]
#[admin_command_dispatch]
pub(super) enum AppserviceCommand {
/// - Register an appservice using its registration YAML
///
......@@ -28,24 +28,13 @@ pub(super) enum AppserviceCommand {
/// - Show an appservice's config using its ID
///
/// You can find the ID using the `list-appservices` command.
Show {
#[clap(alias("show"))]
ShowAppserviceConfig {
/// The appservice to show
appservice_identifier: String,
},
/// - List all the currently registered appservices
List,
}
pub(super) async fn process(command: AppserviceCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
Ok(match command {
AppserviceCommand::Register => register(body).await?,
AppserviceCommand::Unregister {
appservice_identifier,
} => unregister(body, appservice_identifier).await?,
AppserviceCommand::Show {
appservice_identifier,
} => show(body, appservice_identifier).await?,
AppserviceCommand::List => list(body).await?,
})
#[clap(alias("list"))]
ListRegistered,
}
use conduit::Result;
use conduit_macros::implement;
use ruma::events::room::message::RoomMessageEventContent;
use crate::services;
use crate::{services, Command};
/// Uses the iterator in `src/database/key_value/users.rs` to iterator over
/// every user in our database (remote and local). Reports total count, any
/// errors if there were any, etc
pub(super) async fn check_all_users(_body: Vec<&str>) -> Result<RoomMessageEventContent> {
#[implement(Command, params = "<'_>")]
pub(super) async fn check_all_users(&self) -> Result<RoomMessageEventContent> {
let timer = tokio::time::Instant::now();
let results = services().users.db.iter();
let query_time = timer.elapsed();
......
......@@ -4,15 +4,15 @@
use conduit::Result;
use ruma::events::room::message::RoomMessageEventContent;
use self::commands::*;
use crate::Command;
#[derive(Debug, Subcommand)]
pub(super) enum CheckCommand {
AllUsers,
}
pub(super) async fn process(command: CheckCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
pub(super) async fn process(command: CheckCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
Ok(match command {
CheckCommand::AllUsers => check_all_users(body).await?,
CheckCommand::AllUsers => context.check_all_users().await?,
})
}
use service::Services;
pub(crate) struct Command<'a> {
pub(crate) services: &'a Services,
pub(crate) body: &'a [&'a str],
}
This diff is collapsed.
......@@ -3,10 +3,10 @@
use clap::Subcommand;
use conduit::Result;
use conduit_macros::admin_command_dispatch;
use ruma::{events::room::message::RoomMessageEventContent, EventId, OwnedRoomOrAliasId, RoomId, ServerName};
use ruma::{EventId, OwnedRoomOrAliasId, RoomId, ServerName};
use self::{commands::*, tester::TesterCommand};
use self::tester::TesterCommand;
use crate::admin_command_dispatch;
#[admin_command_dispatch]
#[derive(Debug, Subcommand)]
......
use ruma::events::room::message::RoomMessageEventContent;
use crate::Result;
use crate::{admin_command, admin_command_dispatch, Result};
#[admin_command_dispatch]
#[derive(Debug, clap::Subcommand)]
pub(crate) enum TesterCommand {
Tester,
Timer,
}
pub(super) async fn process(command: TesterCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
match command {
TesterCommand::Tester => tester(body).await,
TesterCommand::Timer => timer(body).await,
}
}
#[inline(never)]
#[rustfmt::skip]
#[allow(unused_variables)]
async fn tester(body: Vec<&str>) -> Result<RoomMessageEventContent> {
#[admin_command]
async fn tester(&self) -> Result<RoomMessageEventContent> {
Ok(RoomMessageEventContent::notice_plain("completed"))
}
#[inline(never)]
#[rustfmt::skip]
async fn timer(body: Vec<&str>) -> Result<RoomMessageEventContent> {
#[admin_command]
async fn timer(&self) -> Result<RoomMessageEventContent> {
let started = std::time::Instant::now();
timed(&body);
timed(self.body);
let elapsed = started.elapsed();
Ok(RoomMessageEventContent::notice_plain(format!("completed in {elapsed:#?}")))
......
use std::fmt::Write;
use conduit::Result;
use ruma::{events::room::message::RoomMessageEventContent, OwnedRoomId, RoomId, ServerName, UserId};
use crate::{escape_html, get_room_info, services, Result};
use crate::{admin_command, escape_html, get_room_info};
pub(super) async fn disable_room(_body: Vec<&str>, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
services().rooms.metadata.disable_room(&room_id, true)?;
#[admin_command]
pub(super) async fn disable_room(&self, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
self.services.rooms.metadata.disable_room(&room_id, true)?;
Ok(RoomMessageEventContent::text_plain("Room disabled."))
}
pub(super) async fn enable_room(_body: Vec<&str>, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
services().rooms.metadata.disable_room(&room_id, false)?;
#[admin_command]
pub(super) async fn enable_room(&self, room_id: Box<RoomId>) -> Result<RoomMessageEventContent> {
self.services.rooms.metadata.disable_room(&room_id, false)?;
Ok(RoomMessageEventContent::text_plain("Room enabled."))
}
pub(super) async fn incoming_federation(_body: Vec<&str>) -> Result<RoomMessageEventContent> {
let map = services()
#[admin_command]
pub(super) async fn incoming_federation(&self) -> Result<RoomMessageEventContent> {
let map = self
.services
.rooms
.event_handler
.federation_handletime
......@@ -31,10 +36,10 @@ pub(super) async fn incoming_federation(_body: Vec<&str>) -> Result<RoomMessageE
Ok(RoomMessageEventContent::text_plain(&msg))
}
pub(super) async fn fetch_support_well_known(
_body: Vec<&str>, server_name: Box<ServerName>,
) -> Result<RoomMessageEventContent> {
let response = services()
#[admin_command]
pub(super) async fn fetch_support_well_known(&self, server_name: Box<ServerName>) -> Result<RoomMessageEventContent> {
let response = self
.services
.client
.default
.get(format!("https://{server_name}/.well-known/matrix/support"))
......@@ -72,25 +77,27 @@ pub(super) async fn fetch_support_well_known(
)))
}
pub(super) async fn remote_user_in_rooms(_body: Vec<&str>, user_id: Box<UserId>) -> Result<RoomMessageEventContent> {
if user_id.server_name() == services().globals.config.server_name {
#[admin_command]
pub(super) async fn remote_user_in_rooms(&self, user_id: Box<UserId>) -> Result<RoomMessageEventContent> {
if user_id.server_name() == self.services.globals.config.server_name {
return Ok(RoomMessageEventContent::text_plain(
"User belongs to our server, please use `list-joined-rooms` user admin command instead.",
));
}
if !services().users.exists(&user_id)? {
if !self.services.users.exists(&user_id)? {
return Ok(RoomMessageEventContent::text_plain(
"Remote user does not exist in our database.",
));
}
let mut rooms: Vec<(OwnedRoomId, u64, String)> = services()
let mut rooms: Vec<(OwnedRoomId, u64, String)> = self
.services
.rooms
.state_cache
.rooms_joined(&user_id)
.filter_map(Result::ok)
.map(|room_id| get_room_info(services(), &room_id))
.map(|room_id| get_room_info(self.services, &room_id))
.collect();
if rooms.is_empty() {
......
......@@ -2,10 +2,11 @@
use clap::Subcommand;
use conduit::Result;
use ruma::{events::room::message::RoomMessageEventContent, RoomId, ServerName, UserId};
use ruma::{RoomId, ServerName, UserId};
use self::commands::*;
use crate::admin_command_dispatch;
#[admin_command_dispatch]
#[derive(Debug, Subcommand)]
pub(super) enum FederationCommand {
/// - List all rooms we are currently handling an incoming pdu from
......@@ -39,21 +40,3 @@ pub(super) enum FederationCommand {
user_id: Box<UserId>,
},
}
pub(super) async fn process(command: FederationCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
Ok(match command {
FederationCommand::DisableRoom {
room_id,
} => disable_room(body, room_id).await?,
FederationCommand::EnableRoom {
room_id,
} => enable_room(body, room_id).await?,
FederationCommand::IncomingFederation => incoming_federation(body).await?,
FederationCommand::FetchSupportWellKnown {
server_name,
} => fetch_support_well_known(body, server_name).await?,
FederationCommand::RemoteUserInRooms {
user_id,
} => remote_user_in_rooms(body, user_id).await?,
})
}
......@@ -15,10 +15,10 @@
Services,
};
use crate::{admin, admin::AdminCommand};
use crate::{admin, admin::AdminCommand, Command};
struct Handler<'a> {
services: &'a Services,
struct Handler {
services: &'static Services,
}
#[must_use]
......@@ -68,13 +68,12 @@ fn reply(mut content: RoomMessageEventContent, reply_id: Option<OwnedEventId>) -
Some(content)
}
impl Handler<'_> {
impl Handler {
// Parse and process a message from the admin room
async fn process(&self, msg: &str) -> CommandOutput {
let mut lines = msg.lines().filter(|l| !l.trim().is_empty());
let command = lines.next().expect("each string has at least one line");
let body = lines.collect::<Vec<_>>();
let parsed = match self.parse_command(command) {
let (parsed, body) = match self.parse_command(command) {
Ok(parsed) => parsed,
Err(error) => {
let server_name = self.services.globals.server_name();
......@@ -84,7 +83,12 @@ async fn process(&self, msg: &str) -> CommandOutput {
};
let timer = Instant::now();
let result = Box::pin(admin::process(parsed, body)).await;
let body: Vec<&str> = body.iter().map(String::as_str).collect();
let context = Command {
services: self.services,
body: &body,
};
let result = Box::pin(admin::process(parsed, &context)).await;
let elapsed = timer.elapsed();
conduit::debug!(?command, ok = result.is_ok(), "command processed in {elapsed:?}");
match result {
......@@ -96,9 +100,10 @@ async fn process(&self, msg: &str) -> CommandOutput {
}
// Parse chat messages from the admin room into an AdminCommand object
fn parse_command(&self, command_line: &str) -> Result<AdminCommand, String> {
fn parse_command(&self, command_line: &str) -> Result<(AdminCommand, Vec<String>), String> {
let argv = self.parse_line(command_line);
AdminCommand::try_parse_from(argv).map_err(|error| error.to_string())
let com = AdminCommand::try_parse_from(&argv).map_err(|error| error.to_string())?;
Ok((com, argv))
}
fn complete_command(&self, mut cmd: clap::Command, line: &str) -> String {
......
use conduit::Result;
use conduit::{debug, info, Result};
use ruma::{events::room::message::RoomMessageEventContent, EventId, MxcUri};
use tracing::{debug, info};
use crate::services;
use crate::admin_command;
#[admin_command]
pub(super) async fn delete(
_body: Vec<&str>, mxc: Option<Box<MxcUri>>, event_id: Option<Box<EventId>>,
&self, mxc: Option<Box<MxcUri>>, event_id: Option<Box<EventId>>,
) -> Result<RoomMessageEventContent> {
if event_id.is_some() && mxc.is_some() {
return Ok(RoomMessageEventContent::text_plain(
......@@ -15,7 +15,7 @@ pub(super) async fn delete(
if let Some(mxc) = mxc {
debug!("Got MXC URL: {mxc}");
services().media.delete(mxc.as_ref()).await?;
self.services.media.delete(mxc.as_ref()).await?;
return Ok(RoomMessageEventContent::text_plain(
"Deleted the MXC from our database and on our filesystem.",
......@@ -27,7 +27,7 @@ pub(super) async fn delete(
let mut mxc_deletion_count: usize = 0;
// parsing the PDU for any MXC URLs begins here
if let Some(event_json) = services().rooms.timeline.get_pdu_json(&event_id)? {
if let Some(event_json) = self.services.rooms.timeline.get_pdu_json(&event_id)? {
if let Some(content_key) = event_json.get("content") {
debug!("Event ID has \"content\".");
let content_obj = content_key.as_object();
......@@ -123,7 +123,7 @@ pub(super) async fn delete(
}
for mxc_url in mxc_urls {
services().media.delete(&mxc_url).await?;
self.services.media.delete(&mxc_url).await?;
mxc_deletion_count = mxc_deletion_count.saturating_add(1);
}
......@@ -138,23 +138,26 @@ pub(super) async fn delete(
))
}
pub(super) async fn delete_list(body: Vec<&str>) -> Result<RoomMessageEventContent> {
if body.len() < 2 || !body[0].trim().starts_with("```") || body.last().unwrap_or(&"").trim() != "```" {
#[admin_command]
pub(super) async fn delete_list(&self) -> 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 mxc_list = body
.clone()
.drain(1..body.len().checked_sub(1).unwrap())
let mxc_list = self
.body
.to_vec()
.drain(1..self.body.len().checked_sub(1).unwrap())
.collect::<Vec<_>>();
let mut mxc_deletion_count: usize = 0;
for mxc in mxc_list {
debug!("Deleting MXC {mxc} in bulk");
services().media.delete(mxc).await?;
self.services.media.delete(mxc).await?;
mxc_deletion_count = mxc_deletion_count
.checked_add(1)
.expect("mxc_deletion_count should not get this high");
......@@ -165,10 +168,10 @@ pub(super) async fn delete_list(body: Vec<&str>) -> Result<RoomMessageEventConte
)))
}
pub(super) async fn delete_past_remote_media(
_body: Vec<&str>, duration: String, force: bool,
) -> Result<RoomMessageEventContent> {
let deleted_count = services()
#[admin_command]
pub(super) async fn delete_past_remote_media(&self, duration: String, force: bool) -> Result<RoomMessageEventContent> {
let deleted_count = self
.services
.media
.delete_all_remote_media_at_after_time(duration, force)
.await?;
......
......@@ -2,10 +2,11 @@
use clap::Subcommand;
use conduit::Result;
use ruma::{events::room::message::RoomMessageEventContent, EventId, MxcUri};
use ruma::{EventId, MxcUri};
use self::commands::*;
use crate::admin_command_dispatch;
#[admin_command_dispatch]
#[derive(Debug, Subcommand)]
pub(super) enum MediaCommand {
/// - Deletes a single media file from our database and on the filesystem
......@@ -36,17 +37,3 @@ pub(super) enum MediaCommand {
force: bool,
},
}
pub(super) async fn process(command: MediaCommand, body: Vec<&str>) -> Result<RoomMessageEventContent> {
Ok(match command {
MediaCommand::Delete {
mxc,
event_id,
} => delete(body, mxc, event_id).await?,
MediaCommand::DeleteList => delete_list(body).await?,
MediaCommand::DeletePastRemoteMedia {
duration,
force,
} => delete_past_remote_media(body, duration, force).await?,
})
}
......@@ -3,6 +3,7 @@
#![allow(clippy::enum_glob_use)]
pub(crate) mod admin;
pub(crate) mod command;
pub(crate) mod handler;
mod tests;
pub(crate) mod utils;
......@@ -22,9 +23,13 @@
extern crate conduit_service as service;
pub(crate) use conduit::Result;
pub(crate) use conduit_macros::{admin_command, admin_command_dispatch};
pub(crate) use service::services;
pub(crate) use crate::utils::{escape_html, get_room_info};
pub(crate) use crate::{
command::Command,
utils::{escape_html, get_room_info},
};
pub(crate) const PAGE_SIZE: usize = 100;
......
use ruma::events::room::message::RoomMessageEventContent;
use clap::Subcommand;
use conduit::Result;
use ruma::{
events::{room::message::RoomMessageEventContent, RoomAccountDataEventType},
RoomId, UserId,
};
use super::AccountData;
use crate::{services, Result};
use crate::Command;
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/account_data.rs
pub(super) async fn account_data(subcommand: AccountData) -> Result<RoomMessageEventContent> {
pub(crate) enum AccountDataCommand {
/// - Returns all changes to the account data that happened after `since`.
ChangesSince {
/// Full user ID
user_id: Box<UserId>,
/// UNIX timestamp since (u64)
since: u64,
/// Optional room ID of the account data
room_id: Option<Box<RoomId>>,
},
/// - Searches the account data for a specific kind.
Get {
/// Full user ID
user_id: Box<UserId>,
/// Account data event type
kind: RoomAccountDataEventType,
/// Optional room ID of the account data
room_id: Option<Box<RoomId>>,
},
}
/// All the getters and iterators from src/database/key_value/account_data.rs
pub(super) async fn process(subcommand: AccountDataCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
let services = context.services;
match subcommand {
AccountData::ChangesSince {
AccountDataCommand::ChangesSince {
user_id,
since,
room_id,
} => {
let timer = tokio::time::Instant::now();
let results = services()
let results = services
.account_data
.changes_since(room_id.as_deref(), &user_id, since)?;
let query_time = timer.elapsed();
......@@ -21,13 +51,13 @@ pub(super) async fn account_data(subcommand: AccountData) -> Result<RoomMessageE
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
)))
},
AccountData::Get {
AccountDataCommand::Get {
user_id,
kind,
room_id,
} => {
let timer = tokio::time::Instant::now();
let results = services()
let results = services
.account_data
.get(room_id.as_deref(), &user_id, kind)?;
let query_time = timer.elapsed();
......
use clap::Subcommand;
use conduit::Result;
use ruma::events::room::message::RoomMessageEventContent;
use super::Appservice;
use crate::{services, Result};
use crate::Command;
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/appservice.rs
pub(super) async fn appservice(subcommand: Appservice) -> Result<RoomMessageEventContent> {
pub(crate) enum AppserviceCommand {
/// - Gets the appservice registration info/details from the ID as a string
GetRegistration {
/// Appservice registration ID
appservice_id: Box<str>,
},
/// - Gets all appservice registrations with their ID and registration info
All,
}
/// All the getters and iterators from src/database/key_value/appservice.rs
pub(super) async fn process(subcommand: AppserviceCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
let services = context.services;
match subcommand {
Appservice::GetRegistration {
AppserviceCommand::GetRegistration {
appservice_id,
} => {
let timer = tokio::time::Instant::now();
let results = services()
let results = services
.appservice
.db
.get_registration(appservice_id.as_ref());
......@@ -20,9 +36,9 @@ pub(super) async fn appservice(subcommand: Appservice) -> Result<RoomMessageEven
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
)))
},
Appservice::All => {
AppserviceCommand::All => {
let timer = tokio::time::Instant::now();
let results = services().appservice.all();
let results = services.appservice.all();
let query_time = timer.elapsed();
Ok(RoomMessageEventContent::notice_markdown(format!(
......
use ruma::events::room::message::RoomMessageEventContent;
use clap::Subcommand;
use conduit::Result;
use ruma::{events::room::message::RoomMessageEventContent, ServerName};
use super::Globals;
use crate::{services, Result};
use crate::Command;
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/globals.rs
pub(super) async fn globals(subcommand: Globals) -> Result<RoomMessageEventContent> {
pub(crate) enum GlobalsCommand {
DatabaseVersion,
CurrentCount,
LastCheckForUpdatesId,
LoadKeypair,
/// - This returns an empty `Ok(BTreeMap<..>)` when there are no keys found
/// for the server.
SigningKeysFor {
origin: Box<ServerName>,
},
}
/// All the getters and iterators from src/database/key_value/globals.rs
pub(super) async fn process(subcommand: GlobalsCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
let services = context.services;
match subcommand {
Globals::DatabaseVersion => {
GlobalsCommand::DatabaseVersion => {
let timer = tokio::time::Instant::now();
let results = services().globals.db.database_version();
let results = services.globals.db.database_version();
let query_time = timer.elapsed();
Ok(RoomMessageEventContent::notice_markdown(format!(
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
)))
},
Globals::CurrentCount => {
GlobalsCommand::CurrentCount => {
let timer = tokio::time::Instant::now();
let results = services().globals.db.current_count();
let results = services.globals.db.current_count();
let query_time = timer.elapsed();
Ok(RoomMessageEventContent::notice_markdown(format!(
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
)))
},
Globals::LastCheckForUpdatesId => {
GlobalsCommand::LastCheckForUpdatesId => {
let timer = tokio::time::Instant::now();
let results = services().updates.last_check_for_updates_id();
let results = services.updates.last_check_for_updates_id();
let query_time = timer.elapsed();
Ok(RoomMessageEventContent::notice_markdown(format!(
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
)))
},
Globals::LoadKeypair => {
GlobalsCommand::LoadKeypair => {
let timer = tokio::time::Instant::now();
let results = services().globals.db.load_keypair();
let results = services.globals.db.load_keypair();
let query_time = timer.elapsed();
Ok(RoomMessageEventContent::notice_markdown(format!(
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
)))
},
Globals::SigningKeysFor {
GlobalsCommand::SigningKeysFor {
origin,
} => {
let timer = tokio::time::Instant::now();
let results = services().globals.db.verify_keys_for(&origin);
let results = services.globals.db.verify_keys_for(&origin);
let query_time = timer.elapsed();
Ok(RoomMessageEventContent::notice_markdown(format!(
......
......@@ -10,304 +10,51 @@
use clap::Subcommand;
use conduit::Result;
use room_state_cache::room_state_cache;
use ruma::{
events::{room::message::RoomMessageEventContent, RoomAccountDataEventType},
OwnedServerName, RoomAliasId, RoomId, ServerName, UserId,
};
use self::{
account_data::account_data, appservice::appservice, globals::globals, presence::presence, resolver::resolver,
room_alias::room_alias, sending::sending, users::users,
account_data::AccountDataCommand, appservice::AppserviceCommand, globals::GlobalsCommand,
presence::PresenceCommand, resolver::ResolverCommand, room_alias::RoomAliasCommand,
room_state_cache::RoomStateCacheCommand, sending::SendingCommand, users::UsersCommand,
};
use crate::admin_command_dispatch;
#[admin_command_dispatch]
#[derive(Debug, Subcommand)]
/// Query tables from database
pub(super) enum QueryCommand {
/// - account_data.rs iterators and getters
#[command(subcommand)]
AccountData(AccountData),
AccountData(AccountDataCommand),
/// - appservice.rs iterators and getters
#[command(subcommand)]
Appservice(Appservice),
Appservice(AppserviceCommand),
/// - presence.rs iterators and getters
#[command(subcommand)]
Presence(Presence),
Presence(PresenceCommand),
/// - rooms/alias.rs iterators and getters
#[command(subcommand)]
RoomAlias(RoomAlias),
RoomAlias(RoomAliasCommand),
/// - rooms/state_cache iterators and getters
#[command(subcommand)]
RoomStateCache(RoomStateCache),
RoomStateCache(RoomStateCacheCommand),
/// - globals.rs iterators and getters
#[command(subcommand)]
Globals(Globals),
Globals(GlobalsCommand),
/// - sending.rs iterators and getters
#[command(subcommand)]
Sending(Sending),
Sending(SendingCommand),
/// - users.rs iterators and getters
#[command(subcommand)]
Users(Users),
Users(UsersCommand),
/// - resolver service
#[command(subcommand)]
Resolver(Resolver),
}
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/account_data.rs
pub(super) enum AccountData {
/// - Returns all changes to the account data that happened after `since`.
ChangesSince {
/// Full user ID
user_id: Box<UserId>,
/// UNIX timestamp since (u64)
since: u64,
/// Optional room ID of the account data
room_id: Option<Box<RoomId>>,
},
/// - Searches the account data for a specific kind.
Get {
/// Full user ID
user_id: Box<UserId>,
/// Account data event type
kind: RoomAccountDataEventType,
/// Optional room ID of the account data
room_id: Option<Box<RoomId>>,
},
}
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/appservice.rs
pub(super) enum Appservice {
/// - Gets the appservice registration info/details from the ID as a string
GetRegistration {
/// Appservice registration ID
appservice_id: Box<str>,
},
/// - Gets all appservice registrations with their ID and registration info
All,
}
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/presence.rs
pub(super) enum Presence {
/// - Returns the latest presence event for the given user.
GetPresence {
/// Full user ID
user_id: Box<UserId>,
},
/// - Iterator of the most recent presence updates that happened after the
/// event with id `since`.
PresenceSince {
/// UNIX timestamp since (u64)
since: u64,
},
}
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/rooms/alias.rs
pub(super) enum RoomAlias {
ResolveLocalAlias {
/// Full room alias
alias: Box<RoomAliasId>,
},
/// - Iterator of all our local room aliases for the room ID
LocalAliasesForRoom {
/// Full room ID
room_id: Box<RoomId>,
},
/// - Iterator of all our local aliases in our database with their room IDs
AllLocalAliases,
}
#[derive(Debug, Subcommand)]
pub(super) enum RoomStateCache {
ServerInRoom {
server: Box<ServerName>,
room_id: Box<RoomId>,
},
RoomServers {
room_id: Box<RoomId>,
},
ServerRooms {
server: Box<ServerName>,
},
RoomMembers {
room_id: Box<RoomId>,
},
LocalUsersInRoom {
room_id: Box<RoomId>,
},
ActiveLocalUsersInRoom {
room_id: Box<RoomId>,
},
RoomJoinedCount {
room_id: Box<RoomId>,
},
RoomInvitedCount {
room_id: Box<RoomId>,
},
RoomUserOnceJoined {
room_id: Box<RoomId>,
},
RoomMembersInvited {
room_id: Box<RoomId>,
},
GetInviteCount {
room_id: Box<RoomId>,
user_id: Box<UserId>,
},
GetLeftCount {
room_id: Box<RoomId>,
user_id: Box<UserId>,
},
RoomsJoined {
user_id: Box<UserId>,
},
RoomsLeft {
user_id: Box<UserId>,
},
RoomsInvited {
user_id: Box<UserId>,
},
InviteState {
user_id: Box<UserId>,
room_id: Box<RoomId>,
},
}
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/globals.rs
pub(super) enum Globals {
DatabaseVersion,
CurrentCount,
LastCheckForUpdatesId,
LoadKeypair,
/// - This returns an empty `Ok(BTreeMap<..>)` when there are no keys found
/// for the server.
SigningKeysFor {
origin: Box<ServerName>,
},
}
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/sending.rs
pub(super) enum Sending {
/// - Queries database for all `servercurrentevent_data`
ActiveRequests,
/// - Queries database for `servercurrentevent_data` but for a specific
/// destination
///
/// This command takes only *one* format of these arguments:
///
/// appservice_id
/// server_name
/// user_id AND push_key
///
/// See src/service/sending/mod.rs for the definition of the `Destination`
/// enum
ActiveRequestsFor {
#[arg(short, long)]
appservice_id: Option<String>,
#[arg(short, long)]
server_name: Option<Box<ServerName>>,
#[arg(short, long)]
user_id: Option<Box<UserId>>,
#[arg(short, long)]
push_key: Option<String>,
},
/// - Queries database for `servernameevent_data` which are the queued up
/// requests that will eventually be sent
///
/// This command takes only *one* format of these arguments:
///
/// appservice_id
/// server_name
/// user_id AND push_key
///
/// See src/service/sending/mod.rs for the definition of the `Destination`
/// enum
QueuedRequests {
#[arg(short, long)]
appservice_id: Option<String>,
#[arg(short, long)]
server_name: Option<Box<ServerName>>,
#[arg(short, long)]
user_id: Option<Box<UserId>>,
#[arg(short, long)]
push_key: Option<String>,
},
GetLatestEduCount {
server_name: Box<ServerName>,
},
}
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/users.rs
pub(super) enum Users {
Iter,
}
#[derive(Debug, Subcommand)]
/// Resolver service and caches
pub(super) enum Resolver {
/// Query the destinations cache
DestinationsCache {
server_name: Option<OwnedServerName>,
},
/// Query the overrides cache
OverridesCache {
name: Option<String>,
},
}
/// Processes admin query commands
pub(super) async fn process(command: QueryCommand, _body: Vec<&str>) -> Result<RoomMessageEventContent> {
Ok(match command {
QueryCommand::AccountData(command) => account_data(command).await?,
QueryCommand::Appservice(command) => appservice(command).await?,
QueryCommand::Presence(command) => presence(command).await?,
QueryCommand::RoomAlias(command) => room_alias(command).await?,
QueryCommand::RoomStateCache(command) => room_state_cache(command).await?,
QueryCommand::Globals(command) => globals(command).await?,
QueryCommand::Sending(command) => sending(command).await?,
QueryCommand::Users(command) => users(command).await?,
QueryCommand::Resolver(command) => resolver(command).await?,
})
Resolver(ResolverCommand),
}
use ruma::events::room::message::RoomMessageEventContent;
use clap::Subcommand;
use conduit::Result;
use ruma::{events::room::message::RoomMessageEventContent, UserId};
use super::Presence;
use crate::{services, Result};
use crate::Command;
#[derive(Debug, Subcommand)]
/// All the getters and iterators from src/database/key_value/presence.rs
pub(crate) enum PresenceCommand {
/// - Returns the latest presence event for the given user.
GetPresence {
/// Full user ID
user_id: Box<UserId>,
},
/// - Iterator of the most recent presence updates that happened after the
/// event with id `since`.
PresenceSince {
/// UNIX timestamp since (u64)
since: u64,
},
}
/// All the getters and iterators in key_value/presence.rs
pub(super) async fn presence(subcommand: Presence) -> Result<RoomMessageEventContent> {
pub(super) async fn process(subcommand: PresenceCommand, context: &Command<'_>) -> Result<RoomMessageEventContent> {
let services = context.services;
match subcommand {
Presence::GetPresence {
PresenceCommand::GetPresence {
user_id,
} => {
let timer = tokio::time::Instant::now();
let results = services().presence.db.get_presence(&user_id)?;
let results = services.presence.db.get_presence(&user_id)?;
let query_time = timer.elapsed();
Ok(RoomMessageEventContent::notice_markdown(format!(
"Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```"
)))
},
Presence::PresenceSince {
PresenceCommand::PresenceSince {
since,
} => {
let timer = tokio::time::Instant::now();
let results = services().presence.db.presence_since(since);
let results = services.presence.db.presence_since(since);
let presence_since: Vec<(_, _, _)> = results.collect();
let query_time = timer.elapsed();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment