modules: move all per-module state/config out of server.rs/config.rs into own files
This commit is contained in:
parent
0d4c9297b5
commit
131471e245
18 changed files with 525 additions and 425 deletions
|
|
@ -6,11 +6,80 @@
|
|||
|
||||
use crate::channels::glob_match;
|
||||
use crate::command::{CmdResult, Command};
|
||||
use crate::config::{SecGroup, Tri};
|
||||
use crate::numeric::ERR_NOSUCHNICK;
|
||||
use crate::server::Server;
|
||||
use crate::Uid;
|
||||
|
||||
/// Tri-state for a criterion: don't-care / must-be / must-not-be.
|
||||
#[derive(Clone, Copy, PartialEq, Default)]
|
||||
enum Tri {
|
||||
#[default]
|
||||
Ignore,
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
/// A UnrealIRCd-style security group — all criteria AND-ed.
|
||||
#[derive(Clone, Default)]
|
||||
struct SecGroup {
|
||||
name: String,
|
||||
public: bool,
|
||||
masks: Vec<String>,
|
||||
exclude_masks: Vec<String>,
|
||||
tls: Tri,
|
||||
account: Tri,
|
||||
oper: Tri,
|
||||
bot: Tri,
|
||||
webirc: Tri,
|
||||
score_min: Option<u32>,
|
||||
score_max: Option<u32>,
|
||||
}
|
||||
|
||||
/// Parse the `securitygroup = <name> [criteria…]` config lines into groups.
|
||||
fn parse_groups(s: &Server) -> Vec<SecGroup> {
|
||||
let mut out = Vec::new();
|
||||
for line in s
|
||||
.conf_all("securitygroup")
|
||||
.iter()
|
||||
.chain(s.conf_all("secgroup"))
|
||||
{
|
||||
let mut it = line.split_whitespace();
|
||||
let Some(name) = it.next() else { continue };
|
||||
let mut g = SecGroup {
|
||||
name: name.to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
for tok in it {
|
||||
let (k, val) = match tok.split_once('=') {
|
||||
Some((a, b)) => (a, Some(b)),
|
||||
None => (tok, None),
|
||||
};
|
||||
match (k, val) {
|
||||
("public", _) => g.public = true,
|
||||
("mask", Some(m)) => g.masks.push(m.to_string()),
|
||||
("exclude", Some(m)) | ("exclude-mask", Some(m)) => {
|
||||
g.exclude_masks.push(m.to_string())
|
||||
}
|
||||
("tls", _) | ("tls-users", _) => g.tls = Tri::Yes,
|
||||
("insecure", _) | ("exclude-tls", _) => g.tls = Tri::No,
|
||||
("account", _) | ("registered", _) => g.account = Tri::Yes,
|
||||
("unregistered", _) | ("exclude-account", _) => g.account = Tri::No,
|
||||
("oper", _) => g.oper = Tri::Yes,
|
||||
("exclude-oper", _) => g.oper = Tri::No,
|
||||
("bot", _) | ("bmode", _) => g.bot = Tri::Yes,
|
||||
("exclude-bot", _) | ("exclude-bmode", _) => g.bot = Tri::No,
|
||||
("webirc", _) => g.webirc = Tri::Yes,
|
||||
("exclude-webirc", _) => g.webirc = Tri::No,
|
||||
("scoremin", Some(n)) => g.score_min = n.parse().ok(),
|
||||
("scoremax", Some(n)) => g.score_max = n.parse().ok(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
out.push(g);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Does `uid`'s identity match `mask` (glob against nick!user@{display,real,ip})?
|
||||
fn mask_matches(s: &Server, uid: Uid, mask: &str) -> bool {
|
||||
let Some(u) = s.users.get(&uid) else {
|
||||
|
|
@ -64,17 +133,17 @@ fn matches(s: &Server, uid: Uid, g: &SecGroup) -> bool {
|
|||
|
||||
/// Whether `uid` is a member of the named security group (case-insensitive).
|
||||
pub fn in_group(s: &Server, uid: Uid, name: &str) -> bool {
|
||||
s.sec_groups
|
||||
parse_groups(s)
|
||||
.iter()
|
||||
.any(|g| g.name.eq_ignore_ascii_case(name) && matches(s, uid, g))
|
||||
}
|
||||
|
||||
/// The names of the groups `uid` is in (only public ones unless `include_private`).
|
||||
pub fn user_groups(s: &Server, uid: Uid, include_private: bool) -> Vec<String> {
|
||||
s.sec_groups
|
||||
.iter()
|
||||
parse_groups(s)
|
||||
.into_iter()
|
||||
.filter(|g| (include_private || g.public) && matches(s, uid, g))
|
||||
.map(|g| g.name.clone())
|
||||
.map(|g| g.name)
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue