feat: implement next redirect flow, remove inactivity auto-logout, and add concurrent session termination notification
All checks were successful
Staging Build / build (push) Successful in 2m14s
All checks were successful
Staging Build / build (push) Successful in 2m14s
This commit is contained in:
@@ -195,7 +195,7 @@ export function NavbarClient({ user, role = "partner" }: NavbarClientProps) {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Button asChild className="bg-primary hover:bg-primary/95 text-white dark:text-blue-500">
|
<Button asChild className="bg-primary hover:bg-primary/95 text-white dark:text-blue-500">
|
||||||
<Link href="/login">Anmelden</Link>
|
<Link href={`/auth/login?next=${typeof window !== 'undefined' ? window.location.pathname : '/'}`}>Anmelden</Link>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
@@ -285,7 +285,7 @@ export function NavbarClient({ user, role = "partner" }: NavbarClientProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button asChild className="w-full bg-primary hover:bg-primary/95 text-white dark:text-blue-500" onClick={() => setIsMobileMenuOpen(false)}>
|
<Button asChild className="w-full bg-primary hover:bg-primary/95 text-white dark:text-blue-500" onClick={() => setIsMobileMenuOpen(false)}>
|
||||||
<Link href="/login">Anmelden</Link>
|
<Link href={`/auth/login?next=${typeof window !== 'undefined' ? window.location.pathname : '/'}`}>Anmelden</Link>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,20 +25,7 @@ export function InactivityTracker() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const INACTIVITY_LIMIT = 5 * 60 * 1000; // 5 Minuten in ms
|
// Regelmäßige Überprüfung der Session-Gültigkeit (z.B. wegen Login auf anderem Browser/Gerät)
|
||||||
|
|
||||||
const updateActivity = () => {
|
|
||||||
localStorage.setItem("last_activity", Date.now().toString());
|
|
||||||
};
|
|
||||||
|
|
||||||
// Events zum Tracken der Benutzerinteraktion
|
|
||||||
const events = ["mousemove", "keydown", "mousedown", "touchstart", "scroll", "click"];
|
|
||||||
events.forEach((event) => window.addEventListener(event, updateActivity));
|
|
||||||
|
|
||||||
// Aktivitätszeitstempel beim Mounten initialisieren
|
|
||||||
updateActivity();
|
|
||||||
|
|
||||||
// Regelmäßige Überprüfung der Inaktivität
|
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
const { data: { session } } = await supabase.auth.getSession();
|
const { data: { session } } = await supabase.auth.getSession();
|
||||||
if (!session) return; // Nicht eingeloggt, keine Prüfung nötig
|
if (!session) return; // Nicht eingeloggt, keine Prüfung nötig
|
||||||
@@ -49,32 +36,15 @@ export function InactivityTracker() {
|
|||||||
try {
|
try {
|
||||||
await signOut();
|
await signOut();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Fehler beim Inactivity-Server-Signout:", e);
|
console.error("Fehler beim Server-Signout nach Session-Verlust:", e);
|
||||||
}
|
}
|
||||||
await supabase.auth.signOut();
|
await supabase.auth.signOut();
|
||||||
localStorage.removeItem("last_activity");
|
router.push("/auth/login?message=concurrent");
|
||||||
router.push("/");
|
|
||||||
router.refresh();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lastActivity = Number(localStorage.getItem("last_activity") || Date.now());
|
|
||||||
if (Date.now() - lastActivity > INACTIVITY_LIMIT) {
|
|
||||||
// Bei Überschreitung abmelden
|
|
||||||
try {
|
|
||||||
await signOut();
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Fehler beim Inactivity-Server-Signout:", e);
|
|
||||||
}
|
|
||||||
await supabase.auth.signOut();
|
|
||||||
localStorage.removeItem("last_activity");
|
|
||||||
router.push("/");
|
|
||||||
router.refresh();
|
router.refresh();
|
||||||
}
|
}
|
||||||
}, 5000); // Prüfung alle 5 Sekunden
|
}, 5000); // Prüfung alle 5 Sekunden
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
events.forEach((event) => window.removeEventListener(event, updateActivity));
|
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
};
|
};
|
||||||
}, [supabase, router]);
|
}, [supabase, router]);
|
||||||
|
|||||||
@@ -90,6 +90,17 @@ export function LoginForm({
|
|||||||
onChange={(e) => setPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{(() => {
|
||||||
|
const messageParam = typeof window !== 'undefined' ? new URLSearchParams(window.location.search).get('message') : null;
|
||||||
|
if (messageParam === "concurrent") {
|
||||||
|
return (
|
||||||
|
<p className="text-sm text-amber-500 bg-amber-500/10 border border-amber-500/20 p-3 rounded-lg text-center font-medium">
|
||||||
|
Sie wurden abgemeldet, da Sie sich an einem anderen Gerät angemeldet haben.
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})()}
|
||||||
{error && <p className="text-sm text-red-500">{error}</p>}
|
{error && <p className="text-sm text-red-500">{error}</p>}
|
||||||
<Button type="submit" className="w-full" disabled={isLoading}>
|
<Button type="submit" className="w-full" disabled={isLoading}>
|
||||||
{isLoading ? "Logging in..." : "Login"}
|
{isLoading ? "Logging in..." : "Login"}
|
||||||
|
|||||||
Reference in New Issue
Block a user