fix and update

This commit is contained in:
lendry
2026-07-07 10:38:53 +03:00
parent 12f46f572d
commit f1821c2edc
2 changed files with 67 additions and 64 deletions

View File

@@ -711,6 +711,9 @@ function LoginPageContent() {
try {
await completePin(pendingSessionId, pin);
setPendingSessionId(null);
setPin('');
finishLoginRedirect();
} catch (error) {

View File

@@ -143,6 +143,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const [pinError, setPinError] = React.useState<string | null>(null);
const [bootstrapError, setBootstrapError] = React.useState<string | null>(null);
const isPinLockedRef = React.useRef(false);
const userIdRef = React.useRef<string | null | undefined>(null);
const refreshInFlightRef = React.useRef<Promise<void> | 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,34 +644,48 @@ 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();
markPinIdleWatch(userIdRef.current ?? cachedUser?.id);
if (cachedUser) {
setUser(cachedUser);
}
clearPinLock();
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 onAuthEntryPage =
pathname.startsWith('/auth/login') || pathname.startsWith('/auth/register');
if (!onAuthEntryPage) {
const postPinRedirect =
typeof window !== 'undefined'
? resolvePostPinAuthRedirect(pathname, window.location.search)
@@ -705,9 +703,11 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
await finalizeFedcmLogin(response.accessToken);
} else {
void syncFedcmSession(response.accessToken);
scheduleFedcmSessionSync(response.accessToken, 8000);
}
}
},
[pathname, router, user?.id, warmUpAndApplySession]
[activatePinLock, clearPinLock, pathname, router, showToast]
);
const handlePinUnlock = React.useCallback(