Fix Android documents and idle session
This commit is contained in:
@@ -1,31 +1,24 @@
|
||||
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
||||
import { login as apiLogin, logout as apiLogout, getMe } from '../api/auth';
|
||||
import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { login as apiLogin, logout as apiLogout, getMe, refreshSession as apiRefreshSession } from '../api/auth';
|
||||
import { updateSignatureAppearancePreference as apiUpdateSignatureAppearancePreference } from '../api/users';
|
||||
import {
|
||||
clearAccessToken,
|
||||
expireSession,
|
||||
getAccessToken,
|
||||
getAccessTokenExpiryDelay,
|
||||
SESSION_EXPIRED_EVENT,
|
||||
setAccessToken,
|
||||
} from '../utils/session';
|
||||
|
||||
const AuthContext = createContext(null);
|
||||
const IDLE_SESSION_MS = 15 * 60 * 1000;
|
||||
const ACTIVE_REFRESH_MS = 9 * 60 * 1000;
|
||||
const ACTIVITY_EVENTS = ['click', 'keydown', 'mousemove', 'scroll', 'touchstart'];
|
||||
|
||||
export function AuthProvider({ children }) {
|
||||
const [user, setUser] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const scheduleSessionExpiry = useCallback((token) => {
|
||||
const delay = getAccessTokenExpiryDelay(token);
|
||||
if (delay === null) return undefined;
|
||||
|
||||
const timeoutId = window.setTimeout(() => {
|
||||
expireSession();
|
||||
}, delay);
|
||||
|
||||
return () => window.clearTimeout(timeoutId);
|
||||
}, []);
|
||||
const lastActivityRef = useRef(Date.now());
|
||||
const lastRefreshRef = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
const token = getAccessToken();
|
||||
@@ -48,15 +41,50 @@ export function AuthProvider({ children }) {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const token = getAccessToken();
|
||||
if (!user || !token) return undefined;
|
||||
return scheduleSessionExpiry(token);
|
||||
}, [scheduleSessionExpiry, user]);
|
||||
if (!user) return undefined;
|
||||
|
||||
const registerActivity = () => {
|
||||
const now = Date.now();
|
||||
if (now - lastActivityRef.current > IDLE_SESSION_MS) {
|
||||
expireSession();
|
||||
return;
|
||||
}
|
||||
lastActivityRef.current = now;
|
||||
};
|
||||
|
||||
const keepAlive = async () => {
|
||||
const now = Date.now();
|
||||
if (now - lastActivityRef.current > IDLE_SESSION_MS) {
|
||||
expireSession();
|
||||
return;
|
||||
}
|
||||
|
||||
if (now - lastRefreshRef.current < ACTIVE_REFRESH_MS || !getAccessToken()) return;
|
||||
|
||||
try {
|
||||
const { data } = await apiRefreshSession();
|
||||
setAccessToken(data.data.accessToken);
|
||||
lastRefreshRef.current = now;
|
||||
} catch {
|
||||
expireSession();
|
||||
}
|
||||
};
|
||||
|
||||
ACTIVITY_EVENTS.forEach((eventName) => window.addEventListener(eventName, registerActivity, { passive: true }));
|
||||
const intervalId = window.setInterval(keepAlive, 60 * 1000);
|
||||
|
||||
return () => {
|
||||
ACTIVITY_EVENTS.forEach((eventName) => window.removeEventListener(eventName, registerActivity));
|
||||
window.clearInterval(intervalId);
|
||||
};
|
||||
}, [user]);
|
||||
|
||||
const login = useCallback(async (email, password) => {
|
||||
const { data } = await apiLogin({ email, password });
|
||||
const { accessToken, user: userData } = data.data;
|
||||
setAccessToken(accessToken);
|
||||
lastActivityRef.current = Date.now();
|
||||
lastRefreshRef.current = Date.now();
|
||||
setUser(userData);
|
||||
return userData;
|
||||
}, []);
|
||||
|
||||
Reference in New Issue
Block a user