From 8bcd172c5a05c8e8eb3ddf08895e09fb7a1958bb Mon Sep 17 00:00:00 2001 From: Supra4E8C Date: Mon, 15 Dec 2025 17:47:32 +0800 Subject: [PATCH] fix(auth): add singleton pattern to restoreSession and unify config fetch --- .claude/settings.local.json | 13 +++++++++ src/stores/useAuthStore.ts | 56 +++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 24 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..ee97e89 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,13 @@ +{ + "permissions": { + "allow": [ + "Bash(npm run lint:*)", + "Bash(npx tsc:*)", + "Bash(npm run build)", + "Bash(npm run type-check:*)", + "Bash(find:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/src/stores/useAuthStore.ts b/src/stores/useAuthStore.ts index 0e57d78..96a35b5 100644 --- a/src/stores/useAuthStore.ts +++ b/src/stores/useAuthStore.ts @@ -9,7 +9,6 @@ import type { AuthState, LoginCredentials, ConnectionStatus } from '@/types'; import { STORAGE_KEY_AUTH } from '@/utils/constants'; import { secureStorage } from '@/services/storage/secureStorage'; import { apiClient } from '@/services/api/client'; -import { configApi } from '@/services/api/config'; import { useConfigStore } from './useConfigStore'; import { detectApiBaseFromLocation, normalizeApiBase } from '@/utils/connection'; @@ -26,6 +25,8 @@ interface AuthStoreState extends AuthState { updateConnectionStatus: (status: ConnectionStatus, error?: string | null) => void; } +let restoreSessionPromise: Promise | null = null; + export const useAuthStore = create()( persist( (set, get) => ({ @@ -39,33 +40,39 @@ export const useAuthStore = create()( connectionError: null, // 恢复会话并自动登录 - restoreSession: async () => { - secureStorage.migratePlaintextKeys(['apiBase', 'apiUrl', 'managementKey']); + restoreSession: () => { + if (restoreSessionPromise) return restoreSessionPromise; - const wasLoggedIn = localStorage.getItem('isLoggedIn') === 'true'; - const legacyBase = - secureStorage.getItem('apiBase') || - secureStorage.getItem('apiUrl', { encrypt: true }); - const legacyKey = secureStorage.getItem('managementKey'); + restoreSessionPromise = (async () => { + secureStorage.migratePlaintextKeys(['apiBase', 'apiUrl', 'managementKey']); - const { apiBase, managementKey } = get(); - const resolvedBase = normalizeApiBase(apiBase || legacyBase || detectApiBaseFromLocation()); - const resolvedKey = managementKey || legacyKey || ''; + const wasLoggedIn = localStorage.getItem('isLoggedIn') === 'true'; + const legacyBase = + secureStorage.getItem('apiBase') || + secureStorage.getItem('apiUrl', { encrypt: true }); + const legacyKey = secureStorage.getItem('managementKey'); - set({ apiBase: resolvedBase, managementKey: resolvedKey }); - apiClient.setConfig({ apiBase: resolvedBase, managementKey: resolvedKey }); + const { apiBase, managementKey } = get(); + const resolvedBase = normalizeApiBase(apiBase || legacyBase || detectApiBaseFromLocation()); + const resolvedKey = managementKey || legacyKey || ''; - if (wasLoggedIn && resolvedBase && resolvedKey) { - try { - await get().login({ apiBase: resolvedBase, managementKey: resolvedKey }); - return true; - } catch (error) { - console.warn('Auto login failed:', error); - return false; + set({ apiBase: resolvedBase, managementKey: resolvedKey }); + apiClient.setConfig({ apiBase: resolvedBase, managementKey: resolvedKey }); + + if (wasLoggedIn && resolvedBase && resolvedKey) { + try { + await get().login({ apiBase: resolvedBase, managementKey: resolvedKey }); + return true; + } catch (error) { + console.warn('Auto login failed:', error); + return false; + } } - } - return false; + return false; + })(); + + return restoreSessionPromise; }, // 登录 @@ -83,7 +90,7 @@ export const useAuthStore = create()( }); // 测试连接 - 获取配置 - await configApi.getConfig(); + await useConfigStore.getState().fetchConfig(undefined, true); // 登录成功 set({ @@ -105,6 +112,7 @@ export const useAuthStore = create()( // 登出 logout: () => { + restoreSessionPromise = null; useConfigStore.getState().clearCache(); set({ isAuthenticated: false, @@ -131,7 +139,7 @@ export const useAuthStore = create()( apiClient.setConfig({ apiBase, managementKey }); // 验证连接 - await configApi.getConfig(); + await useConfigStore.getState().fetchConfig(); set({ isAuthenticated: true,