1
0
mirror of https://git.ngram.ca/OpenJam/rc-servers synced 2026-08-23 23:08:52 +00:00

Add some basic commands for sysadmins and permission system for them

This commit is contained in:
NG (Graham)
2025-10-31 21:02:10 -04:00
parent 77b6d8c11f
commit 3ef1aa20d0
13 changed files with 290 additions and 29 deletions

View File

@@ -6,3 +6,12 @@ pub use services::{services_ws, service_msg};
mod user_registry;
pub use user_registry::Users;
enum IntercomOp {
Message(oj_rc_core::persist::user::intercom::IntercomWebServiceUserMessage),
Info(IntercomInfo),
}
enum IntercomInfo {
Close,
}

View File

@@ -18,13 +18,29 @@ pub async fn services_ws(req: HttpRequest, stream: Payload, auth: Data<super::In
// start task but don't wait for it
rt::spawn(async move {
while let Some(msg) = rx.recv().await {
if let Err(e) = session.text(serde_json::to_string(&msg).unwrap()).await {
log::warn!("Failed to send services intercom to user {}: {}", name, e);
break;
let mut is_ok = false;
while let Some(op) = rx.recv().await {
match op {
super::IntercomOp::Message(msg) => {
if let Err(e) = session.text(serde_json::to_string(&msg).unwrap()).await {
log::warn!("Failed to send services intercom to user {}: {}", name, e);
break;
}
},
super::IntercomOp::Info(info) => {
match info {
super::IntercomInfo::Close => {
is_ok = true;
break;
},
}
}
}
}
if !is_ok {
reg.remove_service(name.clone()).await;
}
reg.remove_service(name.clone()).await;
rx.close();
session.close(Some(actix_ws::CloseReason {
code: actix_ws::CloseCode::Normal,

View File

@@ -1,7 +1,5 @@
use oj_rc_core::persist::user::intercom::IntercomWebServiceUserMessage;
pub struct Users {
service_listeners: tokio::sync::RwLock<std::collections::HashMap<String, tokio::sync::mpsc::Sender<IntercomWebServiceUserMessage>>>,
service_listeners: tokio::sync::RwLock<std::collections::HashMap<String, tokio::sync::mpsc::Sender<super::IntercomOp>>>,
}
impl Users {
@@ -11,11 +9,12 @@ impl Users {
}
}
pub async fn register_service(&self, public_id: String, sender: tokio::sync::mpsc::Sender<IntercomWebServiceUserMessage>) {
pub(super) async fn register_service(&self, public_id: String, sender: tokio::sync::mpsc::Sender<super::IntercomOp>) {
let mut write_lock = self.service_listeners.write().await;
if let Some(old_sender) = write_lock.insert(public_id.clone(), sender) {
if !old_sender.is_closed() {
log::warn!("Replaced web services intercom channel for user {} (why duplicate!?)", public_id);
old_sender.send(super::IntercomOp::Info(super::IntercomInfo::Close)).await.unwrap_or_default()
}
}
}
@@ -29,13 +28,22 @@ impl Users {
pub async fn broadcast_service_message(&self, msg: oj_rc_core::persist::user::intercom::IntercomWebServiceMessage) {
let read_lock = self.service_listeners.read().await;
for public_id in msg.public_ids {
if let Some(tx) = read_lock.get(&public_id) {
if let Err(e) = tx.send(msg.data.clone()).await {
if msg.everyone {
if !msg.public_ids.is_empty() { return; } // invalid
for (public_id, tx) in read_lock.iter() {
if let Err(e) = tx.send(super::IntercomOp::Message(msg.data.clone())).await {
log::error!("Failed to send web service intercom message to {}: {}", public_id, e);
}
} else {
log::warn!("Not sending web service intercom message to user {}; no listener found", public_id);
}
} else {
for public_id in msg.public_ids {
if let Some(tx) = read_lock.get(&public_id) {
if let Err(e) = tx.send(super::IntercomOp::Message(msg.data.clone())).await {
log::error!("Failed to send web service intercom message to {}: {}", public_id, e);
}
} else {
log::warn!("Not sending web service intercom message to user {}; no listener found", public_id);
}
}
}
}