2022-02-03 13:24:04 +01:00
|
|
|
use std::sync::Arc;
|
2020-11-09 12:21:04 +01:00
|
|
|
|
2021-06-08 18:10:00 +02:00
|
|
|
use crate::{pdu::PduBuilder, Database};
|
2020-11-09 12:21:04 +01:00
|
|
|
use rocket::futures::{channel::mpsc, stream::StreamExt};
|
2020-12-04 18:16:17 -05:00
|
|
|
use ruma::{
|
2021-10-13 10:16:45 +02:00
|
|
|
events::{room::message::RoomMessageEventContent, EventType},
|
2021-11-27 00:30:28 +01:00
|
|
|
UserId,
|
2020-12-04 18:16:17 -05:00
|
|
|
};
|
2021-10-13 10:16:45 +02:00
|
|
|
use serde_json::value::to_raw_value;
|
2021-07-13 15:44:25 +02:00
|
|
|
use tokio::sync::{MutexGuard, RwLock, RwLockReadGuard};
|
2021-07-29 08:36:01 +02:00
|
|
|
use tracing::warn;
|
2020-11-09 12:21:04 +01:00
|
|
|
|
|
|
|
pub enum AdminCommand {
|
2020-12-08 10:33:44 +01:00
|
|
|
RegisterAppservice(serde_yaml::Value),
|
2021-12-20 15:46:36 +01:00
|
|
|
UnregisterAppservice(String),
|
2020-12-08 10:33:44 +01:00
|
|
|
ListAppservices,
|
2021-12-26 20:00:31 +01:00
|
|
|
ListLocalUsers,
|
2022-01-09 20:07:50 +01:00
|
|
|
ShowMemoryUsage,
|
2021-10-13 10:16:45 +02:00
|
|
|
SendMessage(RoomMessageEventContent),
|
2020-11-09 12:21:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Admin {
|
|
|
|
pub sender: mpsc::UnboundedSender<AdminCommand>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Admin {
|
|
|
|
pub fn start_handler(
|
|
|
|
&self,
|
2021-07-14 07:07:08 +00:00
|
|
|
db: Arc<RwLock<Database>>,
|
2020-11-09 12:21:04 +01:00
|
|
|
mut receiver: mpsc::UnboundedReceiver<AdminCommand>,
|
|
|
|
) {
|
|
|
|
tokio::spawn(async move {
|
|
|
|
// TODO: Use futures when we have long admin commands
|
|
|
|
//let mut futures = FuturesUnordered::new();
|
|
|
|
|
2021-07-14 07:07:08 +00:00
|
|
|
let guard = db.read().await;
|
2020-11-09 12:21:04 +01:00
|
|
|
|
2021-11-27 00:30:28 +01:00
|
|
|
let conduit_user = UserId::parse(format!("@conduit:{}", guard.globals.server_name()))
|
|
|
|
.expect("@conduit:server_name is valid");
|
2021-07-14 07:07:08 +00:00
|
|
|
|
|
|
|
let conduit_room = guard
|
2020-11-09 12:21:04 +01:00
|
|
|
.rooms
|
|
|
|
.id_from_alias(
|
2021-11-27 00:30:28 +01:00
|
|
|
format!("#admins:{}", guard.globals.server_name())
|
|
|
|
.as_str()
|
|
|
|
.try_into()
|
|
|
|
.expect("#admins:server_name is a valid room alias"),
|
2020-11-09 12:21:04 +01:00
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
2021-07-13 15:44:25 +02:00
|
|
|
let conduit_room = match conduit_room {
|
|
|
|
None => {
|
|
|
|
warn!("Conduit instance does not have an #admins room. Logging to that room will not work. Restart Conduit after creating a user to fix this.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Some(r) => r,
|
|
|
|
};
|
2020-12-02 15:49:50 +01:00
|
|
|
|
2021-07-14 07:07:08 +00:00
|
|
|
drop(guard);
|
|
|
|
|
2021-10-13 10:16:45 +02:00
|
|
|
let send_message = |message: RoomMessageEventContent,
|
2021-07-13 15:44:25 +02:00
|
|
|
guard: RwLockReadGuard<'_, Database>,
|
|
|
|
mutex_lock: &MutexGuard<'_, ()>| {
|
|
|
|
guard
|
|
|
|
.rooms
|
|
|
|
.build_and_append_pdu(
|
|
|
|
PduBuilder {
|
|
|
|
event_type: EventType::RoomMessage,
|
2021-10-13 10:16:45 +02:00
|
|
|
content: to_raw_value(&message)
|
2021-07-13 15:44:25 +02:00
|
|
|
.expect("event is valid, we just created it"),
|
|
|
|
unsigned: None,
|
|
|
|
state_key: None,
|
|
|
|
redacts: None,
|
|
|
|
},
|
|
|
|
&conduit_user,
|
|
|
|
&conduit_room,
|
|
|
|
&guard,
|
|
|
|
mutex_lock,
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
};
|
2020-12-08 10:33:44 +01:00
|
|
|
|
2020-11-09 12:21:04 +01:00
|
|
|
loop {
|
2021-03-03 22:38:31 +01:00
|
|
|
tokio::select! {
|
2020-11-09 12:21:04 +01:00
|
|
|
Some(event) = receiver.next() => {
|
2021-07-14 07:07:08 +00:00
|
|
|
let guard = db.read().await;
|
2021-08-03 11:10:58 +02:00
|
|
|
let mutex_state = Arc::clone(
|
2021-07-13 15:44:25 +02:00
|
|
|
guard.globals
|
2021-08-03 11:10:58 +02:00
|
|
|
.roomid_mutex_state
|
2021-07-13 15:44:25 +02:00
|
|
|
.write()
|
|
|
|
.unwrap()
|
|
|
|
.entry(conduit_room.clone())
|
|
|
|
.or_default(),
|
|
|
|
);
|
2021-08-03 11:10:58 +02:00
|
|
|
let state_lock = mutex_state.lock().await;
|
2021-07-14 07:07:08 +00:00
|
|
|
|
2020-11-09 12:21:04 +01:00
|
|
|
match event {
|
2021-12-26 20:00:31 +01:00
|
|
|
AdminCommand::ListLocalUsers => {
|
2022-01-16 21:22:57 +01:00
|
|
|
match guard.users.list_local_users() {
|
2022-01-15 17:10:23 +01:00
|
|
|
Ok(users) => {
|
|
|
|
let mut msg: String = format!("Found {} local user account(s):\n", users.len());
|
|
|
|
msg += &users.join("\n");
|
|
|
|
send_message(RoomMessageEventContent::text_plain(&msg), guard, &state_lock);
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
send_message(RoomMessageEventContent::text_plain(e.to_string()), guard, &state_lock);
|
|
|
|
}
|
|
|
|
}
|
2021-12-24 23:06:54 +01:00
|
|
|
}
|
2020-12-08 10:33:44 +01:00
|
|
|
AdminCommand::RegisterAppservice(yaml) => {
|
2022-01-31 10:07:49 +01:00
|
|
|
match guard.appservice.register_appservice(yaml) {
|
2022-01-31 11:52:33 +01:00
|
|
|
Ok(id) => {
|
2022-01-31 10:07:49 +01:00
|
|
|
let msg: String = format!("OK. Appservice {} created", id);
|
|
|
|
send_message(RoomMessageEventContent::text_plain(msg), guard, &state_lock);
|
|
|
|
}
|
|
|
|
Err(_) => {
|
|
|
|
send_message(RoomMessageEventContent::text_plain("ERR: Failed register appservice. Check server log"), guard, &state_lock);
|
|
|
|
}
|
|
|
|
}
|
2020-12-08 10:33:44 +01:00
|
|
|
}
|
2021-12-20 15:46:36 +01:00
|
|
|
AdminCommand::UnregisterAppservice(service_name) => {
|
2022-01-31 09:27:31 +01:00
|
|
|
if let Ok(_) = guard.appservice.unregister_appservice(&service_name) {
|
|
|
|
if let Ok(_) = guard.sending.cleanup_events(&service_name) {
|
|
|
|
let msg: String = format!("OK. Appservice {} removed", service_name);
|
|
|
|
send_message(RoomMessageEventContent::text_plain(msg), guard, &state_lock);
|
|
|
|
} else {
|
|
|
|
let msg: String = format!("WARN: Appservice {} removed, but failed to cleanup events", service_name);
|
|
|
|
send_message(RoomMessageEventContent::text_plain(msg), guard, &state_lock);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let msg: String = format!("ERR. Appservice {} not removed", service_name);
|
|
|
|
send_message(RoomMessageEventContent::text_plain(msg), guard, &state_lock);
|
|
|
|
}
|
2021-12-20 15:46:36 +01:00
|
|
|
}
|
2020-12-08 10:33:44 +01:00
|
|
|
AdminCommand::ListAppservices => {
|
2021-07-14 07:07:08 +00:00
|
|
|
if let Ok(appservices) = guard.appservice.iter_ids().map(|ids| ids.collect::<Vec<_>>()) {
|
2021-06-08 18:10:00 +02:00
|
|
|
let count = appservices.len();
|
|
|
|
let output = format!(
|
|
|
|
"Appservices ({}): {}",
|
|
|
|
count,
|
|
|
|
appservices.into_iter().filter_map(|r| r.ok()).collect::<Vec<_>>().join(", ")
|
|
|
|
);
|
2021-10-13 10:16:45 +02:00
|
|
|
send_message(RoomMessageEventContent::text_plain(output), guard, &state_lock);
|
2021-06-08 18:10:00 +02:00
|
|
|
} else {
|
2021-10-13 10:16:45 +02:00
|
|
|
send_message(RoomMessageEventContent::text_plain("Failed to get appservices."), guard, &state_lock);
|
2021-06-08 18:10:00 +02:00
|
|
|
}
|
2020-12-08 10:33:44 +01:00
|
|
|
}
|
2022-01-09 20:07:50 +01:00
|
|
|
AdminCommand::ShowMemoryUsage => {
|
|
|
|
if let Ok(response) = guard._db.memory_usage() {
|
|
|
|
send_message(RoomMessageEventContent::text_plain(response), guard, &state_lock);
|
|
|
|
} else {
|
2022-01-20 00:10:39 +01:00
|
|
|
send_message(RoomMessageEventContent::text_plain("Failed to get database memory usage.".to_owned()), guard, &state_lock);
|
2022-01-09 20:07:50 +01:00
|
|
|
}
|
|
|
|
}
|
2020-12-08 10:33:44 +01:00
|
|
|
AdminCommand::SendMessage(message) => {
|
2021-08-03 11:10:58 +02:00
|
|
|
send_message(message, guard, &state_lock);
|
2020-11-09 12:21:04 +01:00
|
|
|
}
|
|
|
|
}
|
2021-07-13 15:44:25 +02:00
|
|
|
|
2021-08-03 11:10:58 +02:00
|
|
|
drop(state_lock);
|
2020-11-09 12:21:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn send(&self, command: AdminCommand) {
|
2021-06-08 18:10:00 +02:00
|
|
|
self.sender.unbounded_send(command).unwrap();
|
2020-11-09 12:21:04 +01:00
|
|
|
}
|
|
|
|
}
|