408 lines
13 KiB
JavaScript
408 lines
13 KiB
JavaScript
/**
|
|
* 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: <Name>")
|
|
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);
|
|
})();
|
|
|