manage-your-printer/static/js/session-manager.min.js
2025-06-04 10:03:22 +02:00

29 lines
10 KiB
JavaScript

class SessionManager{constructor(){this.isAuthenticated=false;this.maxInactiveMinutes=30;this.heartbeatInterval=5*60*1000;this.warningTime=5*60*1000;this.checkInterval=30*1000;this.heartbeatTimer=null;this.statusCheckTimer=null;this.warningShown=false;this.sessionWarningModal=null;this.init();}
async init(){try{await this.checkAuthenticationStatus();if(this.isAuthenticated){this.startSessionMonitoring();this.createWarningModal();console.log('🔐 Session Manager gestartet');console.log(`📊 Max Inaktivität:${this.maxInactiveMinutes}Minuten`);console.log(`💓 Heartbeat Intervall:${this.heartbeatInterval/1000/60}Minuten`);}else{console.log('👤 Benutzer nicht angemeldet - Session Manager inaktiv');}}catch(error){console.error('❌ Session Manager Initialisierung fehlgeschlagen:',error);}}
async checkAuthenticationStatus(){try{const response=await fetch('/api/session/status',{method:'GET',headers:{'Content-Type':'application/json','X-Requested-With':'XMLHttpRequest'}});if(response.ok){const data=await response.json();if(data.success){this.isAuthenticated=true;this.maxInactiveMinutes=data.session.max_inactive_minutes;console.log('✅ Session Status:',{user:data.user.email,timeLeft:Math.floor(data.session.time_left_seconds/60)+' Minuten',lastActivity:new Date(data.session.last_activity).toLocaleString('de-DE')});return data;}}else if(response.status===401){this.isAuthenticated=false;this.handleSessionExpired('Authentication check failed');}}catch(error){console.error('❌ Fehler beim Prüfen des Session-Status:',error);this.isAuthenticated=false;}
return null;}
startSessionMonitoring(){this.heartbeatTimer=setInterval(()=>{this.sendHeartbeat();},this.heartbeatInterval);this.statusCheckTimer=setInterval(()=>{this.checkSessionStatus();},this.checkInterval);setTimeout(()=>this.sendHeartbeat(),1000);}
async sendHeartbeat(){try{const csrfToken=document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');const headers={'Content-Type':'application/json','X-Requested-With':'XMLHttpRequest'};if(csrfToken){headers['X-CSRFToken']=csrfToken;}
const response=await fetch('/api/session/heartbeat',{method:'POST',headers:headers,body:JSON.stringify({timestamp:new Date().toISOString(),page:window.location.pathname,csrf_token:csrfToken})});if(response.ok){const data=await response.json();if(data.success){console.log('💓 Heartbeat gesendet - Session aktiv:',Math.floor(data.time_left_seconds/60)+' Minuten verbleibend');}else{console.warn('⚠️ Heartbeat fehlgeschlagen:',data);}}else if(response.status===401){this.handleSessionExpired('Heartbeat failed - unauthorized');}else if(response.status===400){console.warn('⚠️ CSRF-Token Problem beim Heartbeat - versuche Seite neu zu laden');setTimeout(()=>location.reload(),5000);}}catch(error){console.error('❌ Heartbeat-Fehler:',error);}}
async checkSessionStatus(){try{const sessionData=await this.checkAuthenticationStatus();if(sessionData&&sessionData.session){const timeLeftSeconds=sessionData.session.time_left_seconds;const timeLeftMinutes=Math.floor(timeLeftSeconds/60);if(timeLeftSeconds<=this.warningTime/1000&&timeLeftSeconds>0){if(!this.warningShown){this.showSessionWarning(timeLeftMinutes);this.warningShown=true;}}else if(timeLeftSeconds<=0){this.handleSessionExpired('Session time expired');}else{this.warningShown=false;this.hideSessionWarning();}
this.updateSessionStatusDisplay(sessionData);}}catch(error){console.error('❌ Session-Status-Check fehlgeschlagen:',error);}}
showSessionWarning(minutesLeft){this.hideSessionWarning();this.showToast('Session läuft ab',`Ihre Session läuft in ${minutesLeft}Minuten ab.Möchten Sie verlängern?`,'warning',10000,[{text:'Verlängern',action:()=>this.extendSession()},{text:'Abmelden',action:()=>this.logout()}]);if(this.sessionWarningModal){this.sessionWarningModal.show();this.updateWarningModal(minutesLeft);}
console.log(`⚠️ Session-Warnung:${minutesLeft}Minuten verbleibend`);}
hideSessionWarning(){if(this.sessionWarningModal){this.sessionWarningModal.hide();}}
createWarningModal(){const modalHTML=`<div id="sessionWarningModal"class="fixed inset-0 z-50 hidden overflow-y-auto"aria-labelledby="modal-title"role="dialog"aria-modal="true"><div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"><div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"></div><div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"><div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"><div class="sm:flex sm:items-start"><div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10"><svg class="h-6 w-6 text-red-600"fill="none"viewBox="0 0 24 24"stroke="currentColor"><path stroke-linecap="round"stroke-linejoin="round"stroke-width="2"d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L3.314 16.5c-.77.833.192 2.5 1.732 2.5z"/></svg></div><div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"><h3 class="text-lg leading-6 font-medium text-gray-900"id="modal-title">Session läuft ab</h3><div class="mt-2"><p class="text-sm text-gray-500"id="warningMessage">Ihre Session läuft in<span id="timeRemaining"class="font-bold text-red-600">5</span>Minuten ab.</p><p class="text-sm text-gray-500 mt-2">Möchten Sie Ihre Session verlängern oder sich abmelden?</p></div></div></div></div><div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"><button type="button"id="extendSessionBtn"class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">Session verlängern</button><button type="button"id="logoutBtn"class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">Abmelden</button></div></div></div></div>`;document.body.insertAdjacentHTML('beforeend',modalHTML);document.getElementById('extendSessionBtn').addEventListener('click',()=>{this.extendSession();this.hideSessionWarning();});document.getElementById('logoutBtn').addEventListener('click',()=>{this.logout();});this.sessionWarningModal={element:document.getElementById('sessionWarningModal'),show:()=>{document.getElementById('sessionWarningModal').classList.remove('hidden');},hide:()=>{document.getElementById('sessionWarningModal').classList.add('hidden');}};}
updateWarningModal(minutesLeft){const timeElement=document.getElementById('timeRemaining');if(timeElement){timeElement.textContent=minutesLeft;}}
async extendSession(extendMinutes=30){try{const response=await fetch('/api/session/extend',{method:'POST',headers:{'Content-Type':'application/json','X-Requested-With':'XMLHttpRequest'},body:JSON.stringify({extend_minutes:extendMinutes})});if(response.ok){const data=await response.json();if(data.success){this.warningShown=false;this.showToast('Session verlängert',`Ihre Session wurde um ${data.extended_minutes}Minuten verlängert`,'success',5000);console.log('✅ Session verlängert:',data);}else{this.showToast('Fehler','Session konnte nicht verlängert werden','error');}}else if(response.status===401){this.handleSessionExpired('Extend session failed - unauthorized');}}catch(error){console.error('❌ Session-Verlängerung fehlgeschlagen:',error);this.showToast('Fehler','Session-Verlängerung fehlgeschlagen','error');}}
async logout(){try{this.stopSessionMonitoring();const response=await fetch('/auth/logout',{method:'POST',headers:{'Content-Type':'application/json','X-Requested-With':'XMLHttpRequest'}});if(response.ok){window.location.href='/auth/login';}else{window.location.href='/auth/login';}}catch(error){console.error('❌ Logout-Fehler:',error);window.location.href='/auth/login';}}
handleSessionExpired(reason){console.log('🕒 Session abgelaufen:',reason);this.stopSessionMonitoring();this.isAuthenticated=false;this.showToast('Session abgelaufen','Sie wurden automatisch abgemeldet. Bitte melden Sie sich erneut an.','warning',8000);setTimeout(()=>{window.location.href='/auth/login?reason=session_expired';},2000);}
stopSessionMonitoring(){if(this.heartbeatTimer){clearInterval(this.heartbeatTimer);this.heartbeatTimer=null;}
if(this.statusCheckTimer){clearInterval(this.statusCheckTimer);this.statusCheckTimer=null;}
console.log('🛑 Session-Monitoring gestoppt');}
updateSessionStatusDisplay(sessionData){const statusElement=document.getElementById('sessionStatus');if(statusElement){const timeLeftMinutes=Math.floor(sessionData.session.time_left_seconds/60);statusElement.textContent=`Session:${timeLeftMinutes}min`;if(timeLeftMinutes<=5){statusElement.className='text-red-600 font-medium';}else if(timeLeftMinutes<=10){statusElement.className='text-yellow-600 font-medium';}else{statusElement.className='text-green-600 font-medium';}}}
showToast(title,message,type='info',duration=5000,actions=[]){if(window.showToast){window.showToast(message,type,duration);return;}
if(type==='error'||type==='warning'){alert(`${title}:${message}`);}else{console.log(`${title}:${message}`);}}
isLoggedIn(){return this.isAuthenticated;}
start(){if(!this.heartbeatTimer&&this.isAuthenticated){this.startSessionMonitoring();}}
stop(){this.stopSessionMonitoring();}
async extend(minutes=30){return await this.extendSession(minutes);}
async logoutUser(){return await this.logout();}}
document.addEventListener('DOMContentLoaded',()=>{if(!window.location.pathname.includes('/auth/login')){window.sessionManager=new SessionManager();window.addEventListener('beforeunload',()=>{if(window.sessionManager){window.sessionManager.stop();}});document.addEventListener('visibilitychange',()=>{if(window.sessionManager&&window.sessionManager.isLoggedIn()){if(document.hidden){console.log('🙈 Tab versteckt - Session-Monitoring reduziert');}else{console.log('👁️ Tab sichtbar - Session-Check');setTimeout(()=>window.sessionManager.checkSessionStatus(),1000);}}});}});window.SessionManager=SessionManager;