inspircd: restore logins from replayed accountname metadata
All checks were successful
CI / check (push) Successful in 3m45s

The inbound parser ignored METADATA entirely, so on a services netburst
(after a restart/relink) the ircd's replayed 'accountname' metadata was
dropped — every logged-in user looked logged out to services until they
re-identified, losing ChanServ access. Parse METADATA <uid> accountname
into a new AccountLogin event that restores account_of (empty = logout);
our own echoes and other keys are filtered.
This commit is contained in:
Jean Chevronnet 2026-07-16 09:54:35 +00:00
parent 99df7baf10
commit 7e868babc3
No known key found for this signature in database
4 changed files with 58 additions and 0 deletions

View file

@ -432,6 +432,19 @@
assert!(parted, "the assigned bot parts the released channel");
}
// A netburst that replays a user's accountname restores their services login
// (so a services restart doesn't silently log everyone out); empty = logout.
#[test]
fn account_login_event_restores_session() {
let mut e = engine_with("acctlogin", "alice", "sesame");
e.handle(NetEvent::UserConnect { uid: "000AAAAAB".into(), nick: "alice".into(), host: "h".into() , ip: "0.0.0.0".into() });
assert_eq!(e.network.account_of("000AAAAAB"), None, "not recognised before the metadata");
e.handle(NetEvent::AccountLogin { uid: "000AAAAAB".into(), account: "alice".into() });
assert_eq!(e.network.account_of("000AAAAAB"), Some("alice"), "login restored from the ircd");
e.handle(NetEvent::AccountLogin { uid: "000AAAAAB".into(), account: String::new() });
assert_eq!(e.network.account_of("000AAAAAB"), None, "empty account is a logout");
}
// A suspension that arrives by gossip must end local sessions on that account,
// just as a local SUSPEND does — the account and its channels stay put.
#[test]