1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-06-27 16:35:59 +00:00
conduit/src/database/admin.rs

139 lines
5.6 KiB
Rust
Raw Normal View History

2021-11-27 00:30:28 +01:00
use std::{convert::TryInto, 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};
use ruma::{
events::{room::message::RoomMessageEventContent, EventType},
2021-11-27 00:30:28 +01:00
UserId,
};
use serde_json::value::to_raw_value;
2021-07-13 15:44:25 +02:00
use tokio::sync::{MutexGuard, RwLock, RwLockReadGuard};
use tracing::warn;
2020-11-09 12:21:04 +01:00
pub enum AdminCommand {
RegisterAppservice(serde_yaml::Value),
ListAppservices,
CountLocalUsers,
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,
};
2021-07-14 07:07:08 +00:00
drop(guard);
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,
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-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 {
AdminCommand::CountLocalUsers => {
// count_local_users() only returns with OK(x) where x is the number of found accounts
if let Ok(usercount) = guard.users.count_local_users() {
let message = format!("Found {} local user account(s)", usercount);
send_message(RoomMessageEventContent::text_plain(message), guard, &state_lock);
} else {
// if count_local_users() only returns with OK(x), then why is this? ;-)
send_message(RoomMessageEventContent::text_plain("Unable to count local users"), guard, &state_lock);
}
}
AdminCommand::RegisterAppservice(yaml) => {
2021-07-14 07:07:08 +00:00
guard.appservice.register_appservice(yaml).unwrap(); // TODO handle error
}
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(", ")
);
send_message(RoomMessageEventContent::text_plain(output), guard, &state_lock);
2021-06-08 18:10:00 +02:00
} else {
send_message(RoomMessageEventContent::text_plain("Failed to get appservices."), guard, &state_lock);
2021-06-08 18:10:00 +02: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
}
}