Use RPL_LOGGEDIN/OUT to mirror upstream status

This will allow clients to properly show/hide UI to login and
register.
This commit is contained in:
Simon Ser 2021-11-19 19:21:48 +01:00
parent b5a868bbcd
commit c2a5461cb8
3 changed files with 36 additions and 5 deletions

View File

@ -258,6 +258,7 @@ type downstreamConn struct {
clientName string clientName string
realname string realname string
hostname string hostname string
account string // RPL_LOGGEDIN/OUT state
password string // empty after authentication password string // empty after authentication
network *network // can be nil network *network // can be nil
isMultiUpstream bool isMultiUpstream bool
@ -759,11 +760,10 @@ func (dc *downstreamConn) handleMessageUnregistered(ctx context.Context, msg *ir
return fmt.Errorf("SASL authentication failed: %v", err) return fmt.Errorf("SASL authentication failed: %v", err)
} else if done { } else if done {
dc.saslServer = nil dc.saslServer = nil
dc.SendMessage(&irc.Message{ // Technically we should send RPL_LOGGEDIN here. However we use
Prefix: dc.srv.prefix(), // RPL_LOGGEDIN to mirror the upstream connection status. Let's see
Command: irc.RPL_LOGGEDIN, // how many clients that breaks. See:
Params: []string{dc.nick, dc.prefix().String(), dc.user.Username, "You are now logged in"}, // https://github.com/ircv3/ircv3-specifications/pull/476
})
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(), Prefix: dc.srv.prefix(),
Command: irc.RPL_SASLSUCCESS, Command: irc.RPL_SASLSUCCESS,
@ -1037,6 +1037,29 @@ func (dc *downstreamConn) updateRealname() {
} }
} }
func (dc *downstreamConn) updateAccount() {
uc := dc.upstream()
if uc == nil || uc.account == dc.account || !dc.caps["sasl"] {
return
}
if uc.account != "" {
dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(),
Command: irc.RPL_LOGGEDIN,
Params: []string{dc.nick, dc.prefix().String(), uc.account, "You are logged in as " + uc.account},
})
} else {
dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(),
Command: irc.RPL_LOGGEDOUT,
Params: []string{dc.nick, dc.prefix().String(), "You are logged out"},
})
}
dc.account = uc.account
}
func sanityCheckServer(ctx context.Context, addr string) error { func sanityCheckServer(ctx context.Context, addr string) error {
ctx, cancel := context.WithTimeout(ctx, 15*time.Second) ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel() defer cancel()
@ -1260,6 +1283,7 @@ func (dc *downstreamConn) welcome(ctx context.Context) error {
dc.updateNick() dc.updateNick()
dc.updateRealname() dc.updateRealname()
dc.updateAccount()
if motd := dc.user.srv.Config().MOTD; motd != "" && dc.network == nil { if motd := dc.user.srv.Config().MOTD; motd != "" && dc.network == nil {
for _, msg := range generateMOTD(dc.srv.prefix(), dc.nick, motd) { for _, msg := range generateMOTD(dc.srv.prefix(), dc.nick, motd) {

View File

@ -586,9 +586,15 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
return err return err
} }
uc.logger.Printf("logged in with account %q", uc.account) uc.logger.Printf("logged in with account %q", uc.account)
uc.forEachDownstream(func(dc *downstreamConn) {
dc.updateAccount()
})
case irc.RPL_LOGGEDOUT: case irc.RPL_LOGGEDOUT:
uc.account = "" uc.account = ""
uc.logger.Printf("logged out") uc.logger.Printf("logged out")
uc.forEachDownstream(func(dc *downstreamConn) {
dc.updateAccount()
})
case irc.ERR_NICKLOCKED, irc.RPL_SASLSUCCESS, irc.ERR_SASLFAIL, irc.ERR_SASLTOOLONG, irc.ERR_SASLABORTED: case irc.ERR_NICKLOCKED, irc.RPL_SASLSUCCESS, irc.ERR_SASLFAIL, irc.ERR_SASLTOOLONG, irc.ERR_SASLABORTED:
var info string var info string
if err := parseMessageParams(msg, nil, &info); err != nil { if err := parseMessageParams(msg, nil, &info); err != nil {

View File

@ -541,6 +541,7 @@ func (u *user) run() {
dc.updateNick() dc.updateNick()
dc.updateRealname() dc.updateRealname()
dc.updateAccount()
}) })
u.forEachDownstream(func(dc *downstreamConn) { u.forEachDownstream(func(dc *downstreamConn) {
if dc.caps["soju.im/bouncer-networks-notify"] { if dc.caps["soju.im/bouncer-networks-notify"] {