From f1821c2edccbfb66d8d9abb545fe9ff22580ff75 Mon Sep 17 00:00:00 2001 From: lendry Date: Tue, 7 Jul 2026 10:38:53 +0300 Subject: [PATCH] fix and update --- apps/frontend/app/auth/login/page.tsx | 3 + apps/frontend/components/id/auth-provider.tsx | 128 +++++++++--------- 2 files changed, 67 insertions(+), 64 deletions(-) diff --git a/apps/frontend/app/auth/login/page.tsx b/apps/frontend/app/auth/login/page.tsx index 34ed0c8..c01ea2c 100644 --- a/apps/frontend/app/auth/login/page.tsx +++ b/apps/frontend/app/auth/login/page.tsx @@ -711,6 +711,9 @@ function LoginPageContent() { try { await completePin(pendingSessionId, pin); + setPendingSessionId(null); + setPin(''); + finishLoginRedirect(); } catch (error) { diff --git a/apps/frontend/components/id/auth-provider.tsx b/apps/frontend/components/id/auth-provider.tsx index c533c4d..4b970ea 100644 --- a/apps/frontend/components/id/auth-provider.tsx +++ b/apps/frontend/components/id/auth-provider.tsx @@ -143,6 +143,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const [pinError, setPinError] = React.useState(null); const [bootstrapError, setBootstrapError] = React.useState(null); const isPinLockedRef = React.useRef(false); + const userIdRef = React.useRef(null); const refreshInFlightRef = React.useRef | null>(null); const initialBootstrapDoneRef = React.useRef(false); @@ -170,6 +171,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { isPinLockedRef.current = isPinLocked; }, [isPinLocked]); + React.useEffect(() => { + userIdRef.current = user?.id; + }, [user?.id]); + const clearPinLock = React.useCallback(() => { setIsPinLocked(false); setLockedSessionId(null); @@ -193,7 +198,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const activatePinLock = React.useCallback((sessionId: string) => { const resolvedSessionId = sessionId || window.localStorage.getItem(AUTH_SESSION_KEY); if (!resolvedSessionId) return; - markPinIdleWatch(user?.id); + markPinIdleWatch(userIdRef.current); setLockedSessionId(resolvedSessionId); setIsPinLocked(true); setPinError(null); @@ -206,36 +211,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { if (accessToken) { void syncFedcmSession(accessToken); } - }, [user?.id]); - - const warmUpAndApplySession = React.useCallback( - async (accessToken: string) => { - setIsSessionReady(false); - setIsLoading(true); - setBootstrapError(null); - invalidateApiGatewayReady(); - setIsApiReady(false); - - try { - await ensureApiGatewayReady(); - const session = await fetchAuthSession(accessToken); - applySessionState(session, { setUser, setToken, activatePinLock, clearPinLock }); - initialBootstrapDoneRef.current = true; - setIsApiReady(true); - setIsSessionReady(true); - } catch (error) { - setBootstrapError( - isGatewayUnavailableError(error) - ? 'Не удалось подключиться к серверу API. Подождите несколько секунд и нажмите «Повторить».' - : (getApiErrorMessage(error, 'Не удалось подключиться к серверу API') ?? 'Ошибка подключения') - ); - throw error; - } finally { - setIsLoading(false); - } - }, - [activatePinLock, clearPinLock] - ); + }, []); const establishSession = React.useCallback( async (auth: AuthTokens) => { @@ -463,9 +439,12 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { return () => setPinRequiredHandler(null); }, [activatePinLock]); + const refreshProfileRef = React.useRef(refreshProfile); + refreshProfileRef.current = refreshProfile; + React.useEffect(() => { - void refreshProfile(); - }, [refreshProfile]); + void refreshProfileRef.current(); + }, []); const pinIdleLockEnabled = isSessionReady && @@ -523,6 +502,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { await establishSession(auth); } else { persistPartialAuth(auth); + setUser(auth.user); markPinIdleWatch(auth.user.id); setHasStoredSession(true); } @@ -559,6 +539,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { await establishSession(response.auth); } else if (response.auth) { persistPartialAuth(response.auth); + setUser(response.auth.user); markPinIdleWatch(response.auth.user.id); setHasStoredSession(true); } @@ -581,6 +562,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { await establishSession(auth); } else { persistPartialAuth(auth); + setUser(auth.user); markPinIdleWatch(auth.user.id); setHasStoredSession(true); } @@ -603,6 +585,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { await establishSession(auth); } else { persistPartialAuth(auth); + setUser(auth.user); markPinIdleWatch(auth.user.id); setHasStoredSession(true); } @@ -632,6 +615,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { await establishSession(auth); } else { persistPartialAuth(auth); + setUser(auth.user); markPinIdleWatch(auth.user.id); setHasStoredSession(true); } @@ -660,54 +644,70 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { method: 'POST', body: JSON.stringify({ sessionId, pin }) }); + window.localStorage.setItem(AUTH_TOKEN_KEY, response.accessToken); window.localStorage.setItem(AUTH_SESSION_KEY, sessionId); setToken(response.accessToken); - markPinIdleWatch(user?.id); + clearPinLock(); - try { - await warmUpAndApplySession(response.accessToken); - } catch (error) { - if (!isGatewayUnavailableError(error)) { - throw error; - } - const cachedUser = readCachedUserProfile(); - if (cachedUser) { - setUser(cachedUser); - } - clearPinLock(); - setBootstrapError(null); - initialBootstrapDoneRef.current = true; - setIsApiReady(true); - setIsSessionReady(true); - setIsLoading(false); + const cachedUser = readCachedUserProfile(); + markPinIdleWatch(userIdRef.current ?? cachedUser?.id); + if (cachedUser) { + setUser(cachedUser); } + setHasStoredSession(true); + setBootstrapError(null); + initialBootstrapDoneRef.current = true; + setIsApiReady(true); + setIsSessionReady(true); + setIsLoading(false); + + void fetchAuthSession(response.accessToken) + .then((session) => { + applySessionState(session, { setUser, setToken, activatePinLock, clearPinLock }); + }) + .catch((error) => { + if (isPinRequiredError(error)) { + activatePinLock(error.sessionId ?? sessionId); + return; + } + if (!isGatewayUnavailableError(error)) { + const message = getApiErrorMessage(error, 'Не удалось обновить профиль после PIN'); + if (message) showToast(message); + } + }); if (isFedcmLoginPopup()) { await finalizeFedcmLogin(response.accessToken); return; } - const postPinRedirect = - typeof window !== 'undefined' - ? resolvePostPinAuthRedirect(pathname, window.location.search) - : null; + const onAuthEntryPage = + pathname.startsWith('/auth/login') || pathname.startsWith('/auth/register'); + + if (!onAuthEntryPage) { + const postPinRedirect = + typeof window !== 'undefined' + ? resolvePostPinAuthRedirect(pathname, window.location.search) + : null; + + if (postPinRedirect !== null) { + if (shouldFinalizeFedcmLogin(pathname)) { + await finalizeFedcmLogin(response.accessToken); + } + router.replace(postPinRedirect); + return; + } - if (postPinRedirect !== null) { if (shouldFinalizeFedcmLogin(pathname)) { await finalizeFedcmLogin(response.accessToken); + } else { + void syncFedcmSession(response.accessToken); + scheduleFedcmSessionSync(response.accessToken, 8000); } - router.replace(postPinRedirect); - return; - } - - if (shouldFinalizeFedcmLogin(pathname)) { - await finalizeFedcmLogin(response.accessToken); - } else { - void syncFedcmSession(response.accessToken); } }, - [pathname, router, user?.id, warmUpAndApplySession] + [activatePinLock, clearPinLock, pathname, router, showToast] ); const handlePinUnlock = React.useCallback(