fix(integrations): align vault-backed credential status
This commit is contained in:
parent
be0424652c
commit
ed5a628fa9
@ -4,6 +4,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import { CheckCircle2, Loader2, RefreshCw, ShieldCheck } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
import { resolveCredentialReady } from "@/lib/integrations/credentialStatus";
|
||||
import type { IntegrationDefaults } from "@/lib/openclaw/types";
|
||||
import type { XWorkmateProfileResponse } from "@/lib/xworkmate/types";
|
||||
import { toXWorkmateIntegrationDefaults } from "@/lib/xworkmate/types";
|
||||
@ -147,10 +148,14 @@ export function XWorkmateProfileEditor({
|
||||
key: "openclaw",
|
||||
label: "OpenClaw",
|
||||
configured: Boolean(openclawUrl.trim()),
|
||||
tokenConfigured:
|
||||
payload.tokenConfigured.openclaw ||
|
||||
Boolean(vaultSecretPath.trim()) ||
|
||||
Boolean(openclawToken.trim()),
|
||||
tokenConfigured: resolveCredentialReady({
|
||||
inlineToken: openclawToken,
|
||||
storedTokenConfigured: payload.tokenConfigured.openclaw,
|
||||
vaultUrl,
|
||||
vaultSecretPath,
|
||||
vaultAuthToken: vaultToken,
|
||||
storedVaultAuthConfigured: payload.tokenConfigured.vault,
|
||||
}),
|
||||
},
|
||||
{
|
||||
key: "vault",
|
||||
@ -163,8 +168,14 @@ export function XWorkmateProfileEditor({
|
||||
key: "apisix",
|
||||
label: "APISIX",
|
||||
configured: Boolean(apisixUrl.trim()),
|
||||
tokenConfigured:
|
||||
payload.tokenConfigured.apisix || Boolean(apisixToken.trim()),
|
||||
tokenConfigured: resolveCredentialReady({
|
||||
inlineToken: apisixToken,
|
||||
storedTokenConfigured: payload.tokenConfigured.apisix,
|
||||
vaultUrl,
|
||||
vaultSecretPath,
|
||||
vaultAuthToken: vaultToken,
|
||||
storedVaultAuthConfigured: payload.tokenConfigured.vault,
|
||||
}),
|
||||
},
|
||||
],
|
||||
[
|
||||
|
||||
34
src/lib/integrations/credentialStatus.test.ts
Normal file
34
src/lib/integrations/credentialStatus.test.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import {
|
||||
hasVaultBackedCredentialAccess,
|
||||
resolveCredentialReady,
|
||||
} from '@/lib/integrations/credentialStatus'
|
||||
|
||||
describe('credentialStatus', () => {
|
||||
test('marks credentials ready when an inline token is present', () => {
|
||||
expect(
|
||||
resolveCredentialReady({
|
||||
inlineToken: 'live-token',
|
||||
}),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
test('marks credentials ready when vault auth can resolve a locator-backed secret', () => {
|
||||
expect(
|
||||
resolveCredentialReady({
|
||||
vaultUrl: 'https://vault.svc.plus',
|
||||
vaultSecretPath: 'kv/team-a/openclaw',
|
||||
vaultAuthToken: 'vault-token',
|
||||
}),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
test('keeps credentials pending when the vault locator is incomplete', () => {
|
||||
expect(
|
||||
hasVaultBackedCredentialAccess({
|
||||
vaultUrl: 'https://vault.svc.plus',
|
||||
vaultSecretPath: 'kv/team-a/openclaw',
|
||||
storedVaultAuthConfigured: false,
|
||||
}),
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
33
src/lib/integrations/credentialStatus.ts
Normal file
33
src/lib/integrations/credentialStatus.ts
Normal file
@ -0,0 +1,33 @@
|
||||
type CredentialStatusInput = {
|
||||
inlineToken?: string
|
||||
storedTokenConfigured?: boolean
|
||||
vaultUrl?: string
|
||||
vaultSecretPath?: string
|
||||
vaultAuthToken?: string
|
||||
storedVaultAuthConfigured?: boolean
|
||||
}
|
||||
|
||||
function hasText(value?: string): boolean {
|
||||
return Boolean(value?.trim())
|
||||
}
|
||||
|
||||
export function hasVaultBackedCredentialAccess(
|
||||
input: Pick<
|
||||
CredentialStatusInput,
|
||||
'vaultUrl' | 'vaultSecretPath' | 'vaultAuthToken' | 'storedVaultAuthConfigured'
|
||||
>,
|
||||
): boolean {
|
||||
return (
|
||||
hasText(input.vaultUrl) &&
|
||||
hasText(input.vaultSecretPath) &&
|
||||
(hasText(input.vaultAuthToken) || Boolean(input.storedVaultAuthConfigured))
|
||||
)
|
||||
}
|
||||
|
||||
export function resolveCredentialReady(input: CredentialStatusInput): boolean {
|
||||
return (
|
||||
Boolean(input.storedTokenConfigured) ||
|
||||
hasText(input.inlineToken) ||
|
||||
hasVaultBackedCredentialAccess(input)
|
||||
)
|
||||
}
|
||||
@ -11,6 +11,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { resolveCredentialReady } from "@/lib/integrations/credentialStatus";
|
||||
import type { IntegrationDefaults } from "@/lib/openclaw/types";
|
||||
import { useOpenClawConsoleStore } from "@/state/openclawConsoleStore";
|
||||
|
||||
@ -199,10 +200,14 @@ export function IntegrationsConsole({
|
||||
key: "openclaw",
|
||||
label: "OpenClaw Gateway",
|
||||
configured: Boolean(openclawUrl.trim()),
|
||||
tokenConfigured:
|
||||
resolvedDefaults.openclawTokenConfigured ||
|
||||
Boolean(vaultSecretPath.trim() && (vaultToken.trim() || resolvedDefaults.vaultTokenConfigured)) ||
|
||||
Boolean(openclawToken.trim()),
|
||||
tokenConfigured: resolveCredentialReady({
|
||||
inlineToken: openclawToken,
|
||||
storedTokenConfigured: resolvedDefaults.openclawTokenConfigured,
|
||||
vaultUrl,
|
||||
vaultSecretPath,
|
||||
vaultAuthToken: vaultToken,
|
||||
storedVaultAuthConfigured: resolvedDefaults.vaultTokenConfigured,
|
||||
}),
|
||||
},
|
||||
{
|
||||
key: "vault",
|
||||
@ -215,8 +220,14 @@ export function IntegrationsConsole({
|
||||
key: "apisix",
|
||||
label: "APISIX AI Gateway",
|
||||
configured: Boolean(apisixUrl.trim()),
|
||||
tokenConfigured:
|
||||
resolvedDefaults.apisixTokenConfigured || Boolean(apisixToken.trim()),
|
||||
tokenConfigured: resolveCredentialReady({
|
||||
inlineToken: apisixToken,
|
||||
storedTokenConfigured: resolvedDefaults.apisixTokenConfigured,
|
||||
vaultUrl,
|
||||
vaultSecretPath,
|
||||
vaultAuthToken: vaultToken,
|
||||
storedVaultAuthConfigured: resolvedDefaults.vaultTokenConfigured,
|
||||
}),
|
||||
},
|
||||
],
|
||||
[
|
||||
@ -332,7 +343,9 @@ export function IntegrationsConsole({
|
||||
</p>
|
||||
<p className="mt-1 text-xs text-[var(--color-text-subtle)]">
|
||||
{item.configured ? "address ready" : "missing address"} ·{" "}
|
||||
{item.tokenConfigured ? "token ready" : "token pending"}
|
||||
{item.tokenConfigured
|
||||
? "credential path ready"
|
||||
: "credential pending"}
|
||||
</p>
|
||||
</div>
|
||||
<StatusBadge
|
||||
|
||||
Loading…
Reference in New Issue
Block a user