mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix: preserve ClickClack setup secret refs
This commit is contained in:
@@ -12,16 +12,20 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { useAutoCleanupTempDirTracker } from "../../../test/helpers/temp-dir.js";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
createClient: vi.fn(),
|
||||
me: vi.fn(),
|
||||
resolveWorkspaceId: vi.fn(),
|
||||
workspaces: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./http-client.js", () => ({
|
||||
createClickClackClient: () => ({
|
||||
me: mocks.me,
|
||||
workspaces: mocks.workspaces,
|
||||
}),
|
||||
createClickClackClient: (options: unknown) => {
|
||||
mocks.createClient(options);
|
||||
return {
|
||||
me: mocks.me,
|
||||
workspaces: mocks.workspaces,
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("./resolve.js", () => ({
|
||||
@@ -54,6 +58,7 @@ function tokenCredential() {
|
||||
|
||||
describe("ClickClack setup wizard", () => {
|
||||
beforeEach(() => {
|
||||
mocks.createClient.mockReset();
|
||||
mocks.me.mockReset();
|
||||
mocks.resolveWorkspaceId.mockReset();
|
||||
mocks.workspaces.mockReset();
|
||||
@@ -126,6 +131,35 @@ describe("ClickClack setup wizard", () => {
|
||||
hasConfiguredValue: true,
|
||||
resolvedValue: "ccb_file",
|
||||
});
|
||||
|
||||
const secretRefAccount = {
|
||||
channels: {
|
||||
clickclack: {
|
||||
baseUrl: "https://clickclack.example",
|
||||
token: { source: "file", provider: "vault", id: "/clickclack/token" },
|
||||
workspace: "default",
|
||||
},
|
||||
},
|
||||
} satisfies CoreConfig;
|
||||
expect(await clickClackSetupWizard.status.resolveConfigured({ cfg: secretRefAccount })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
credential.inspect({
|
||||
cfg: secretRefAccount,
|
||||
accountId: "default",
|
||||
}),
|
||||
).toMatchObject({
|
||||
accountConfigured: true,
|
||||
hasConfiguredValue: true,
|
||||
resolvedValue: undefined,
|
||||
});
|
||||
expect(
|
||||
clickClackSetupWizard.introNote?.shouldShow?.({
|
||||
cfg: secretRefAccount,
|
||||
accountId: "default",
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("switches the default account to env auth before URL and workspace prompts", async () => {
|
||||
@@ -192,6 +226,27 @@ describe("ClickClack setup wizard", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("uses the resolved setup credential for live validation", async () => {
|
||||
await runSetupWizardFinalize({
|
||||
finalize: clickClackSetupWizard.finalize,
|
||||
cfg: {
|
||||
channels: {
|
||||
clickclack: {
|
||||
baseUrl: "https://clickclack.example",
|
||||
token: { source: "file", provider: "vault", id: "/clickclack/token" },
|
||||
workspace: "default",
|
||||
},
|
||||
},
|
||||
} satisfies CoreConfig,
|
||||
credentialValues: { token: "ccb_resolved" },
|
||||
});
|
||||
|
||||
expect(mocks.createClient).toHaveBeenCalledWith({
|
||||
baseUrl: "https://clickclack.example",
|
||||
token: "ccb_resolved",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps setup saved when the token is rejected", async () => {
|
||||
mocks.me.mockRejectedValue({ status: 401 });
|
||||
const note = vi.fn(async () => undefined);
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
applyClickClackSetupConfigPatch,
|
||||
normalizeClickClackBaseUrl,
|
||||
} from "./setup-core.js";
|
||||
import type { CoreConfig } from "./types.js";
|
||||
import type { CoreConfig, ResolvedClickClackAccount } from "./types.js";
|
||||
|
||||
const t = createSetupTranslator();
|
||||
const channel = "clickclack" as const;
|
||||
@@ -35,6 +35,20 @@ function isWorkspaceNotFound(error: unknown): boolean {
|
||||
return error instanceof Error && error.message.startsWith("ClickClack workspace not found:");
|
||||
}
|
||||
|
||||
function hasConfiguredClickClackCredential(account: ResolvedClickClackAccount): boolean {
|
||||
return (
|
||||
hasConfiguredSecretInput(account.config.token) || Boolean(account.config.tokenFile?.trim())
|
||||
);
|
||||
}
|
||||
|
||||
function isClickClackSetupConfigured(account: ResolvedClickClackAccount): boolean {
|
||||
return Boolean(
|
||||
account.baseUrl &&
|
||||
account.workspace &&
|
||||
(account.token || hasConfiguredClickClackCredential(account)),
|
||||
);
|
||||
}
|
||||
|
||||
export const clickClackSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: createStandardChannelSetupStatus({
|
||||
@@ -48,10 +62,12 @@ export const clickClackSetupWizard: ChannelSetupWizard = {
|
||||
resolveConfigured: ({ cfg, accountId }) =>
|
||||
(accountId ? [accountId] : listClickClackAccountIds(cfg as CoreConfig)).some(
|
||||
(resolvedAccountId) =>
|
||||
resolveClickClackAccount({
|
||||
cfg: cfg as CoreConfig,
|
||||
accountId: resolvedAccountId,
|
||||
}).configured,
|
||||
isClickClackSetupConfigured(
|
||||
resolveClickClackAccount({
|
||||
cfg: cfg as CoreConfig,
|
||||
accountId: resolvedAccountId,
|
||||
}),
|
||||
),
|
||||
),
|
||||
}),
|
||||
introNote: {
|
||||
@@ -63,10 +79,12 @@ export const clickClackSetupWizard: ChannelSetupWizard = {
|
||||
}),
|
||||
],
|
||||
shouldShow: ({ cfg, accountId }) =>
|
||||
!resolveClickClackAccount({
|
||||
cfg: cfg as CoreConfig,
|
||||
accountId,
|
||||
}).configured,
|
||||
!isClickClackSetupConfigured(
|
||||
resolveClickClackAccount({
|
||||
cfg: cfg as CoreConfig,
|
||||
accountId,
|
||||
}),
|
||||
),
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
@@ -83,11 +101,10 @@ export const clickClackSetupWizard: ChannelSetupWizard = {
|
||||
cfg: cfg as CoreConfig,
|
||||
accountId,
|
||||
});
|
||||
const hasConfiguredValue = hasConfiguredClickClackCredential(resolved);
|
||||
return {
|
||||
accountConfigured: resolved.configured,
|
||||
hasConfiguredValue:
|
||||
hasConfiguredSecretInput(resolved.config.token) ||
|
||||
Boolean(resolved.config.tokenFile?.trim()),
|
||||
accountConfigured: Boolean(resolved.token) || hasConfiguredValue,
|
||||
hasConfiguredValue,
|
||||
resolvedValue: resolved.token || undefined,
|
||||
envValue:
|
||||
accountId === DEFAULT_ACCOUNT_ID
|
||||
@@ -148,7 +165,7 @@ export const clickClackSetupWizard: ChannelSetupWizard = {
|
||||
}),
|
||||
},
|
||||
],
|
||||
finalize: async ({ cfg, accountId, prompter }) => {
|
||||
finalize: async ({ cfg, accountId, credentialValues, prompter }) => {
|
||||
const account = resolveClickClackAccount({
|
||||
cfg: cfg as CoreConfig,
|
||||
accountId,
|
||||
@@ -156,7 +173,7 @@ export const clickClackSetupWizard: ChannelSetupWizard = {
|
||||
try {
|
||||
const client = createClickClackClient({
|
||||
baseUrl: account.baseUrl,
|
||||
token: account.token,
|
||||
token: credentialValues.token || account.token,
|
||||
});
|
||||
const me = await client.me();
|
||||
const workspaceId = await resolveWorkspaceId(client, account.workspace);
|
||||
|
||||
Reference in New Issue
Block a user