fix and update
This commit is contained in:
@@ -711,6 +711,9 @@ function LoginPageContent() {
|
||||
try {
|
||||
|
||||
await completePin(pendingSessionId, pin);
|
||||
setPendingSessionId(null);
|
||||
setPin('');
|
||||
finishLoginRedirect();
|
||||
|
||||
} catch (error) {
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user