Mehrfachlogin nicht mehr möglich

This commit is contained in:
Cay 2026-03-13 13:22:52 +00:00
parent 4d8681ac86
commit fd116db132
11 changed files with 157 additions and 143 deletions

31
middleware/auth.js Normal file
View File

@ -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;

View File

@ -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);
});

View File

@ -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 = `
<h3>${data.name}</h3>
<p>Level: ${data.level}</p>
<p>Punkte: ${data.points} / ${data.nextLevelPoints}</p>
<p>${data.description}</p>
<div class="progress-bar">
<div class="progress-fill"
style="width:${(data.points / data.nextLevelPoints) * 100}%">
const data = await res.json();
document.getElementById("tab-info").innerHTML = `
<h3>${data.name}</h3>
<p>Level: ${data.level}</p>
<p>Punkte: ${data.points} / ${data.nextLevelPoints}</p>
<p>${data.description}</p>
<div class="progress-bar">
<div class="progress-fill"
style="width:${(data.points / data.nextLevelPoints) * 100}%">
</div>
</div>
</div>
`;
`;
document.getElementById("tab-actions").innerHTML = `
<button>Betreten</button>
<button>Handeln</button>
`;
document.getElementById("tab-actions").innerHTML = `
<button>Betreten</button>
<button>Handeln</button>
`;
document.getElementById("tab-upgrade").innerHTML = `
<p>Kosten: ${data.upgradeCost}</p>
<button>Upgrade</button>
`;
document.getElementById("tab-upgrade").innerHTML = `
<p>Kosten: ${data.upgradeCost}</p>
<button>Upgrade</button>
`;
document.getElementById("tab-history").innerHTML = `
<p>${data.history}</p>
`;
document.getElementById("tab-history").innerHTML = `
<p>${data.history}</p>
`;
} 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 = `
<h3>${data.name}</h3>
<p>Level: ${data.level}</p>
<p>Punkte: ${data.points} / ${data.nextLevelPoints}</p>
<p>${data.description}</p>
`;
document.getElementById("tab-upgrade").innerHTML = `
<p>Nächstes Level benötigt:</p>
<p>${data.nextLevelPoints} Punkte</p>
<p>Kosten: ${data.upgradeCost}</p>
`;
document.getElementById("tab-history").innerHTML = `
<p>${data.history}</p>
`;
} 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 = `
<strong>${data.name}</strong><br>
Level ${data.level}<br>
Punkte ${data.points}/${data.nextLevelPoints}<br>
<hr>
Upgrade Kosten:<br>
${data.upgradeCost}
`;
if (!res.ok) throw new Error("API Fehler");
tooltip.style.display = "block";
const data = await res.json();
tooltip.innerHTML = `
<strong>${data.name}</strong><br>
Level ${data.level}<br>
Punkte ${data.points}/${data.nextLevelPoints}<br>
<hr>
Upgrade Kosten:<br>
${data.upgradeCost}
`;
tooltip.style.display = "block";
} catch (err) {
console.error("Tooltip Fehler:", err);
}
});
building.addEventListener("mousemove", (e) => {

View File

@ -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");
});

View File

@ -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;

View File

@ -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");
}
});

View File

@ -1,19 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<title>Schloss</title>
<link rel="stylesheet" href="/css/building.css" />
</head>
<body>
<div class="building">
<h1>Schloss</h1>
<p>Hier kannst du deine Charaktere verwalten.</p>
<a class="back" href="/launcher"> Zurück zur Karte </a>
</div>
</body>
</html>

View File

@ -1,7 +0,0 @@
<div class="building">
<h1>Kirche</h1>
<p>Segnungen und Heilungen.</p>
<a href="/launcher">Zurück zur Karte</a>
</div>

View File

@ -1,7 +0,0 @@
<div class="building">
<h1>Marktplatz</h1>
<p>Hier kannst du Items kaufen.</p>
<a href="/launcher">Zurück zur Karte</a>
</div>

View File

@ -1,7 +0,0 @@
<div class="building">
<h1>Portal</h1>
<p>Dungeon Zugang.</p>
<a href="/launcher">Zurück zur Karte</a>
</div>

View File

@ -1,7 +0,0 @@
<div class="building">
<h1>Turm</h1>
<p>PvP Arena.</p>
<a href="/launcher">Zurück zur Karte</a>
</div>