Admin User nach einer Zeit von einer Stunde löschen (Cookie oder Local Storrage) , automatisch abmelden

This commit is contained in:
ISA
2025-09-08 07:08:59 +02:00
parent c03802e97f
commit 22321a7ac9
7 changed files with 80 additions and 9 deletions

View File

@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
NEXT_PUBLIC_EXPORT_STATIC=false NEXT_PUBLIC_EXPORT_STATIC=false
NEXT_PUBLIC_USE_CGI=false NEXT_PUBLIC_USE_CGI=false
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.855 NEXT_PUBLIC_APP_VERSION=1.6.856
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter) NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)

View File

@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
NEXT_PUBLIC_EXPORT_STATIC=true NEXT_PUBLIC_EXPORT_STATIC=true
NEXT_PUBLIC_USE_CGI=true NEXT_PUBLIC_USE_CGI=true
# App-Versionsnummer # App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.6.855 NEXT_PUBLIC_APP_VERSION=1.6.856
NEXT_PUBLIC_CPL_MODE=production NEXT_PUBLIC_CPL_MODE=production

View File

@@ -1,3 +1,8 @@
## [1.6.856] 2025-09-08
- chore: Jenkinsfile
---
## [1.6.855] 2025-09-05 ## [1.6.855] 2025-09-05
- fix: allow scripts in woodpecker - fix: allow scripts in woodpecker

View File

@@ -1,5 +1,5 @@
"use client"; // components/Header.jsx "use client"; // components/Header.jsx
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useRef, useCallback } from "react";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import Image from "next/image"; import Image from "next/image";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@@ -15,16 +15,18 @@ function Header() {
const router = useRouter(); const router = useRouter();
const [showSettingsModal, setShowSettingsModal] = useState(false); const [showSettingsModal, setShowSettingsModal] = useState(false);
const [isAdminLoggedIn, setIsAdminLoggedIn] = useState(false); const [isAdminLoggedIn, setIsAdminLoggedIn] = useState(false);
const autoLogoutTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
// Removed duplicate declaration of deviceName // Removed duplicate declaration of deviceName
const handleCloseSettingsModal = () => setShowSettingsModal(false); const handleCloseSettingsModal = () => setShowSettingsModal(false);
const handleLogout = () => { const handleLogout = useCallback(() => {
sessionStorage.removeItem("token"); // Token entfernen sessionStorage.removeItem("token"); // Token entfernen
localStorage.setItem("isAdminLoggedIn", "false"); // Admin-Status entfernen localStorage.setItem("isAdminLoggedIn", "false"); // Admin-Status entfernen
localStorage.removeItem("adminLoginTime"); // Login-Zeitpunkt entfernen
setIsAdminLoggedIn(false); // Zustand sofort aktualisieren setIsAdminLoggedIn(false); // Zustand sofort aktualisieren
router.push("/offline.html"); // Weiterleitung router.push("/offline.html"); // Weiterleitung
}; }, [router]);
useEffect(() => { useEffect(() => {
// Initialer Check beim Laden der Komponente // Initialer Check beim Laden der Komponente
@@ -43,6 +45,56 @@ function Header() {
clearInterval(interval); // Intervall stoppen, wenn die Komponente entladen wird clearInterval(interval); // Intervall stoppen, wenn die Komponente entladen wird
}; };
}, [isAdminLoggedIn]); }, [isAdminLoggedIn]);
// Auto-Logout nach 1 Minute (Test): nutzt adminLoginTime aus localStorage
useEffect(() => {
// Timer bereinigen, wenn sich der Status ändert
if (autoLogoutTimerRef.current) {
clearTimeout(autoLogoutTimerRef.current);
autoLogoutTimerRef.current = null;
}
if (!isAdminLoggedIn) return;
const iso = localStorage.getItem("adminLoginTime");
const loginTime = iso ? new Date(iso).getTime() : Date.now();
if (!iso) {
// Falls älterer Login ohne Zeitstempel, setze jetzt
try {
localStorage.setItem(
"adminLoginTime",
new Date(loginTime).toISOString()
);
} catch {
void 0; // ignore write errors (e.g., storage disabled)
}
}
// 1 Minute ab Login (60_000 ms), eine Stunde (3_600_000 ms) im Produktivbetrieb
const target = loginTime + 3_600_000;
const delay = Math.max(0, target - Date.now());
// Fallback: wenn Datum in Vergangenheit (z.B. Uhrzeit geändert), sofort abmelden
autoLogoutTimerRef.current = setTimeout(() => {
// Versuche den Button zu klicken, falls vorhanden
const btn = document.querySelector<HTMLButtonElement>(
'button[aria-label="Abmelden"]'
);
if (btn) {
btn.click();
} else {
// Fallback direkt
handleLogout();
}
}, delay);
return () => {
if (autoLogoutTimerRef.current) {
clearTimeout(autoLogoutTimerRef.current);
autoLogoutTimerRef.current = null;
}
};
}, [isAdminLoggedIn, handleLogout]);
//---------------------------------------------------------------- //----------------------------------------------------------------
const dispatch = useDispatch<AppDispatch>(); const dispatch = useDispatch<AppDispatch>();
@@ -139,6 +191,7 @@ function Header() {
<div className="flex items-center justify-end w-1/4 space-x-1"> <div className="flex items-center justify-end w-1/4 space-x-1">
<button <button
onClick={handleLogout} onClick={handleLogout}
aria-label="Abmelden"
className="bg-littwin-blue text-white px-4 py-2 rounded" className="bg-littwin-blue text-white px-4 py-2 rounded"
> >
Abmelden Abmelden

View File

@@ -22,6 +22,12 @@ const UserManagementSettings: React.FC = () => {
() => { () => {
setLoginSuccess(true); setLoginSuccess(true);
setError(""); setError("");
// Speichere die System-Uhrzeit (Login-Zeitpunkt) im localStorage
try {
localStorage.setItem("adminLoginTime", new Date().toISOString());
} catch {
// Ignoriere Speicherfehler (z. B. in Private Mode)
}
}, },
(errorMsg) => { (errorMsg) => {
setLoginSuccess(false); setLoginSuccess(false);
@@ -47,7 +53,14 @@ const UserManagementSettings: React.FC = () => {
<button <button
type="button" type="button"
className="bg-littwin-blue text-white px-4 py-2 h-8 text-xs rounded whitespace-nowrap" className="bg-littwin-blue text-white px-4 py-2 h-8 text-xs rounded whitespace-nowrap"
onClick={logoutAdmin} onClick={() => {
try {
localStorage.removeItem("adminLoginTime");
} catch {
// ignore
}
logoutAdmin();
}}
> >
Admin abmelden Admin abmelden
</button> </button>

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.855", "version": "1.6.856",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.855", "version": "1.6.856",
"dependencies": { "dependencies": {
"@fontsource/roboto": "^5.1.0", "@fontsource/roboto": "^5.1.0",
"@headlessui/react": "^2.2.4", "@headlessui/react": "^2.2.4",

View File

@@ -1,6 +1,6 @@
{ {
"name": "cpl-v4", "name": "cpl-v4",
"version": "1.6.855", "version": "1.6.856",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 3000", "dev": "next dev -p 3000",