From e121b6ab8628ee120413a535a07ac0de726fb7a2 Mon Sep 17 00:00:00 2001 From: Ryan Angilly Date: Tue, 3 Mar 2026 09:18:43 -0700 Subject: [PATCH] fix: mask workspace credential fields in settings UI --- .../test/web-ui-token-field-masking.test.ts | 44 +++++++++++++++++++ .../src/routes/(settings)/+layout.svelte | 12 +++-- .../workspace/[workspaceName]/+page.svelte | 12 +++-- 3 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 packages/core/test/web-ui-token-field-masking.test.ts diff --git a/packages/core/test/web-ui-token-field-masking.test.ts b/packages/core/test/web-ui-token-field-masking.test.ts new file mode 100644 index 0000000..c69d455 --- /dev/null +++ b/packages/core/test/web-ui-token-field-masking.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, it } from "bun:test"; +import { join } from "node:path"; + +function findInputBlock(markup: string, inputId: string): string | undefined { + const inputBlocks = markup.match(//g) ?? []; + return inputBlocks.find((block) => block.includes(`id="${inputId}"`)); +} + +async function readWorkspaceSettingsMarkup(relativePath: string): Promise { + const absolutePath = join(process.cwd(), relativePath); + return Bun.file(absolutePath).text(); +} + +describe("web-ui credential fields", () => { + it("masks token fields in add workspace dialog", async () => { + const markup = await readWorkspaceSettingsMarkup("packages/web-ui/src/routes/(settings)/+layout.svelte"); + + for (const inputId of [ + "new-workspace-app-token", + "new-workspace-bot-token", + "new-workspace-discord-bot-token", + "new-workspace-lark-app-secret", + ]) { + const block = findInputBlock(markup, inputId); + expect(block).toBeDefined(); + expect(block).toContain('type="password"'); + } + }); + + it("masks token fields in workspace detail editor", async () => { + const markup = await readWorkspaceSettingsMarkup("packages/web-ui/src/routes/(settings)/workspace/[workspaceName]/+page.svelte"); + + for (const inputId of [ + "workspace-app-token", + "workspace-bot-token", + "workspace-discord-bot-token", + "workspace-lark-app-secret", + ]) { + const block = findInputBlock(markup, inputId); + expect(block).toBeDefined(); + expect(block).toContain('type="password"'); + } + }); +}); diff --git a/packages/web-ui/src/routes/(settings)/+layout.svelte b/packages/web-ui/src/routes/(settings)/+layout.svelte index af7b371..d4b83b2 100644 --- a/packages/web-ui/src/routes/(settings)/+layout.svelte +++ b/packages/web-ui/src/routes/(settings)/+layout.svelte @@ -306,9 +306,10 @@ @@ -316,9 +317,10 @@ @@ -327,9 +329,10 @@ @@ -349,9 +352,10 @@ diff --git a/packages/web-ui/src/routes/(settings)/workspace/[workspaceName]/+page.svelte b/packages/web-ui/src/routes/(settings)/workspace/[workspaceName]/+page.svelte index cffa01a..32d794d 100644 --- a/packages/web-ui/src/routes/(settings)/workspace/[workspaceName]/+page.svelte +++ b/packages/web-ui/src/routes/(settings)/workspace/[workspaceName]/+page.svelte @@ -372,9 +372,10 @@ onWorkspaceTextInput(selectedWorkspace.id, "slackAppToken", event)} + autocomplete="new-password" /> @@ -382,9 +383,10 @@ onWorkspaceTextInput(selectedWorkspace.id, "slackBotToken", event)} + autocomplete="new-password" /> {:else if selectedWorkspace.type === "discord"} @@ -392,9 +394,10 @@ onWorkspaceTextInput(selectedWorkspace.id, "discordBotToken", event)} + autocomplete="new-password" /> {:else} @@ -412,9 +415,10 @@ onWorkspaceTextInput(selectedWorkspace.id, "larkAppSecret", event)} + autocomplete="new-password" /> {/if}