Add OperServ with AKILL network bans
The first operator module. AKILL manages network bans as a typed, event-sourced list with lazy expiry, mirroring the patterns the other modules use: - AKILL ADD [+expiry] <user@host> <reason> stores the ban and drives an ircd G-line (applied to matching users already online and to future connections); AKILL DEL <mask|number> lifts it; AKILL LIST [pattern] shows the live list, numbered. Admin-only. - Bans are Global events, so every node holds the list and re-asserts each one at burst with its remaining duration. Expired bans are hidden lazily and dropped at compaction. - Masks are normalised to user@host (a nick! prefix is stripped, both sides lowercased) and an all-wildcard mask is refused. Email (send_email) is already reachable from the api via ServiceCtx, and adds AddLine/DelLine to the action vocabulary for any future X-line kinds.
This commit is contained in:
parent
253d4c2a2d
commit
d2c1d076fb
12 changed files with 430 additions and 12 deletions
|
|
@ -318,6 +318,14 @@ impl Protocol for InspIrcd {
|
|||
NetAction::Invite { from, uid, channel } => {
|
||||
vec![format!(":{} INVITE {} {} 1 0", from, uid, channel)]
|
||||
}
|
||||
// ADDLINE <type> <mask> <setter> <set-time> <duration> :<reason>. A
|
||||
// duration of 0 is permanent; the ircd applies it to matching users
|
||||
// already online and propagates it across the network.
|
||||
NetAction::AddLine { kind, mask, setter, duration, reason } => {
|
||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(self.ts);
|
||||
vec![self.sourced(format!("ADDLINE {} {} {} {} {} :{}", kind, mask, setter, now, duration, reason))]
|
||||
}
|
||||
NetAction::DelLine { kind, mask } => vec![self.sourced(format!("DELLINE {} {}", kind, mask))],
|
||||
NetAction::Raw(s) => vec![s.clone()],
|
||||
// Internal: the link layer handles these before serialization.
|
||||
NetAction::DeferRegister { .. } | NetAction::DeferPassword { .. } | NetAction::SendEmail { .. } => vec![],
|
||||
|
|
@ -485,6 +493,23 @@ mod tests {
|
|||
assert!(!lines[0].contains('\n') && !lines[0].contains('\r'));
|
||||
}
|
||||
|
||||
// A network ban serializes to ADDLINE / DELLINE, sourced from our server.
|
||||
#[test]
|
||||
fn serializes_network_bans() {
|
||||
let add = proto().serialize(&NetAction::AddLine {
|
||||
kind: "G".into(),
|
||||
mask: "*@evil.host".into(),
|
||||
setter: "staff".into(),
|
||||
duration: 3600,
|
||||
reason: "spamming".into(),
|
||||
});
|
||||
assert_eq!(add.len(), 1);
|
||||
assert!(add[0].starts_with(":42S ADDLINE G *@evil.host staff "), "{add:?}");
|
||||
assert!(add[0].ends_with(" 3600 :spamming"), "{add:?}");
|
||||
let del = proto().serialize(&NetAction::DelLine { kind: "G".into(), mask: "*@evil.host".into() });
|
||||
assert_eq!(del, vec![":42S DELLINE G *@evil.host".to_string()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_ftopic_and_filters_own() {
|
||||
let ev = proto().parse(":0IRAAAAAB FTOPIC #chan 1783845132 1783845140 :Welcome all");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue