inspircd: restore logins from replayed accountname metadata
All checks were successful
CI / check (push) Successful in 3m45s
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:
parent
99df7baf10
commit
7e868babc3
4 changed files with 58 additions and 0 deletions
|
|
@ -850,6 +850,18 @@ impl Engine {
|
|||
}
|
||||
out
|
||||
}
|
||||
NetEvent::AccountLogin { uid, account } => {
|
||||
// The ircd told us who a user is logged in as (e.g. replayed on our
|
||||
// netburst). Restore the mapping so services recognise the login;
|
||||
// no side-effects — the burst already put them in their channels.
|
||||
if account.is_empty() {
|
||||
self.network.clear_account(&uid);
|
||||
} else {
|
||||
self.network.set_account(&uid, &account);
|
||||
self.pending_enforce.retain(|p| p.uid != uid);
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
NetEvent::NickChange { uid, nick } => {
|
||||
let new_nick = nick.clone();
|
||||
self.network.user_nick_change(&uid, nick);
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue