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 {
|
||||
useQuery,
|
||||
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 (
|
||||
<AuthContext.Provider
|
||||
value={{
|
||||
|
||||
Reference in New Issue
Block a user