fix and update

This commit is contained in:
lendry
2026-06-30 16:03:33 +03:00
parent 69063c8fba
commit 2eeb928a72
6 changed files with 138 additions and 19 deletions

View File

@@ -107,15 +107,13 @@ function applySessionState(
function readInitialAuthState() {
if (typeof window === 'undefined') {
return { token: null as string | null, hasStoredSession: false, cachedUser: null as PublicUser | null };
return { token: null as string | null, hasStoredSession: false };
}
const token = window.localStorage.getItem(AUTH_TOKEN_KEY);
const refresh = window.localStorage.getItem(AUTH_REFRESH_KEY);
const cachedUser = readCachedUserProfile();
return {
token,
hasStoredSession: Boolean(refresh || token),
cachedUser
hasStoredSession: Boolean(refresh || token)
};
}
@@ -125,7 +123,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const { showToast } = useToast();
const initialAuth = React.useMemo(() => readInitialAuthState(), []);
const [token, setToken] = React.useState<string | null>(initialAuth.token);
const [user, setUser] = React.useState<PublicUser | null>(initialAuth.cachedUser);
const [user, setUser] = React.useState<PublicUser | null>(null);
const [isLoading, setIsLoading] = React.useState(true);
const [isApiReady, setIsApiReady] = React.useState(false);
const [isSessionReady, setIsSessionReady] = React.useState(false);
@@ -269,8 +267,12 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
setHasStoredSession(Boolean(refreshToken));
if (!currentToken && !refreshToken) {
window.localStorage.removeItem(AUTH_USER_CACHE_KEY);
setUser(null);
setToken(null);
initialBootstrapDoneRef.current = true;
setIsSessionReady(true);
setIsApiReady(true);
setIsLoading(false);
return;
}
@@ -282,7 +284,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}
try {
for (let bootstrapAttempt = 0; bootstrapAttempt < 6; bootstrapAttempt += 1) {
for (let bootstrapAttempt = 0; bootstrapAttempt < 4; bootstrapAttempt += 1) {
try {
if (isInitialBootstrap) {
await waitForStableGateway(3);
@@ -293,11 +295,14 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
try {
const session = await fetchAuthSession(currentToken);
applySessionState(session, { setUser, setToken, activatePinLock, clearPinLock });
setIsApiReady(true);
setIsSessionReady(true);
return;
} catch (error) {
if (isPinRequiredError(error)) {
activatePinLock(error.sessionId ?? window.localStorage.getItem(AUTH_SESSION_KEY) ?? '');
setIsApiReady(true);
setIsSessionReady(true);
return;
}
if (!(error instanceof ApiError) || error.code !== 'TOKEN_EXPIRED') {
@@ -321,11 +326,14 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
cacheUserProfile(refreshed.user);
}
activatePinLock(refreshed.sessionId ?? '');
setIsApiReady(true);
setIsSessionReady(true);
return;
}
if (refreshed.accessToken) {
const session = await fetchAuthSession(refreshed.accessToken);
applySessionState(session, { setUser, setToken, activatePinLock, clearPinLock });
setIsApiReady(true);
setIsSessionReady(true);
return;
}
@@ -333,17 +341,26 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
throw new ApiError('Сессия недействительна', 401);
} catch (error) {
if (isGatewayUnavailableError(error) && isInitialBootstrap && bootstrapAttempt + 1 < 6) {
if (isGatewayUnavailableError(error) && isInitialBootstrap && bootstrapAttempt + 1 < 4) {
invalidateApiGatewayReady();
if (bootstrapAttempt >= 1) {
setBootstrapError(
'Не удалось подключиться к серверу API (502). Подождите несколько секунд и нажмите «Повторить».'
);
}
await new Promise((resolve) => setTimeout(resolve, 1200));
continue;
}
if (isPinRequiredError(error)) {
activatePinLock(error.sessionId ?? window.localStorage.getItem(AUTH_SESSION_KEY) ?? '');
setIsApiReady(true);
setIsSessionReady(true);
return;
}
if (refreshToken && error instanceof ApiError && error.status === 403) {
activatePinLock(window.localStorage.getItem(AUTH_SESSION_KEY) ?? '');
setIsApiReady(true);
setIsSessionReady(true);
return;
}
if (error instanceof ApiError && (error.code === 'NO_REFRESH' || error.status === 401)) {
@@ -612,7 +629,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const isBootstrapping =
!isPinLocked &&
Boolean(hasStoredSession || token || user) &&
Boolean(hasStoredSession || token) &&
(isLoading || !isApiReady || !isSessionReady);
return (
@@ -649,6 +666,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
? () => {
setBootstrapError(null);
initialBootstrapDoneRef.current = false;
invalidateApiGatewayReady();
void refreshProfile();
}
: undefined