feat: auto-logout after 1 hour of inactivity
Tracks user activity events (mouse, keyboard, scroll, touch) and resets a 60-minute idle timer on each event. Shows a warning toast at 55 minutes, then calls logoutMutation at 60 minutes to clear the session. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { createContext, ReactNode, useContext } from "react";
|
import { createContext, ReactNode, useContext, useEffect, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
useQuery,
|
useQuery,
|
||||||
useMutation,
|
useMutation,
|
||||||
@@ -131,6 +131,51 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const IDLE_TIMEOUT = 60 * 60 * 1000;
|
||||||
|
const WARN_BEFORE = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
const logoutTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
const warnTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
const warnedRef = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
const clearTimers = () => {
|
||||||
|
if (logoutTimer.current) clearTimeout(logoutTimer.current);
|
||||||
|
if (warnTimer.current) clearTimeout(warnTimer.current);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetTimers = () => {
|
||||||
|
clearTimers();
|
||||||
|
warnedRef.current = false;
|
||||||
|
|
||||||
|
warnTimer.current = setTimeout(() => {
|
||||||
|
if (!warnedRef.current) {
|
||||||
|
warnedRef.current = true;
|
||||||
|
toast({
|
||||||
|
title: "Session expiring soon",
|
||||||
|
description: "You will be logged out in 5 minutes due to inactivity.",
|
||||||
|
duration: 10000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, IDLE_TIMEOUT - WARN_BEFORE);
|
||||||
|
|
||||||
|
logoutTimer.current = setTimeout(() => {
|
||||||
|
logoutMutation.mutate();
|
||||||
|
}, IDLE_TIMEOUT);
|
||||||
|
};
|
||||||
|
|
||||||
|
const events = ["mousemove", "mousedown", "keydown", "scroll", "touchstart", "click"];
|
||||||
|
events.forEach((e) => window.addEventListener(e, resetTimers, { passive: true }));
|
||||||
|
resetTimers();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimers();
|
||||||
|
events.forEach((e) => window.removeEventListener(e, resetTimers));
|
||||||
|
};
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthContext.Provider
|
<AuthContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|||||||
Reference in New Issue
Block a user