Search: node settings are indexed, with credentials masked on the server
/search gains a `setting` category, `<node>.<setting>` under its flow with the node type and the value in a new `detail` field, so Ctrl-K finds which node uses a broker or a timeout and opens the node. `setting_text` is the one place that decides what may be said: a reference to a stored secret shows its name (to superusers only, as the secrets list does), a plain value in an `x-secret` field or under a key like password, token or api_key is masked and never indexed, nested credentials in headers or query are masked, long values are clipped. The global search ranks what contains the query as typed ahead of loose spellings before it caps a group, which long setting values would otherwise have crowded out.
This commit is contained in:
@@ -21,7 +21,14 @@ test.beforeAll(async ({ browser }) => {
|
||||
data: {
|
||||
name: flowName,
|
||||
title: "Searchable flow",
|
||||
nodes: [{ id: "findme", type: "python", title: "Find me" }],
|
||||
nodes: [
|
||||
{
|
||||
id: "findme",
|
||||
type: "python",
|
||||
title: "Find me",
|
||||
params: { tuning_gain: 7, api_token: "s3cr3t-token" },
|
||||
},
|
||||
],
|
||||
inputs: [{ spec: { name: "findme_input", dtype: "float" } }],
|
||||
},
|
||||
})
|
||||
@@ -102,3 +109,26 @@ test("opens on the keyboard from anywhere", async ({ page }) => {
|
||||
|
||||
await expect(page.getByTestId("global-search-input")).toBeFocused()
|
||||
})
|
||||
|
||||
test("finds a setting with its value, and never a credential", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/")
|
||||
await page.getByRole("button", { name: "Search", exact: true }).click()
|
||||
const input = page.getByTestId("global-search-input")
|
||||
|
||||
await input.fill("tuning_gain")
|
||||
const gain = page.getByRole("option", { name: /findme\.tuning_gain/ })
|
||||
await expect(gain).toContainText(`${flowName} · python · 7`)
|
||||
|
||||
// The token is masked on the server, so it never reaches the page.
|
||||
await input.fill("api_token")
|
||||
await expect(
|
||||
page.getByRole("option", { name: /findme\.api_token/ }),
|
||||
).toContainText("••••")
|
||||
await expect(page.getByRole("dialog")).not.toContainText("s3cr3t-token")
|
||||
|
||||
await input.fill("tuning_gain")
|
||||
await gain.click()
|
||||
await expect(page).toHaveURL(new RegExp(`/flows/${flowName}\\?node=findme$`))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user