Skip to content

Commit e4266e1

Browse files
author
fengjiayi
committed
fix: verify MCP management key before connecting
1 parent 603043c commit e4266e1

1 file changed

Lines changed: 26 additions & 12 deletions

File tree

frontend/sereinflow-web/src/components/runs/McpKeySettings.vue

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@ import { t } from '../../i18n'
2222
2323
const props = defineProps<{ projectWorkspaces: ProjectWorkspaceDto[] }>()
2424
25-
const managementSecret = ref(getMcpManagementCredential())
25+
const initialCredential = getMcpManagementCredential()
26+
const managementSecret = ref(initialCredential)
27+
const credentialInput = ref(initialCredential ?? '')
2628
const rememberCredential = ref(hasRememberedMcpManagementCredential())
2729
const keys = ref<McpApiKeyDto[]>([])
2830
const isLoading = ref(false)
2931
const isSaving = ref(false)
32+
const isAuthenticated = ref(false)
3033
const error = ref('')
3134
const notice = ref('')
3235
const revealedSecret = ref('')
33-
const connected = computed(() => Boolean(managementSecret.value))
36+
const connected = computed(() => isAuthenticated.value)
3437
const projectOptions = computed(() => mcpKeyProjectOptions(props.projectWorkspaces))
3538
3639
const createForm = reactive<CreateMcpApiKeyRequestDto>({
@@ -56,19 +59,23 @@ const permissionOptions: Array<{ value: McpPermission; label: string; hint: stri
5659
{ value: 'sensitive.read', label: '敏感内容读取', hint: '读取脚本源码或流程字面量' },
5760
]
5861
59-
async function loadKeys(): Promise<void> {
60-
if (!managementSecret.value) return
62+
async function loadKeys(secret = managementSecret.value): Promise<boolean> {
63+
if (!secret) return false
6164
isLoading.value = true
6265
error.value = ''
6366
try {
64-
keys.value = await listMcpApiKeys(managementSecret.value)
67+
keys.value = await listMcpApiKeys(secret)
68+
managementSecret.value = secret
69+
isAuthenticated.value = true
70+
return true
6571
} catch (exception) {
6672
if (exception instanceof McpApiError && exception.status === 401) {
6773
clearCredential()
6874
error.value = t('console.mcpKeyUnauthorized')
6975
} else {
7076
error.value = errorMessage(exception)
7177
}
78+
return false
7279
} finally {
7380
isLoading.value = false
7481
}
@@ -81,6 +88,8 @@ async function setupKey(): Promise<void> {
8188
try {
8289
const created = await setupMcpApiKey()
8390
managementSecret.value = created.secret
91+
credentialInput.value = created.secret
92+
isAuthenticated.value = true
8493
storeMcpManagementCredential(created.secret, rememberCredential.value)
8594
revealedSecret.value = created.secret
8695
notice.value = t('console.mcpKeyCreated')
@@ -93,14 +102,17 @@ async function setupKey(): Promise<void> {
93102
}
94103
95104
async function connectKey(): Promise<void> {
96-
const candidate = managementSecret.value?.trim()
105+
if (isLoading.value || isSaving.value) return
106+
const candidate = credentialInput.value.trim()
97107
if (!candidate) {
98108
error.value = t('console.mcpKeyRequired')
99109
return
100110
}
101-
storeMcpManagementCredential(candidate, rememberCredential.value)
102-
managementSecret.value = candidate
103-
await loadKeys()
111+
notice.value = ''
112+
if (await loadKeys(candidate)) {
113+
storeMcpManagementCredential(candidate, rememberCredential.value)
114+
notice.value = t('console.mcpKeyConnected')
115+
}
104116
}
105117
106118
async function createKey(): Promise<void> {
@@ -189,6 +201,8 @@ async function copySecret(): Promise<void> {
189201
function clearCredential(): void {
190202
clearMcpManagementCredential()
191203
managementSecret.value = undefined
204+
credentialInput.value = ''
205+
isAuthenticated.value = false
192206
keys.value = []
193207
revealedSecret.value = ''
194208
}
@@ -225,7 +239,7 @@ onMounted(() => { void loadKeys() })
225239
<h2 id="mcp-key-settings-title"><KeyRound :size="17" />{{ t('console.mcpKeyTitle') }}</h2>
226240
<p>{{ t('console.mcpKeyHint') }}</p>
227241
</div>
228-
<button v-if="connected" class="icon-button" type="button" :title="t('console.mcpKeyRefresh')" :aria-label="t('console.mcpKeyRefresh')" :disabled="isLoading" @click="loadKeys"><RefreshCw :size="15" :class="{ 'is-spinning': isLoading }" /></button>
242+
<button v-if="connected" class="icon-button" type="button" :title="t('console.mcpKeyRefresh')" :aria-label="t('console.mcpKeyRefresh')" :disabled="isLoading" @click="loadKeys()"><RefreshCw :size="15" :class="{ 'is-spinning': isLoading }" /></button>
229243
</div>
230244

231245
<p v-if="error" class="mcp-key-settings__message mcp-key-settings__message--error" role="alert">{{ error }}</p>
@@ -240,9 +254,9 @@ onMounted(() => { void loadKeys() })
240254

241255
<div v-if="!connected" class="mcp-key-settings__connect">
242256
<div class="mcp-key-settings__empty"><LockKeyhole :size="20" /><div><strong>{{ t('console.mcpKeyConnectTitle') }}</strong><p>{{ t('console.mcpKeyConnectHint') }}</p></div></div>
243-
<label class="mcp-key-settings__credential"><span>{{ t('console.mcpKeySecretLabel') }}</span><input v-model="managementSecret" type="password" autocomplete="off" :placeholder="t('console.mcpKeySecretPlaceholder')" @keyup.enter="connectKey" /></label>
257+
<label class="mcp-key-settings__credential"><span>{{ t('console.mcpKeySecretLabel') }}</span><input v-model="credentialInput" type="password" autocomplete="off" :placeholder="t('console.mcpKeySecretPlaceholder')" @keyup.enter="connectKey" /></label>
244258
<label class="mcp-key-settings__remember"><input v-model="rememberCredential" type="checkbox" /><span>{{ t('console.mcpKeyRemember') }}</span></label>
245-
<div class="mcp-key-settings__actions"><button class="command-button run" type="button" :disabled="isSaving" @click="connectKey"><ShieldCheck :size="15" /><span>{{ t('console.mcpKeyConnect') }}</span></button><button class="command-button quiet" type="button" :disabled="isSaving" @click="setupKey"><Plus :size="15" /><span>{{ t('console.mcpKeySetup') }}</span></button></div>
259+
<div class="mcp-key-settings__actions"><button class="command-button run" type="button" :disabled="isSaving || isLoading" @click="connectKey"><ShieldCheck :size="15" /><span>{{ t('console.mcpKeyConnect') }}</span></button><button class="command-button quiet" type="button" :disabled="isSaving || isLoading" @click="setupKey"><Plus :size="15" /><span>{{ t('console.mcpKeySetup') }}</span></button></div>
246260
</div>
247261

248262
<template v-else>

0 commit comments

Comments
 (0)