operlevels: oper = <name> <pass> <level>; a lower-level oper can't KILL a higher-level one
This commit is contained in:
parent
3b2f30965a
commit
3b43abc88a
7 changed files with 64 additions and 8 deletions
|
|
@ -48,6 +48,7 @@ pub mod metadata;
|
|||
pub mod multiline;
|
||||
pub mod network_icon;
|
||||
pub mod ojoin;
|
||||
pub mod operlevels;
|
||||
pub mod operprefix;
|
||||
pub mod password_hash;
|
||||
pub mod profilelink;
|
||||
|
|
|
|||
46
src/modules/operlevels.rs
Normal file
46
src/modules/operlevels.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//! operlevels — each `oper` block may carry a numeric level (`oper = <name> <pass>
|
||||
//! <level>`, default 0). A lower-level oper cannot KILL a higher-level oper. The
|
||||
//! level is stored on the user at OPER; with all levels at the default it's inert,
|
||||
//! so no config flag is needed.
|
||||
|
||||
use crate::server::Server;
|
||||
use crate::Uid;
|
||||
|
||||
/// The oper level stored on a user's `ext`.
|
||||
struct OperLevel(u32);
|
||||
|
||||
/// Record `uid`'s oper level (called from the OPER handler after oper-up).
|
||||
pub fn set(s: &mut Server, uid: Uid, level: u32) {
|
||||
if let Some(u) = s.users.get_mut(&uid) {
|
||||
*u.ext.get_or_insert_with(|| OperLevel(0)) = OperLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
/// A user's oper level (0 if unset / not an oper).
|
||||
pub fn level(s: &Server, uid: Uid) -> u32 {
|
||||
s.users
|
||||
.get(&uid)
|
||||
.and_then(|u| u.ext.get::<OperLevel>())
|
||||
.map(|l| l.0)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// The reason `actor` may not KILL `target` under operlevels, if any: only when the
|
||||
/// target is an oper of a strictly higher level than the actor.
|
||||
pub fn deny_kill(s: &Server, actor: Uid, target: Uid) -> Option<String> {
|
||||
if !s.is_oper(target) {
|
||||
return None; // non-opers aren't protected
|
||||
}
|
||||
if level(s, actor) < level(s, target) {
|
||||
let tnick = s
|
||||
.users
|
||||
.get(&target)
|
||||
.map(|u| u.nick.clone())
|
||||
.unwrap_or_default();
|
||||
Some(format!(
|
||||
"Permission Denied- {tnick} outranks you (higher oper level)"
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ pub fn handle(s: &mut Server, method: &str, _params: &str) -> Result<String, Rpc
|
|||
let opers: Vec<String> = s
|
||||
.opers
|
||||
.iter()
|
||||
.map(|(name, _pass)| {
|
||||
.map(|(name, _pass, _lvl)| {
|
||||
obj(&[
|
||||
("name", qstr(name)),
|
||||
("type", qstr("")),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue