diff --git a/config.enc b/config.enc index 5c52f6f..cdcddf8 100644 --- a/config.enc +++ b/config.enc @@ -1 +1 @@ -G/kDLEJ/LddnnNnginIGYSM4Ax0g5pJaF0lrdOXke51cz3jSTrZxP7rjTXRlqLcoUJhPaVLvjb/DcyNYB/C339a+PFWyIdWYjSb6G4aPkD8J21yFWDDLpc08bXvoAx2PeE+Fc9v5mJUGDVv2wQoDvkHqIpN8ewrfRZ6+JF3OfQ== \ No newline at end of file +4PsgCvoOJLNXPpxOHOvm+KbVYz3pNxg8oOXO7zoH3MPffEhZLI7i5qf3o6oqZDI04us8xSSz9j3KIN+Atno/VFlYzSoq3ki1F+WSTz37LfcE3goPqhm6UaH8c9lHdulemH9tqgGq/DxgbKaup5t/ZJnLseaHHpdyTZok1jWULN0nlDuL/HvVVtqw5sboPqU= \ No newline at end of file diff --git a/db.js b/db.js index 60d7d1f..5495f88 100644 --- a/db.js +++ b/db.js @@ -11,6 +11,7 @@ function initPool() { return mysql.createPool({ host: config.db.host, + port: config.db.port || 3306, user: config.db.user, password: config.db.password, database: config.db.name, diff --git a/routes/admin.routes.js b/routes/admin.routes.js index 1ccb8fe..9ce52e1 100644 --- a/routes/admin.routes.js +++ b/routes/admin.routes.js @@ -71,6 +71,7 @@ router.get("/database", requireAdmin, async (req, res) => { if (cfg?.db) { const conn = await mysql.createConnection({ host: cfg.db.host, + port: Number(cfg.db.port || 3306), // ✅ WICHTIG: Port nutzen user: cfg.db.user, password: cfg.db.password, database: cfg.db.name, @@ -131,26 +132,46 @@ router.get("/database", requireAdmin, async (req, res) => { dbConfig: cfg?.db || null, testResult: null, backupFiles, - systemInfo, // ✅ DAS HAT GEFEHLT + systemInfo, }); }); // ✅ Nur testen (ohne speichern) router.post("/database/test", requireAdmin, async (req, res) => { - try { - const { host, user, password, name } = req.body; + const backupDir = path.join(__dirname, "..", "backups"); - if (!host || !user || !password || !name) { + function getBackupFiles() { + try { + if (fs.existsSync(backupDir)) { + return fs + .readdirSync(backupDir) + .filter((f) => f.toLowerCase().endsWith(".sql")) + .sort() + .reverse(); + } + } catch (err) { + console.error("❌ Backup Ordner Fehler:", err); + } + return []; + } + + try { + const { host, port, user, password, name } = req.body; + + if (!host || !port || !user || !password || !name) { const cfg = loadConfig(); return res.render("admin/database", { user: req.session.user, dbConfig: cfg?.db || null, testResult: { ok: false, message: "❌ Bitte alle Felder ausfüllen." }, + backupFiles: getBackupFiles(), + systemInfo: null, }); } const conn = await mysql.createConnection({ host, + port: Number(port), user, password, database: name, @@ -161,8 +182,10 @@ router.post("/database/test", requireAdmin, async (req, res) => { return res.render("admin/database", { user: req.session.user, - dbConfig: { host, user, password, name }, + dbConfig: { host, port: Number(port), user, password, name }, // ✅ PORT bleibt drin! testResult: { ok: true, message: "✅ Verbindung erfolgreich!" }, + backupFiles: getBackupFiles(), + systemInfo: null, }); } catch (err) { console.error("❌ DB TEST ERROR:", err); @@ -174,22 +197,59 @@ router.post("/database/test", requireAdmin, async (req, res) => { ok: false, message: "❌ Verbindung fehlgeschlagen: " + err.message, }, + backupFiles: getBackupFiles(), + systemInfo: null, }); } }); // ✅ DB Settings speichern + Verbindung testen router.post("/database", requireAdmin, async (req, res) => { - try { - const { host, user, password, name } = req.body; + function flashSafe(type, msg) { + if (typeof req.flash === "function") { + req.flash(type, msg); + return; + } + req.session.flash = req.session.flash || []; + req.session.flash.push({ type, message: msg }); + } - if (!host || !user || !password || !name) { - req.flash("error", "❌ Bitte alle Felder ausfüllen."); - return res.redirect("/admin/database"); + const backupDir = path.join(__dirname, "..", "backups"); + + // ✅ backupFiles immer bereitstellen + function getBackupFiles() { + try { + if (fs.existsSync(backupDir)) { + return fs + .readdirSync(backupDir) + .filter((f) => f.toLowerCase().endsWith(".sql")) + .sort() + .reverse(); + } + } catch (err) { + console.error("❌ Backup Ordner Fehler:", err); + } + return []; + } + + try { + const { host, port, user, password, name } = req.body; + + if (!host || !port || !user || !password || !name) { + flashSafe("danger", "❌ Bitte alle Felder ausfüllen."); + return res.render("admin/database", { + user: req.session.user, + dbConfig: req.body, + testResult: { ok: false, message: "❌ Bitte alle Felder ausfüllen." }, + backupFiles: getBackupFiles(), + systemInfo: null, + }); } + // ✅ Verbindung testen const conn = await mysql.createConnection({ host, + port: Number(port), user, password, database: name, @@ -198,25 +258,51 @@ router.post("/database", requireAdmin, async (req, res) => { await conn.query("SELECT 1"); await conn.end(); - // ✅ Speichern in config.enc + // ✅ Speichern inkl. Port const current = loadConfig() || {}; - current.db = { host, user, password, name }; + current.db = { + host, + port: Number(port), + user, + password, + name, + }; saveConfig(current); - // ✅ DB Pool resetten (falls vorhanden) + // ✅ Pool reset if (typeof db.resetPool === "function") { db.resetPool(); } - req.flash( - "success", - "✅ DB Einstellungen gespeichert + Verbindung erfolgreich getestet.", - ); - return res.redirect("/admin/database"); + flashSafe("success", "✅ DB Einstellungen gespeichert!"); + + // ✅ DIREKT NEU LADEN aus config.enc (damit wirklich die gespeicherten Werte drin stehen) + const freshCfg = loadConfig(); + + return res.render("admin/database", { + user: req.session.user, + dbConfig: freshCfg?.db || null, + testResult: { + ok: true, + message: "✅ Gespeichert und Verbindung getestet.", + }, + backupFiles: getBackupFiles(), + systemInfo: null, + }); } catch (err) { console.error("❌ DB UPDATE ERROR:", err); - req.flash("error", "❌ Verbindung fehlgeschlagen: " + err.message); - return res.redirect("/admin/database"); + flashSafe("danger", "❌ Verbindung fehlgeschlagen: " + err.message); + + return res.render("admin/database", { + user: req.session.user, + dbConfig: req.body, + testResult: { + ok: false, + message: "❌ Verbindung fehlgeschlagen: " + err.message, + }, + backupFiles: getBackupFiles(), + systemInfo: null, + }); } }); diff --git a/views/admin/database.ejs b/views/admin/database.ejs index 10d6048..63327df 100644 --- a/views/admin/database.ejs +++ b/views/admin/database.ejs @@ -1,466 +1,252 @@ - - - - - Datenbankverwaltung - +<%- include("../partials/page-header", { + user, + title: "Datenbankverwaltung", + subtitle: "", + showUserName: true +}) %> - - - - +
- - - - - -
- - - <%- include("../partials/admin-sidebar", { user, active: "database" }) %> - - -
- - + +
-
+ +
+
- - <%- include("../partials/flash") %> +

+ Datenbank Konfiguration +

- - <% if (testResult) { %> -
- <%= testResult.message %> -
- <% } %> +

+ Hier kannst du die DB-Verbindung testen und speichern. +

-
-
- -

Datenbank Tools

- -
- Hinweis: Diese Funktionen sind nur für Admins sichtbar und sollten mit Vorsicht benutzt werden. -
- - -
-
- -
-
🔧 Datenbankverbindung ändern
+ +
+
+ +
- <% if (!dbConfig) { %> -
- ❌ Keine Datenbank-Konfiguration gefunden (config.enc fehlt oder ungültig). +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + + + +
+ + + <% if (typeof testResult !== "undefined" && testResult) { %> +
+ <%= testResult.message %> +
+ <% } %> + +
+
+ + +
+
+ +

+ Systeminformationen +

+ + <% if (typeof systemInfo !== "undefined" && systemInfo?.error) { %> + +
+ ❌ Fehler beim Auslesen der Datenbankinfos: +
<%= systemInfo.error %>
+
+ + <% } else if (typeof systemInfo !== "undefined" && systemInfo) { %> + +
+
+
+
MySQL Version
+
<%= systemInfo.version %>
+
+
+ +
+
+
Anzahl Tabellen
+
<%= systemInfo.tableCount %>
+
+
+ +
+
+
Datenbankgröße
+
<%= systemInfo.dbSizeMB %> MB
+
+
+
+ + <% if (systemInfo.tables && systemInfo.tables.length > 0) { %> +
+ +
Tabellenübersicht
+ +
+ + + + + + + + + + + <% systemInfo.tables.forEach(t => { %> + + + + + + <% }) %> + +
TabelleZeilenGröße (MB)
<%= t.name %><%= t.row_count %><%= t.size_mb %>
<% } %> - -
+ <% } else { %> -
- - -
+
+ ⚠️ Keine Systeminfos verfügbar (DB ist evtl. nicht konfiguriert oder Verbindung fehlgeschlagen). +
-
- - -
+ <% } %> -
- - -
+
+
-
- - -
+ +
+
- -
+

+ Backup & Restore +

- - + + + +
+
+ + + + - - - - - - - - - - Zurücksetzen - -
- -
-
- Standardmäßig sind die Felder gesperrt. Erst auf Bearbeiten klicken. -
- -
-
+ + <% if (typeof backupFiles === "undefined" || !backupFiles || backupFiles.length === 0) { %> +
+ ℹ️ Noch keine Backups vorhanden. +
+ <% } %> +
- - -
- - -
-
-
-
📦 Backup
-

- Erstellt ein SQL Backup der kompletten Datenbank. -

- -
- -
-
-
-
- - -
-
-
-
♻️ Restore
-

- Wähle ein Backup aus dem Ordner /backups und stelle die Datenbank wieder her. -

- - <% if (!backupFiles || backupFiles.length === 0) { %> -
- Keine Backups im Ordner /backups gefunden. -
- <% } %> - -
- -
- <% (backupFiles || []).forEach((f, index) => { %> - - <% }) %> -
- - -
- -
- Es werden die neuesten Backups zuerst angezeigt. Wenn mehr vorhanden sind, kannst du scrollen. -
- -
-
-
- - -
-
-
-
🔍 Systeminfo
- - <% if (!systemInfo) { %> -

Keine Systeminfos verfügbar.

- - <% } else if (systemInfo.error) { %> -
- ❌ Systeminfo konnte nicht geladen werden: <%= systemInfo.error %> -
- - <% } else { %> - -
- - -
-
- -
-
DB Version
-
<%= systemInfo.version %>
-
- -
-
Tabellen
-
<%= systemInfo.tableCount %>
-
- -
-
DB Größe
-
<%= systemInfo.dbSizeMB %> MB
-
- -
-
- - -
-
-
Tabellenübersicht
- -
- - - - - - - - - - - <% systemInfo.tables.forEach(t => { %> - - - - - - <% }) %> - -
TabellennameRowsMB
<%= t.name %><%= t.row_count %><%= t.size_mb %>
-
- -
-
- -
- - <% } %> -
-
-
- -
-
-
+
- - - - - diff --git a/views/partials/admin-sidebar.ejs b/views/partials/admin-sidebar.ejs index 4a97f8f..2b4bcd4 100644 --- a/views/partials/admin-sidebar.ejs +++ b/views/partials/admin-sidebar.ejs @@ -63,5 +63,17 @@ <% } %> + + + Datenbank + <% if (!isAdmin) { %> + + <% } %> + +