From fd116db1325987585a688525fc677fa8a42a93c4 Mon Sep 17 00:00:00 2001 From: Cay Date: Fri, 13 Mar 2026 13:22:52 +0000 Subject: [PATCH] =?UTF-8?q?Mehrfachlogin=20nicht=20mehr=20m=C3=B6glich?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware/auth.js | 31 ++++++++ public/js/building.js | 11 ++- public/js/map-ui.js | 150 +++++++++++++++++++------------------ routes/buildings.js | 15 ++-- routes/launcher.js | 13 ++-- routes/login.js | 33 ++++++-- views/buildings/castle.ejs | 19 ----- views/buildings/church.ejs | 7 -- views/buildings/market.ejs | 7 -- views/buildings/portal.ejs | 7 -- views/buildings/tower.ejs | 7 -- 11 files changed, 157 insertions(+), 143 deletions(-) create mode 100644 middleware/auth.js delete mode 100644 views/buildings/castle.ejs delete mode 100644 views/buildings/church.ejs delete mode 100644 views/buildings/market.ejs delete mode 100644 views/buildings/portal.ejs delete mode 100644 views/buildings/tower.ejs diff --git a/middleware/auth.js b/middleware/auth.js new file mode 100644 index 0000000..88aebf3 --- /dev/null +++ b/middleware/auth.js @@ -0,0 +1,31 @@ +const db = require("../database/database"); + +async function auth(req, res, next) { + if (!req.session.user) { + return res.redirect("/"); + } + + try { + const [rows] = await db.query( + "SELECT session_token FROM accounts WHERE id = ?", + [req.session.user.id], + ); + + if (!rows.length) { + req.session.destroy(); + return res.redirect("/"); + } + + if (rows[0].session_token !== req.session.user.token) { + req.session.destroy(); + return res.redirect("/"); + } + + next(); + } catch (error) { + console.error(error); + res.redirect("/"); + } +} + +module.exports = auth; diff --git a/public/js/building.js b/public/js/building.js index f3f7844..346664b 100644 --- a/public/js/building.js +++ b/public/js/building.js @@ -1,5 +1,10 @@ fetch("/api/buildings") - .then((res) => res.json()) + .then((res) => { + if (!res.ok) { + throw new Error("API Fehler"); + } + return res.json(); + }) .then((buildings) => { buildings.forEach((building) => { const element = document.querySelector( @@ -10,7 +15,6 @@ fetch("/api/buildings") let title = element.querySelector("title"); - // Falls kein title existiert → erstellen if (!title) { title = document.createElementNS("http://www.w3.org/2000/svg", "title"); element.prepend(title); @@ -18,4 +22,7 @@ fetch("/api/buildings") title.textContent = building.name; }); + }) + .catch((error) => { + console.error("Buildings API Fehler:", error); }); diff --git a/public/js/map-ui.js b/public/js/map-ui.js index 465d38b..d6c389a 100644 --- a/public/js/map-ui.js +++ b/public/js/map-ui.js @@ -2,6 +2,10 @@ const popup = document.getElementById("building-popup"); const title = document.getElementById("popup-title"); const tooltip = document.getElementById("map-tooltip"); +/* ================================ + Tabs zurücksetzen +================================ */ + function resetTabs() { document .querySelectorAll(".tab") @@ -10,7 +14,6 @@ function resetTabs() { .querySelectorAll(".tab-content") .forEach((c) => c.classList.remove("active")); - // erster Tab aktiv const firstTab = document.querySelector(".tab"); const firstContent = document.querySelector(".tab-content"); @@ -18,57 +21,67 @@ function resetTabs() { if (firstContent) firstContent.classList.add("active"); } -document.querySelectorAll(".building").forEach((b) => { - b.addEventListener("click", async (e) => { +/* ================================ + Gebäude Popup öffnen +================================ */ + +document.querySelectorAll(".building").forEach((building) => { + building.addEventListener("click", async (e) => { e.preventDefault(); - const name = b.querySelector("title").textContent; - const url = b.getAttribute("href"); + try { + const name = building.querySelector("title")?.textContent || "Gebäude"; + const url = building.getAttribute("href"); - title.innerText = name; + title.innerText = name; - // Position des Gebäudes - const rect = b.getBoundingClientRect(); + popup.style.left = "50%"; + popup.style.top = "50%"; + popup.style.display = "block"; - popup.style.left = "50%"; - popup.style.top = "50%"; + resetTabs(); - popup.style.display = "block"; - resetTabs(); + const res = await fetch("/api" + url); - // AJAX Gebäudedaten laden - const res = await fetch("/api" + url); - const data = await res.json(); + if (!res.ok) throw new Error("API Fehler"); - document.getElementById("tab-info").innerHTML = ` -

${data.name}

-

Level: ${data.level}

-

Punkte: ${data.points} / ${data.nextLevelPoints}

-

${data.description}

-
-
+ const data = await res.json(); + + document.getElementById("tab-info").innerHTML = ` +

${data.name}

+

Level: ${data.level}

+

Punkte: ${data.points} / ${data.nextLevelPoints}

+

${data.description}

+
+
+
-
- `; + `; - document.getElementById("tab-actions").innerHTML = ` - - - `; + document.getElementById("tab-actions").innerHTML = ` + + + `; - document.getElementById("tab-upgrade").innerHTML = ` -

Kosten: ${data.upgradeCost}

- - `; + document.getElementById("tab-upgrade").innerHTML = ` +

Kosten: ${data.upgradeCost}

+ + `; - document.getElementById("tab-history").innerHTML = ` -

${data.history}

- `; + document.getElementById("tab-history").innerHTML = ` +

${data.history}

+ `; + } catch (error) { + console.error("Gebäude konnte nicht geladen werden:", error); + } }); }); -// Tabs +/* ================================ + Tabs wechseln +================================ */ + document.querySelectorAll(".tab").forEach((tab) => { tab.addEventListener("click", () => { document @@ -84,53 +97,42 @@ document.querySelectorAll(".tab").forEach((tab) => { }); }); +/* ================================ + Popup schließen +================================ */ + document.querySelector(".popup-close").onclick = () => { popup.style.display = "none"; }; -async function loadBuilding(buildingId) { - try { - const res = await fetch("/api/building/" + buildingId); - const data = await res.json(); - - document.getElementById("tab-info").innerHTML = ` -

${data.name}

-

Level: ${data.level}

-

Punkte: ${data.points} / ${data.nextLevelPoints}

-

${data.description}

- `; - - document.getElementById("tab-upgrade").innerHTML = ` -

Nächstes Level benötigt:

-

${data.nextLevelPoints} Punkte

-

Kosten: ${data.upgradeCost}

- `; - - document.getElementById("tab-history").innerHTML = ` -

${data.history}

- `; - } catch (err) { - console.error("Fehler beim Laden des Gebäudes:", err); - } -} +/* ================================ + Tooltip +================================ */ document.querySelectorAll(".building").forEach((building) => { building.addEventListener("mouseenter", async (e) => { - const id = building.dataset.id; + try { + const id = building.dataset.id; - const res = await fetch("/api/building/" + id); - const data = await res.json(); + const res = await fetch("/api/building/" + id); - tooltip.innerHTML = ` - ${data.name}
- Level ${data.level}
- Punkte ${data.points}/${data.nextLevelPoints}
-
- Upgrade Kosten:
- ${data.upgradeCost} - `; + if (!res.ok) throw new Error("API Fehler"); - tooltip.style.display = "block"; + const data = await res.json(); + + tooltip.innerHTML = ` + ${data.name}
+ Level ${data.level}
+ Punkte ${data.points}/${data.nextLevelPoints}
+
+ Upgrade Kosten:
+ ${data.upgradeCost} + `; + + tooltip.style.display = "block"; + } catch (err) { + console.error("Tooltip Fehler:", err); + } }); building.addEventListener("mousemove", (e) => { diff --git a/routes/buildings.js b/routes/buildings.js index 1c48ec8..f30893e 100644 --- a/routes/buildings.js +++ b/routes/buildings.js @@ -1,23 +1,28 @@ const express = require("express"); const router = express.Router(); +const auth = require("../middleware/auth"); -router.get("/castle", (req, res) => { +/* ================================ + Gebäude Seiten +================================ */ + +router.get("/castle", auth, (req, res) => { res.render("buildings/castle"); }); -router.get("/market", (req, res) => { +router.get("/market", auth, (req, res) => { res.render("buildings/market"); }); -router.get("/church", (req, res) => { +router.get("/church", auth, (req, res) => { res.render("buildings/church"); }); -router.get("/portal", (req, res) => { +router.get("/portal", auth, (req, res) => { res.render("buildings/portal"); }); -router.get("/tower", (req, res) => { +router.get("/tower", auth, (req, res) => { res.render("buildings/tower"); }); diff --git a/routes/launcher.js b/routes/launcher.js index dcf5e38..128e513 100644 --- a/routes/launcher.js +++ b/routes/launcher.js @@ -1,11 +1,12 @@ const express = require("express"); const router = express.Router(); +const auth = require("../middleware/auth"); -router.get("/", (req, res) => { - if (!req.session.user) { - return res.redirect("/"); - } +/* ================================ + Launcher Seite +================================ */ +router.get("/", auth, (req, res) => { res.render("launcher", { character: { name: req.session.user.username, @@ -13,8 +14,4 @@ router.get("/", (req, res) => { }); }); -router.get("/launcher-dev", (req, res) => { - res.render("launcher-dev"); -}); - module.exports = router; diff --git a/routes/login.js b/routes/login.js index 42f1d1a..9f048eb 100644 --- a/routes/login.js +++ b/routes/login.js @@ -2,6 +2,7 @@ const express = require("express"); const router = express.Router(); const db = require("../database/database"); const bcrypt = require("bcrypt"); +const crypto = require("crypto"); /* ================================ Login verarbeiten @@ -14,6 +15,7 @@ router.post("/", async (req, res) => { /* Server laden (für index.ejs) */ const [servers] = await db.query("SELECT * FROM servers"); + /* User laden */ const [rows] = await db.query( "SELECT * FROM accounts WHERE username = ? AND verified = 1", [username], @@ -28,6 +30,7 @@ router.post("/", async (req, res) => { const user = rows[0]; + /* Passwort prüfen */ const passwordMatch = await bcrypt.compare(password, user.password); if (!passwordMatch) { @@ -37,25 +40,41 @@ router.post("/", async (req, res) => { }); } - /* Session speichern */ + /* ================================ + Session Token erstellen + ================================= */ + + const sessionToken = crypto.randomBytes(64).toString("hex"); + + /* Token in DB speichern (überschreibt alten Login) */ + + await db.query("UPDATE accounts SET session_token = ? WHERE id = ?", [ + sessionToken, + user.id, + ]); + + /* ================================ + Session speichern + ================================= */ req.session.user = { id: user.id, username: user.username, + token: sessionToken, }; - /* Wenn kein Charaktername existiert */ + /* ================================ + Weiterleitung + ================================= */ if (!user.ingame_name) { return res.redirect("/create-character"); } - /* Wenn Charakter existiert */ - - res.redirect("/launcher"); + return res.redirect("/launcher"); } catch (error) { - console.error(error); - res.send("Login Fehler"); + console.error("Login Fehler:", error); + res.status(500).send("Serverfehler beim Login"); } }); diff --git a/views/buildings/castle.ejs b/views/buildings/castle.ejs deleted file mode 100644 index 2038823..0000000 --- a/views/buildings/castle.ejs +++ /dev/null @@ -1,19 +0,0 @@ - - - - - Schloss - - - - - -
-

Schloss

- -

Hier kannst du deine Charaktere verwalten.

- - Zurück zur Karte -
- - diff --git a/views/buildings/church.ejs b/views/buildings/church.ejs deleted file mode 100644 index 4fdbb0f..0000000 --- a/views/buildings/church.ejs +++ /dev/null @@ -1,7 +0,0 @@ -
-

Kirche

- -

Segnungen und Heilungen.

- - Zurück zur Karte -
diff --git a/views/buildings/market.ejs b/views/buildings/market.ejs deleted file mode 100644 index 23fe2f9..0000000 --- a/views/buildings/market.ejs +++ /dev/null @@ -1,7 +0,0 @@ -
-

Marktplatz

- -

Hier kannst du Items kaufen.

- - Zurück zur Karte -
diff --git a/views/buildings/portal.ejs b/views/buildings/portal.ejs deleted file mode 100644 index 156ec4a..0000000 --- a/views/buildings/portal.ejs +++ /dev/null @@ -1,7 +0,0 @@ -
-

Portal

- -

Dungeon Zugang.

- - Zurück zur Karte -
diff --git a/views/buildings/tower.ejs b/views/buildings/tower.ejs deleted file mode 100644 index 94867e2..0000000 --- a/views/buildings/tower.ejs +++ /dev/null @@ -1,7 +0,0 @@ -
-

Turm

- -

PvP Arena.

- - Zurück zur Karte -