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 = `
-
-
+ 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
-
-
-
-
-
-
-
-
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 @@
-
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 @@
-
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 @@
-
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 @@
-