updates on the login
This commit is contained in:
96
src/hooks/useInactivityLogout.js
Normal file
96
src/hooks/useInactivityLogout.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { clearFcmToken } from 'store/reducers/fcmSlice';
|
||||
import { logoutUser } from 'store/reducers/loginUserSlice';
|
||||
import {
|
||||
ABSOLUTE_SESSION_TIMEOUT_MS,
|
||||
ACTIVITY_STORAGE_KEY,
|
||||
AUTH_PRESENCE_KEY,
|
||||
INACTIVITY_TIMEOUT_MS,
|
||||
SESSION_START_STORAGE_KEY,
|
||||
isSessionActive,
|
||||
markActivity,
|
||||
markSessionStart,
|
||||
performSessionLogout
|
||||
} from 'utils/session';
|
||||
|
||||
const ACTIVITY_EVENTS = ['mousemove', 'mousedown', 'keydown', 'scroll', 'touchstart', 'wheel'];
|
||||
const ACTIVITY_WRITE_THROTTLE_MS = 5000;
|
||||
const IDLE_CHECK_INTERVAL_MS = 15000;
|
||||
|
||||
// Two independent timers, both enforced from localStorage so every tab on the
|
||||
// origin agrees:
|
||||
// - INACTIVITY_TIMEOUT_MS: logs out after 15 minutes with no interaction, so
|
||||
// a laptop left unlocked doesn't leave the console open indefinitely.
|
||||
// - ABSOLUTE_SESSION_TIMEOUT_MS: a hard 30-minute cap since login, even if
|
||||
// the user has been continuously active, so localStorage (auth keys, FCM
|
||||
// token, cached zone list) never lingers on disk longer than that.
|
||||
// A logout in one tab (auth key cleared) is picked up by the others via the
|
||||
// 'storage' event.
|
||||
const useInactivityLogout = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useDispatch();
|
||||
const lastWriteRef = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
const doLogout = () => performSessionLogout({ queryClient, dispatch, clearFcmToken, logoutUser });
|
||||
|
||||
const handleActivity = () => {
|
||||
const now = Date.now();
|
||||
if (now - lastWriteRef.current < ACTIVITY_WRITE_THROTTLE_MS) return;
|
||||
lastWriteRef.current = now;
|
||||
markActivity();
|
||||
};
|
||||
|
||||
const handleStorage = (event) => {
|
||||
if (event.key === AUTH_PRESENCE_KEY && !event.newValue) {
|
||||
doLogout();
|
||||
}
|
||||
};
|
||||
|
||||
// Guards against the browser restoring a cached (bfcache) copy of a
|
||||
// protected page via the back/forward button after logout happened.
|
||||
const handlePageShow = (event) => {
|
||||
if (event.persisted && !isSessionActive()) {
|
||||
window.location.replace('/login');
|
||||
}
|
||||
};
|
||||
|
||||
if (isSessionActive()) {
|
||||
if (!localStorage.getItem(ACTIVITY_STORAGE_KEY)) markActivity();
|
||||
// Sessions that were already open before this feature shipped won't have
|
||||
// a start time yet — give them a fresh 30-minute window instead of
|
||||
// treating them as already expired.
|
||||
if (!localStorage.getItem(SESSION_START_STORAGE_KEY)) markSessionStart();
|
||||
}
|
||||
|
||||
ACTIVITY_EVENTS.forEach((eventName) => window.addEventListener(eventName, handleActivity, { passive: true }));
|
||||
window.addEventListener('storage', handleStorage);
|
||||
window.addEventListener('pageshow', handlePageShow);
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
if (!isSessionActive()) return;
|
||||
|
||||
const lastActivity = Number(localStorage.getItem(ACTIVITY_STORAGE_KEY)) || Date.now();
|
||||
if (Date.now() - lastActivity >= INACTIVITY_TIMEOUT_MS) {
|
||||
doLogout();
|
||||
return;
|
||||
}
|
||||
|
||||
const sessionStart = Number(localStorage.getItem(SESSION_START_STORAGE_KEY)) || Date.now();
|
||||
if (Date.now() - sessionStart >= ABSOLUTE_SESSION_TIMEOUT_MS) {
|
||||
doLogout();
|
||||
}
|
||||
}, IDLE_CHECK_INTERVAL_MS);
|
||||
|
||||
return () => {
|
||||
ACTIVITY_EVENTS.forEach((eventName) => window.removeEventListener(eventName, handleActivity));
|
||||
window.removeEventListener('storage', handleStorage);
|
||||
window.removeEventListener('pageshow', handlePageShow);
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, [queryClient, dispatch]);
|
||||
};
|
||||
|
||||
export default useInactivityLogout;
|
||||
Reference in New Issue
Block a user