fix(auth): add singleton pattern to restoreSession and unify config fetch

This commit is contained in:
Supra4E8C
2025-12-15 17:47:32 +08:00
parent 4d898b3e20
commit 8bcd172c5a
2 changed files with 45 additions and 24 deletions

View File

@@ -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": []
}
}

View File

@@ -9,7 +9,6 @@ import type { AuthState, LoginCredentials, ConnectionStatus } from '@/types';
import { STORAGE_KEY_AUTH } from '@/utils/constants'; import { STORAGE_KEY_AUTH } from '@/utils/constants';
import { secureStorage } from '@/services/storage/secureStorage'; import { secureStorage } from '@/services/storage/secureStorage';
import { apiClient } from '@/services/api/client'; import { apiClient } from '@/services/api/client';
import { configApi } from '@/services/api/config';
import { useConfigStore } from './useConfigStore'; import { useConfigStore } from './useConfigStore';
import { detectApiBaseFromLocation, normalizeApiBase } from '@/utils/connection'; import { detectApiBaseFromLocation, normalizeApiBase } from '@/utils/connection';
@@ -26,6 +25,8 @@ interface AuthStoreState extends AuthState {
updateConnectionStatus: (status: ConnectionStatus, error?: string | null) => void; updateConnectionStatus: (status: ConnectionStatus, error?: string | null) => void;
} }
let restoreSessionPromise: Promise<boolean> | null = null;
export const useAuthStore = create<AuthStoreState>()( export const useAuthStore = create<AuthStoreState>()(
persist( persist(
(set, get) => ({ (set, get) => ({
@@ -39,33 +40,39 @@ export const useAuthStore = create<AuthStoreState>()(
connectionError: null, connectionError: null,
// 恢复会话并自动登录 // 恢复会话并自动登录
restoreSession: async () => { restoreSession: () => {
secureStorage.migratePlaintextKeys(['apiBase', 'apiUrl', 'managementKey']); if (restoreSessionPromise) return restoreSessionPromise;
const wasLoggedIn = localStorage.getItem('isLoggedIn') === 'true'; restoreSessionPromise = (async () => {
const legacyBase = secureStorage.migratePlaintextKeys(['apiBase', 'apiUrl', 'managementKey']);
secureStorage.getItem<string>('apiBase') ||
secureStorage.getItem<string>('apiUrl', { encrypt: true });
const legacyKey = secureStorage.getItem<string>('managementKey');
const { apiBase, managementKey } = get(); const wasLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
const resolvedBase = normalizeApiBase(apiBase || legacyBase || detectApiBaseFromLocation()); const legacyBase =
const resolvedKey = managementKey || legacyKey || ''; secureStorage.getItem<string>('apiBase') ||
secureStorage.getItem<string>('apiUrl', { encrypt: true });
const legacyKey = secureStorage.getItem<string>('managementKey');
set({ apiBase: resolvedBase, managementKey: resolvedKey }); const { apiBase, managementKey } = get();
apiClient.setConfig({ apiBase: resolvedBase, managementKey: resolvedKey }); const resolvedBase = normalizeApiBase(apiBase || legacyBase || detectApiBaseFromLocation());
const resolvedKey = managementKey || legacyKey || '';
if (wasLoggedIn && resolvedBase && resolvedKey) { set({ apiBase: resolvedBase, managementKey: resolvedKey });
try { apiClient.setConfig({ apiBase: resolvedBase, managementKey: resolvedKey });
await get().login({ apiBase: resolvedBase, managementKey: resolvedKey });
return true; if (wasLoggedIn && resolvedBase && resolvedKey) {
} catch (error) { try {
console.warn('Auto login failed:', error); await get().login({ apiBase: resolvedBase, managementKey: resolvedKey });
return false; 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<AuthStoreState>()(
}); });
// 测试连接 - 获取配置 // 测试连接 - 获取配置
await configApi.getConfig(); await useConfigStore.getState().fetchConfig(undefined, true);
// 登录成功 // 登录成功
set({ set({
@@ -105,6 +112,7 @@ export const useAuthStore = create<AuthStoreState>()(
// 登出 // 登出
logout: () => { logout: () => {
restoreSessionPromise = null;
useConfigStore.getState().clearCache(); useConfigStore.getState().clearCache();
set({ set({
isAuthenticated: false, isAuthenticated: false,
@@ -131,7 +139,7 @@ export const useAuthStore = create<AuthStoreState>()(
apiClient.setConfig({ apiBase, managementKey }); apiClient.setConfig({ apiBase, managementKey });
// 验证连接 // 验证连接
await configApi.getConfig(); await useConfigStore.getState().fetchConfig();
set({ set({
isAuthenticated: true, isAuthenticated: true,