/** * Benutzer-Authentifizierung und Account-Verwaltung. * Verwaltet den Login-Status über den LocalStorage, steuert die Anzeige im Header, * verarbeitet Login- und Registrierungsformulare und ermöglicht das Löschen des Kontos. */ (function () { // Der Schlüssel, unter dem die Benutzerdaten im LocalStorage abgelegt werden. const AUTH_STORAGE_KEY = "loremIpsumAuth"; /** * Liest die aktuellen Anmeldedaten aus dem LocalStorage des Browsers. * @returns {Object|null} Ein Objekt mit {username, password} oder null, falls nicht angemeldet oder ungültig. */ function readAuth() { const raw = localStorage.getItem(AUTH_STORAGE_KEY); if (!raw) { return null; } try { const parsed = JSON.parse(raw); // Validieren, dass die Pflichtfelder vorhanden sind if (!parsed.username || !parsed.password) { return null; } return parsed; } catch { // Fehler beim JSON-Parsen (z.B. manipulierte Daten) -> als nicht angemeldet behandeln return null; } } /** * Speichert die Benutzerdaten verschlüsselt als JSON-String im LocalStorage. * @param {string} username - Der Benutzername. * @param {string} password - Das generierte/eingegebene Passwort. */ function saveAuth(username, password) { localStorage.setItem( AUTH_STORAGE_KEY, JSON.stringify({ username: username, password: password }), ); } /** * Entfernt die Anmeldedaten aus dem LocalStorage (Logout). */ function clearAuth() { localStorage.removeItem(AUTH_STORAGE_KEY); } /** * Aktualisiert die Anzeige des Benutzernamens im Header und den Login-Button. */ function updateHeaderUsername() { const usernameDisplay = document.getElementById("username-display"); const navbarLogin = document.getElementById("navbar-login"); const auth = readAuth(); // Text im Header anpassen ("User: Guest" oder "User: ") if (usernameDisplay) { usernameDisplay.textContent = auth ? "User: " + auth.username : "User: Guest"; } // Text des Login-Links in der Navbar anpassen if (navbarLogin) { navbarLogin.textContent = auth ? auth.username : "Login / Registrieren"; } } /** * Zeigt dem Benutzer Feedback (z. B. Fehlermeldungen) auf der Login-Seite an. * @param {string} message - Die anzuzeigende Nachricht. * @param {string} type - Der Bootstrap-Alert-Typ (danger, warning, success, info). */ function setFeedback(message, type) { const feedback = document.getElementById("auth-feedback"); if (!feedback) { return; } feedback.className = "alert alert-" + type; feedback.textContent = message; feedback.classList.remove("d-none"); // Alert einblenden } /** * Aktualisiert den Zustand der Session-Box (Anzeige der aktuellen Anmeldung). * Blendet die Forms aus bzw. ein und aktiviert/deaktiviert die Buttons. */ function updateSessionBox() { const sessionText = document.getElementById("current-session-text"); const logoutButton = document.getElementById("logout-button"); const deleteAccountButton = document.getElementById("delete-account-button"); const currentSessionBox = document.getElementById("current-session-box"); const authFormsRow = document.getElementById("auth-forms-row"); if (!sessionText || !logoutButton || !deleteAccountButton || !currentSessionBox || !authFormsRow) { return; } const auth = readAuth(); if (auth) { // Wenn eingeloggt: Session-Info anzeigen und Buttons aktivieren sessionText.textContent = "Eingeloggt als " + auth.username + "."; logoutButton.disabled = false; deleteAccountButton.disabled = false; currentSessionBox.classList.remove("d-none"); authFormsRow.classList.remove("d-none"); } else { // Wenn nicht eingeloggt: Info setzen und Session-Box verbergen sessionText.textContent = "Nicht eingeloggt."; logoutButton.disabled = true; deleteAccountButton.disabled = true; currentSessionBox.classList.add("d-none"); authFormsRow.classList.remove("d-none"); } } /** * Hilfsfunktion zum Instanziieren des UserService. * @returns {UserService|null} Eine UserService-Instanz oder null. */ function getUserService() { if (!window.config || !window.UserService) { return null; } return new window.UserService(window.config); } /** * Behandelt das Absenden des Login-Formulars. * Authentifiziert den Benutzer beim Backend und speichert die Session bei Erfolg. * @param {Event} event - Das Submit-Event des Formulars. */ async function handleLoginSubmit(event) { event.preventDefault(); const userService = getUserService(); if (!userService) { setFeedback("User-Service konnte nicht geladen werden.", "danger"); return; } const usernameInput = document.getElementById("login-username"); const passwordInput = document.getElementById("login-password"); const submitButton = event.submitter; // Der geklickte Button const username = usernameInput.value.trim(); const password = passwordInput.value.trim(); if (!username || !password) { setFeedback("Bitte Username und Passwort eingeben.", "warning"); return; } // Button während der Anfrage sperren und Ladeindikator zeigen if (submitButton) { submitButton.disabled = true; submitButton.textContent = "Einloggen..."; } let result; try { result = await userService.getUser(username, password); } catch (error) { console.error("Login fehlgeschlagen:", error); setFeedback("Login fehlgeschlagen: Backend ist nicht erreichbar.", "danger"); if (submitButton) { submitButton.disabled = false; submitButton.textContent = "Einloggen"; } return; } // Button wieder freigeben if (submitButton) { submitButton.disabled = false; submitButton.textContent = "Einloggen"; } if (result.ok) { // Login erfolgreich: Daten speichern, Ansicht aktualisieren und zur Startseite leiten saveAuth(username, password); setFeedback("Login erfolgreich.", "success"); updateSessionBox(); updateHeaderUsername(); // Falls das Navigationsmenü geöffnet ist, dessen Status aktualisieren if (typeof window.updateMessagesNavState === "function") { window.updateMessagesNavState(); } // Kurze Verzögerung für visuelles Feedback vor dem Seitenwechsel setTimeout(function() { if (typeof window.loadPage === "function") { window.loadPage("home", "nav-home"); } }, 500); return; } if (result.status === 401) { setFeedback("Login fehlgeschlagen: Username oder Passwort ist falsch.", "danger"); return; } setFeedback("Login fehlgeschlagen (Status " + result.status + ").", "danger"); } /** * Behandelt das Absenden des Registrierungsformulars. * Sendet den gewünschten Benutzernamen ans Backend, welches das Passwort generiert. * Zeigt das Passwort anschließend in einem Bootstrap-Modal an, da es nur einmalig sichtbar ist. * @param {Event} event - Das Submit-Event des Formulars. */ async function handleRegisterSubmit(event) { event.preventDefault(); const userService = getUserService(); if (!userService) { setFeedback("User-Service konnte nicht geladen werden.", "danger"); return; } const usernameInput = document.getElementById("register-username"); const username = usernameInput.value.trim(); if (!username) { setFeedback("Bitte einen Username eingeben.", "warning"); return; } const result = await userService.postUser(username); if (result.ok && result.body) { // Registrierung erfolgreich: Antwortdaten auslesen const createdName = result.body.name || username; const createdPassword = result.body.password || ""; // Direkt einloggen mit den erhaltenen Daten saveAuth(createdName, createdPassword); updateSessionBox(); updateHeaderUsername(); if (typeof window.updateMessagesNavState === "function") { window.updateMessagesNavState(); } // Modal mit den generierten Zugangsdaten befüllen const modalUsername = document.getElementById("modal-username"); const modalPassword = document.getElementById("modal-password"); if (modalUsername) modalUsername.textContent = createdName; if (modalPassword) modalPassword.textContent = createdPassword; // Das Passwort-Modal anzeigen const passwordModalElement = document.getElementById("password-modal"); if (passwordModalElement) { const passwordModal = new window.bootstrap.Modal(passwordModalElement); // Nach Schließen des Modals automatisch auf die Startseite weiterleiten passwordModalElement.addEventListener("hidden.bs.modal", function handleClose() { if (typeof window.loadPage === "function") { window.loadPage("home", "nav-home"); } passwordModalElement.removeEventListener("hidden.bs.modal", handleClose); }); passwordModal.show(); } else { // Fallback, falls das Bootstrap-Modal im DOM nicht gefunden wurde setFeedback( "Account erstellt. Username: " + createdName + ", Passwort: " + createdPassword, "success", ); setTimeout(function() { if (typeof window.loadPage === "function") { window.loadPage("home", "nav-home"); } }, 1500); } // Formularfelder für eventuelle spätere Logins vorausfüllen const loginUsernameInput = document.getElementById("login-username"); const loginPasswordInput = document.getElementById("login-password"); if (loginUsernameInput && loginPasswordInput) { loginUsernameInput.value = createdName; loginPasswordInput.value = createdPassword; } return; } // Fehlerbehandlung if (result.status === 400) { const errorMessage = result.body && result.body.message ? result.body.message : "Dieser Username existiert bereits."; setFeedback(errorMessage, "danger"); return; } setFeedback( "Account konnte nicht erstellt werden (Status " + result.status + ").", "danger", ); } /** * Loggt den aktuellen Benutzer aus (löscht Auth-Daten aus LocalStorage und aktualisiert UI). */ function handleLogout() { clearAuth(); setFeedback("Du wurdest ausgeloggt.", "info"); updateSessionBox(); updateHeaderUsername(); if (typeof window.updateMessagesNavState === "function") { window.updateMessagesNavState(); } } /** * Behandelt das Löschen des eigenen Accounts. * Fordert eine Sicherheitsbestätigung an, sendet die Löschanfrage ans Backend * und führt bei Erfolg einen automatischen Logout aus. */ async function handleDeleteAccount() { const auth = readAuth(); if (!auth) { setFeedback("Du bist nicht eingeloggt.", "warning"); return; } // Sicherheitsabfrage im Browser const wantsDelete = window.confirm( "Möchtest du den Account \"" + auth.username + "\" wirklich löschen?", ); if (!wantsDelete) { return; } const userService = getUserService(); if (!userService) { setFeedback("User-Service konnte nicht geladen werden.", "danger"); return; } const result = await userService.deleteUser(auth.username, auth.password); if (result.ok) { // Account erfolgreich gelöscht: Lokal ausloggen und Feedback geben clearAuth(); updateSessionBox(); updateHeaderUsername(); if (typeof window.updateMessagesNavState === "function") { window.updateMessagesNavState(); } setFeedback("Account wurde gelöscht.", "success"); return; } if (result.status === 401) { setFeedback("Account konnte nicht gelöscht werden: nicht autorisiert.", "danger"); return; } setFeedback( "Account konnte nicht gelöscht werden (Status " + result.status + ").", "danger", ); } /** * Initialisiert die Login-Seite. * Bindet alle Event-Listener an die Formulare und Buttons nach dem Laden des HTML-Inhalts. */ function initLoginPage() { const loginForm = document.getElementById("login-form"); const registerForm = document.getElementById("register-form"); const logoutButton = document.getElementById("logout-button"); const deleteAccountButton = document.getElementById("delete-account-button"); if (!loginForm || !registerForm || !logoutButton || !deleteAccountButton) { return; } loginForm.addEventListener("submit", handleLoginSubmit); registerForm.addEventListener("submit", handleRegisterSubmit); logoutButton.addEventListener("click", handleLogout); deleteAccountButton.addEventListener("click", handleDeleteAccount); // Initialen UI-Zustand herstellen updateSessionBox(); updateHeaderUsername(); } // Bindet die Initialisierungsfunktion an das globale Fensterobjekt für navigation.js window.initLoginPage = initLoginPage; // Stellt Authentifizierungsfunktionen global bereit, damit andere Module (z. B. play.js) // prüfen können, ob und wer eingeloggt ist. window.AppAuth = { getAuth: readAuth, clearAuth: clearAuth, }; // Beim allerersten Laden der Anwendung direkt den Header anpassen document.addEventListener("DOMContentLoaded", updateHeaderUsername); })();