From e080e5f076a54e77935e6632d7ba585ac3260dff Mon Sep 17 00:00:00 2001 From: Salastil Date: Fri, 28 Aug 2026 09:13:22 -0400 Subject: [PATCH] Offer the SASL settings the pane already claimed to have The daemon has done SASL for a long time. There was simply no way to turn it on: the account card offered autojoin, a NickServ password and the proxy switch, and nothing else - while the settings pane told people that "SASL, autojoin and NickServ auto-identify are per-account instead, from that account's own entry in the Accounts pane". Two of those three were true. So the card carries them now, behind one switch because they are one decision, and sent as one call because the daemon stores them together - a username applied without the password it goes with is a state that could decide a connection attempt on its own. The plaintext allowance only appears on a connection that has no encryption, which the daemon now reports. On a TLS account it decides nothing, and a switch that appears to weaken something while doing nothing is worse than no switch. Where it does appear it says what it actually means: SASL PLAIN is the password with base64 round it, and without the allowance connecting is refused rather than done quietly in the clear. Submodule moves to the matching daemon. --- nobilis | 2 +- src/renderer/src/app.css | 15 +++ src/renderer/src/components/AccountsPanel.tsx | 110 ++++++++++++++++++ src/shared/wire.ts | 5 + 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/nobilis b/nobilis index e0c66ca..d4b6ab8 160000 --- a/nobilis +++ b/nobilis @@ -1 +1 @@ -Subproject commit e0c66ca0c98966f5f382d47c675e5444df732834 +Subproject commit d4b6ab89f3102b6dacb6a00f75021ecdb70cec6d diff --git a/src/renderer/src/app.css b/src/renderer/src/app.css index 99d4124..afb8aeb 100644 --- a/src/renderer/src/app.css +++ b/src/renderer/src/app.css @@ -816,6 +816,21 @@ img.composer-emoji { gap: var(--spacing-s); } +/* The SASL fields read as one decision rather than three loose settings, so + they are boxed together and indent under the switch that turns them on. */ +.sasl-block { + display: flex; + flex-direction: column; + gap: var(--spacing-s); + padding: var(--spacing-s); + border: 1px solid var(--outline-light); + border-radius: var(--corner-radius); +} + +.sasl-block .field { + margin-left: calc(16px + var(--spacing-s)); +} + .qr-image { width: 220px; height: 220px; diff --git a/src/renderer/src/components/AccountsPanel.tsx b/src/renderer/src/components/AccountsPanel.tsx index 566c5e8..abea1d6 100644 --- a/src/renderer/src/components/AccountsPanel.tsx +++ b/src/renderer/src/components/AccountsPanel.tsx @@ -274,6 +274,7 @@ function AccountRow({ account }: { account: Account }): JSX.Element { call('setAccountAutojoin', { accountId: account.id, channels }) } /> + ) => void +}): JSX.Element { + const [username, setUsername] = useState(account.saslUsername) + const [password, setPassword] = useState('') + const [allowPlaintext, setAllowPlaintext] = useState(account.allowPlaintextSasl) + + const apply = (patch: { enabled?: boolean; saslUser?: string; allowPlaintextSasl?: boolean }): void => + call('setAccountSasl', { + accountId: account.id, + enabled: account.saslEnabled, + saslUser: username, + // Empty means "leave the stored one alone" - the daemon never reads a + // password back out, so there is nothing to prefill and clearing the + // box must not be read as clearing the credential. + password, + allowPlaintextSasl: allowPlaintext, + ...patch + }) + + return ( +
+ + + {account.saslEnabled && ( + <> + { + setUsername(value) + apply({ saslUser: value }) + }} + /> + { + setPassword(value) + call('setAccountSasl', { + accountId: account.id, + enabled: true, + saslUser: username, + password: value, + allowPlaintextSasl: allowPlaintext + }) + }} + /> + + {/* Only where it is a live question. On a TLS connection the + allowance decides nothing, and offering it there would be a + switch that appears to weaken something and does not. */} + {!account.ssl && ( + + )} + + )} +
+ ) +} + function LabeledInput({ label, defaultValue, diff --git a/src/shared/wire.ts b/src/shared/wire.ts index 251992c..1965e92 100644 --- a/src/shared/wire.ts +++ b/src/shared/wire.ts @@ -16,6 +16,11 @@ export interface Account { saslEnabled: boolean saslUsername: string allowPlaintextSasl: boolean + /** + * Whether the connection is encrypted. Only IRC is ever false - every other + * service here is HTTPS or WSS by construction. + */ + ssl: boolean hasPassword: boolean avatarUrl?: string sockchatRooms?: SockChatRoom[]