From 4bba49770dd76e3a48530f084f01c8a90c3720a2 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Mon, 12 Jan 2026 22:59:37 +0530 Subject: [PATCH] fix: clear gateway auth on off selection --- src/commands/configure.gateway-auth.test.ts | 55 +++++++++++++++++++++ src/commands/configure.ts | 53 ++++++++++++-------- 2 files changed, 88 insertions(+), 20 deletions(-) create mode 100644 src/commands/configure.gateway-auth.test.ts diff --git a/src/commands/configure.gateway-auth.test.ts b/src/commands/configure.gateway-auth.test.ts new file mode 100644 index 000000000..69faad450 --- /dev/null +++ b/src/commands/configure.gateway-auth.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, it } from "vitest"; + +import { buildGatewayAuthConfig } from "./configure.js"; + +describe("buildGatewayAuthConfig", () => { + it("clears token/password when auth is off", () => { + const result = buildGatewayAuthConfig({ + existing: { mode: "token", token: "abc", password: "secret" }, + mode: "off", + }); + + expect(result).toBeUndefined(); + }); + + it("preserves allowTailscale when auth is off", () => { + const result = buildGatewayAuthConfig({ + existing: { + mode: "token", + token: "abc", + allowTailscale: true, + }, + mode: "off", + }); + + expect(result).toEqual({ allowTailscale: true }); + }); + + it("drops password when switching to token", () => { + const result = buildGatewayAuthConfig({ + existing: { + mode: "password", + password: "secret", + allowTailscale: false, + }, + mode: "token", + token: "abc", + }); + + expect(result).toEqual({ + mode: "token", + token: "abc", + allowTailscale: false, + }); + }); + + it("drops token when switching to password", () => { + const result = buildGatewayAuthConfig({ + existing: { mode: "token", token: "abc" }, + mode: "password", + password: "secret", + }); + + expect(result).toEqual({ mode: "password", password: "secret" }); + }); +}); diff --git a/src/commands/configure.ts b/src/commands/configure.ts index 82ebb1296..1546b7e28 100644 --- a/src/commands/configure.ts +++ b/src/commands/configure.ts @@ -8,7 +8,7 @@ import { text as clackText, } from "@clack/prompts"; import { ensureAuthProfileStore } from "../agents/auth-profiles.js"; -import type { ClawdbotConfig } from "../config/config.js"; +import type { ClawdbotConfig, GatewayAuthConfig } from "../config/config.js"; import { CONFIG_PATH_CLAWDBOT, readConfigFileSnapshot, @@ -157,6 +157,27 @@ const CONFIGURE_SECTION_OPTIONS: { type ConfigureSectionChoice = WizardSection | "__continue"; +type GatewayAuthChoice = "off" | "token" | "password"; + +export function buildGatewayAuthConfig(params: { + existing?: GatewayAuthConfig; + mode: GatewayAuthChoice; + token?: string; + password?: string; +}): GatewayAuthConfig | undefined { + const allowTailscale = params.existing?.allowTailscale; + const base: GatewayAuthConfig = {}; + if (typeof allowTailscale === "boolean") base.allowTailscale = allowTailscale; + + if (params.mode === "off") { + return Object.keys(base).length > 0 ? base : undefined; + } + if (params.mode === "token") { + return { ...base, mode: "token", token: params.token }; + } + return { ...base, mode: "password", password: params.password }; +} + async function promptConfigureSection( runtime: RuntimeEnv, hasSelection: boolean, @@ -225,7 +246,7 @@ async function promptGatewayConfig( initialValue: "token", }), runtime, - ) as "off" | "token" | "password"; + ) as GatewayAuthChoice; const tailscaleMode = guardCancel( await select({ @@ -287,6 +308,7 @@ async function promptGatewayConfig( } let gatewayToken: string | undefined; + let gatewayPassword: string | undefined; let next = cfg; if (authMode === "token") { @@ -298,13 +320,6 @@ async function promptGatewayConfig( runtime, ); gatewayToken = String(tokenInput).trim() || randomToken(); - next = { - ...next, - gateway: { - ...next.gateway, - auth: { ...next.gateway?.auth, mode: "token", token: gatewayToken }, - }, - }; } if (authMode === "password") { @@ -315,19 +330,16 @@ async function promptGatewayConfig( }), runtime, ); - next = { - ...next, - gateway: { - ...next.gateway, - auth: { - ...next.gateway?.auth, - mode: "password", - password: String(password).trim(), - }, - }, - }; + gatewayPassword = String(password).trim(); } + const authConfig = buildGatewayAuthConfig({ + existing: next.gateway?.auth, + mode: authMode, + token: gatewayToken, + password: gatewayPassword, + }); + next = { ...next, gateway: { @@ -335,6 +347,7 @@ async function promptGatewayConfig( mode: "local", port, bind, + auth: authConfig, tailscale: { ...next.gateway?.tailscale, mode: tailscaleMode,