Mehrfachlogin nicht mehr möglich
This commit is contained in:
parent
4d8681ac86
commit
fd116db132
31
middleware/auth.js
Normal file
31
middleware/auth.js
Normal 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;
|
||||||
@ -1,5 +1,10 @@
|
|||||||
fetch("/api/buildings")
|
fetch("/api/buildings")
|
||||||
.then((res) => res.json())
|
.then((res) => {
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error("API Fehler");
|
||||||
|
}
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
.then((buildings) => {
|
.then((buildings) => {
|
||||||
buildings.forEach((building) => {
|
buildings.forEach((building) => {
|
||||||
const element = document.querySelector(
|
const element = document.querySelector(
|
||||||
@ -10,7 +15,6 @@ fetch("/api/buildings")
|
|||||||
|
|
||||||
let title = element.querySelector("title");
|
let title = element.querySelector("title");
|
||||||
|
|
||||||
// Falls kein title existiert → erstellen
|
|
||||||
if (!title) {
|
if (!title) {
|
||||||
title = document.createElementNS("http://www.w3.org/2000/svg", "title");
|
title = document.createElementNS("http://www.w3.org/2000/svg", "title");
|
||||||
element.prepend(title);
|
element.prepend(title);
|
||||||
@ -18,4 +22,7 @@ fetch("/api/buildings")
|
|||||||
|
|
||||||
title.textContent = building.name;
|
title.textContent = building.name;
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Buildings API Fehler:", error);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,6 +2,10 @@ const popup = document.getElementById("building-popup");
|
|||||||
const title = document.getElementById("popup-title");
|
const title = document.getElementById("popup-title");
|
||||||
const tooltip = document.getElementById("map-tooltip");
|
const tooltip = document.getElementById("map-tooltip");
|
||||||
|
|
||||||
|
/* ================================
|
||||||
|
Tabs zurücksetzen
|
||||||
|
================================ */
|
||||||
|
|
||||||
function resetTabs() {
|
function resetTabs() {
|
||||||
document
|
document
|
||||||
.querySelectorAll(".tab")
|
.querySelectorAll(".tab")
|
||||||
@ -10,7 +14,6 @@ function resetTabs() {
|
|||||||
.querySelectorAll(".tab-content")
|
.querySelectorAll(".tab-content")
|
||||||
.forEach((c) => c.classList.remove("active"));
|
.forEach((c) => c.classList.remove("active"));
|
||||||
|
|
||||||
// erster Tab aktiv
|
|
||||||
const firstTab = document.querySelector(".tab");
|
const firstTab = document.querySelector(".tab");
|
||||||
const firstContent = document.querySelector(".tab-content");
|
const firstContent = document.querySelector(".tab-content");
|
||||||
|
|
||||||
@ -18,26 +21,30 @@ function resetTabs() {
|
|||||||
if (firstContent) firstContent.classList.add("active");
|
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();
|
e.preventDefault();
|
||||||
|
|
||||||
const name = b.querySelector("title").textContent;
|
try {
|
||||||
const url = b.getAttribute("href");
|
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.left = "50%";
|
||||||
popup.style.top = "50%";
|
popup.style.top = "50%";
|
||||||
|
|
||||||
popup.style.display = "block";
|
popup.style.display = "block";
|
||||||
|
|
||||||
resetTabs();
|
resetTabs();
|
||||||
|
|
||||||
// AJAX Gebäudedaten laden
|
|
||||||
const res = await fetch("/api" + url);
|
const res = await fetch("/api" + url);
|
||||||
|
|
||||||
|
if (!res.ok) throw new Error("API Fehler");
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
document.getElementById("tab-info").innerHTML = `
|
document.getElementById("tab-info").innerHTML = `
|
||||||
@ -65,10 +72,16 @@ document.querySelectorAll(".building").forEach((b) => {
|
|||||||
document.getElementById("tab-history").innerHTML = `
|
document.getElementById("tab-history").innerHTML = `
|
||||||
<p>${data.history}</p>
|
<p>${data.history}</p>
|
||||||
`;
|
`;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gebäude konnte nicht geladen werden:", error);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tabs
|
/* ================================
|
||||||
|
Tabs wechseln
|
||||||
|
================================ */
|
||||||
|
|
||||||
document.querySelectorAll(".tab").forEach((tab) => {
|
document.querySelectorAll(".tab").forEach((tab) => {
|
||||||
tab.addEventListener("click", () => {
|
tab.addEventListener("click", () => {
|
||||||
document
|
document
|
||||||
@ -84,41 +97,27 @@ document.querySelectorAll(".tab").forEach((tab) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* ================================
|
||||||
|
Popup schließen
|
||||||
|
================================ */
|
||||||
|
|
||||||
document.querySelector(".popup-close").onclick = () => {
|
document.querySelector(".popup-close").onclick = () => {
|
||||||
popup.style.display = "none";
|
popup.style.display = "none";
|
||||||
};
|
};
|
||||||
|
|
||||||
async function loadBuilding(buildingId) {
|
/* ================================
|
||||||
try {
|
Tooltip
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelectorAll(".building").forEach((building) => {
|
document.querySelectorAll(".building").forEach((building) => {
|
||||||
building.addEventListener("mouseenter", async (e) => {
|
building.addEventListener("mouseenter", async (e) => {
|
||||||
|
try {
|
||||||
const id = building.dataset.id;
|
const id = building.dataset.id;
|
||||||
|
|
||||||
const res = await fetch("/api/building/" + id);
|
const res = await fetch("/api/building/" + id);
|
||||||
|
|
||||||
|
if (!res.ok) throw new Error("API Fehler");
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
tooltip.innerHTML = `
|
tooltip.innerHTML = `
|
||||||
@ -131,6 +130,9 @@ document.querySelectorAll(".building").forEach((building) => {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
tooltip.style.display = "block";
|
tooltip.style.display = "block";
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Tooltip Fehler:", err);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
building.addEventListener("mousemove", (e) => {
|
building.addEventListener("mousemove", (e) => {
|
||||||
|
|||||||
@ -1,23 +1,28 @@
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
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");
|
res.render("buildings/castle");
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/market", (req, res) => {
|
router.get("/market", auth, (req, res) => {
|
||||||
res.render("buildings/market");
|
res.render("buildings/market");
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/church", (req, res) => {
|
router.get("/church", auth, (req, res) => {
|
||||||
res.render("buildings/church");
|
res.render("buildings/church");
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/portal", (req, res) => {
|
router.get("/portal", auth, (req, res) => {
|
||||||
res.render("buildings/portal");
|
res.render("buildings/portal");
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/tower", (req, res) => {
|
router.get("/tower", auth, (req, res) => {
|
||||||
res.render("buildings/tower");
|
res.render("buildings/tower");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const auth = require("../middleware/auth");
|
||||||
|
|
||||||
router.get("/", (req, res) => {
|
/* ================================
|
||||||
if (!req.session.user) {
|
Launcher Seite
|
||||||
return res.redirect("/");
|
================================ */
|
||||||
}
|
|
||||||
|
|
||||||
|
router.get("/", auth, (req, res) => {
|
||||||
res.render("launcher", {
|
res.render("launcher", {
|
||||||
character: {
|
character: {
|
||||||
name: req.session.user.username,
|
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;
|
module.exports = router;
|
||||||
|
|||||||
@ -2,6 +2,7 @@ const express = require("express");
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const db = require("../database/database");
|
const db = require("../database/database");
|
||||||
const bcrypt = require("bcrypt");
|
const bcrypt = require("bcrypt");
|
||||||
|
const crypto = require("crypto");
|
||||||
|
|
||||||
/* ================================
|
/* ================================
|
||||||
Login verarbeiten
|
Login verarbeiten
|
||||||
@ -14,6 +15,7 @@ router.post("/", async (req, res) => {
|
|||||||
/* Server laden (für index.ejs) */
|
/* Server laden (für index.ejs) */
|
||||||
const [servers] = await db.query("SELECT * FROM servers");
|
const [servers] = await db.query("SELECT * FROM servers");
|
||||||
|
|
||||||
|
/* User laden */
|
||||||
const [rows] = await db.query(
|
const [rows] = await db.query(
|
||||||
"SELECT * FROM accounts WHERE username = ? AND verified = 1",
|
"SELECT * FROM accounts WHERE username = ? AND verified = 1",
|
||||||
[username],
|
[username],
|
||||||
@ -28,6 +30,7 @@ router.post("/", async (req, res) => {
|
|||||||
|
|
||||||
const user = rows[0];
|
const user = rows[0];
|
||||||
|
|
||||||
|
/* Passwort prüfen */
|
||||||
const passwordMatch = await bcrypt.compare(password, user.password);
|
const passwordMatch = await bcrypt.compare(password, user.password);
|
||||||
|
|
||||||
if (!passwordMatch) {
|
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 = {
|
req.session.user = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
|
token: sessionToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Wenn kein Charaktername existiert */
|
/* ================================
|
||||||
|
Weiterleitung
|
||||||
|
================================= */
|
||||||
|
|
||||||
if (!user.ingame_name) {
|
if (!user.ingame_name) {
|
||||||
return res.redirect("/create-character");
|
return res.redirect("/create-character");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wenn Charakter existiert */
|
return res.redirect("/launcher");
|
||||||
|
|
||||||
res.redirect("/launcher");
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error("Login Fehler:", error);
|
||||||
res.send("Login Fehler");
|
res.status(500).send("Serverfehler beim Login");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
<div class="building">
|
|
||||||
<h1>Kirche</h1>
|
|
||||||
|
|
||||||
<p>Segnungen und Heilungen.</p>
|
|
||||||
|
|
||||||
<a href="/launcher">Zurück zur Karte</a>
|
|
||||||
</div>
|
|
||||||
@ -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>
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
<div class="building">
|
|
||||||
<h1>Portal</h1>
|
|
||||||
|
|
||||||
<p>Dungeon Zugang.</p>
|
|
||||||
|
|
||||||
<a href="/launcher">Zurück zur Karte</a>
|
|
||||||
</div>
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
<div class="building">
|
|
||||||
<h1>Turm</h1>
|
|
||||||
|
|
||||||
<p>PvP Arena.</p>
|
|
||||||
|
|
||||||
<a href="/launcher">Zurück zur Karte</a>
|
|
||||||
</div>
|
|
||||||
Loading…
Reference in New Issue
Block a user