OperServ: OPER — runtime operator management

OPER ADD <account> <priv[,priv]> / DEL <account> / LIST grants or revokes
services-operator privileges (auspex, suspend, admin) at runtime, without
editing config and restarting. Runtime grants are event-sourced (Global,
so they federate and survive restart) and UNIONED with the declarative
[[oper]] config at the engine, so either source makes an account an
operator; a config oper can't be revoked here. Admin-only.

Factored the privilege-name parsing into Privs::from_names (+ names/union)
so config loading and runtime grants share one definition.
This commit is contained in:
Jean Chevronnet 2026-07-14 01:33:30 +00:00
parent e45eab2cd6
commit a67409e0d3
No known key found for this signature in database
7 changed files with 217 additions and 17 deletions

View file

@ -80,19 +80,9 @@ pub struct Oper {
impl Config {
// The account -> privileges table (casefolded keys) built from [[oper]].
pub fn opers(&self) -> std::collections::HashMap<String, fedserv_api::Privs> {
use fedserv_api::{Priv, Privs};
let mut map = std::collections::HashMap::new();
for o in &self.oper {
let mut privs = Privs::default();
for p in &o.privs {
match p.to_ascii_lowercase().as_str() {
"auspex" => privs = privs.with(Priv::Auspex),
"suspend" => privs = privs.with(Priv::Suspend),
"admin" => privs = privs.with(Priv::Admin),
other => tracing::warn!(privilege = other, account = %o.account, "unknown oper privilege, ignoring"),
}
}
map.insert(o.account.to_ascii_lowercase(), privs);
map.insert(o.account.to_ascii_lowercase(), fedserv_api::Privs::from_names(&o.privs));
}
map
}