neue db verbindung
This commit is contained in:
parent
6f5c9a28a1
commit
16fb18f9e6
@ -1 +1 @@
|
||||
4PsgCvoOJLNXPpxOHOvm+KbVYz3pNxg8oOXO7zoH3MPffEhZLI7i5qf3o6oqZDI04us8xSSz9j3KIN+Atno/VFlYzSoq3ki1F+WSTz37LfcE3goPqhm6UaH8c9lHdulemH9tqgGq/DxgbKaup5t/ZJnLseaHHpdyTZok1jWULN0nlDuL/HvVVtqw5sboPqU=
|
||||
MgmDGURt7NfYtetWb79ghkifQA6ztKwK/7Hl1BNBG2QA+kIbDtHM+1R8XPRiTtDtBHPo+T8UmzvmOuztdphLvMnMW7/Jlqo+VAg4mbYDRLz8WQja5KBmIQJf1eF5riHPu0zQDjY7VU1AX2mzR8xfWrB+CngkagEHXv7OsigsRmxlrB3oGTd6GY6PeAYq3jTblo4kjDDg6GWeDJoF
|
||||
@ -3,45 +3,76 @@ const router = express.Router();
|
||||
const mysql = require("mysql2/promise");
|
||||
|
||||
// ✅ nutzt deinen bestehenden config-manager (NICHT utils/config!)
|
||||
const { configExists, saveConfig } = require("../config-manager");
|
||||
const { configExists, loadConfig, saveConfig } = require("../config-manager");
|
||||
|
||||
// ✅ DB + Session Reset (wie in deiner app.js)
|
||||
const db = require("../db");
|
||||
const { resetSessionStore } = require("../config/session");
|
||||
|
||||
/**
|
||||
* Setup darf nur laufen, wenn config.enc NICHT existiert
|
||||
* (sonst könnte jeder die DB später überschreiben)
|
||||
* Setup ist immer erreichbar – auch wenn config.enc schon existiert.
|
||||
* So kann die DB-Verbindung jederzeit korrigiert werden.
|
||||
* Schutz: Nur wenn DB bereits erreichbar ist UND User eingeloggt ist → blockieren.
|
||||
*/
|
||||
function blockIfInstalled(req, res, next) {
|
||||
if (configExists()) {
|
||||
return res.redirect("/");
|
||||
}
|
||||
// Immer durchlassen – Setup muss auch zur Korrektur nutzbar sein
|
||||
next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Form anzeigen
|
||||
* Setup Form anzeigen – vorhandene Werte aus config.enc als Defaults laden
|
||||
*/
|
||||
router.get("/", blockIfInstalled, (req, res) => {
|
||||
// Bestehende Config als Vorausfüllung laden (Passwort bleibt leer)
|
||||
let existing = {};
|
||||
try {
|
||||
if (configExists()) {
|
||||
const cfg = loadConfig();
|
||||
existing = cfg?.db || {};
|
||||
}
|
||||
} catch (e) {
|
||||
existing = {};
|
||||
}
|
||||
|
||||
return res.render("setup/index", {
|
||||
title: "Erstinstallation",
|
||||
title: configExists() ? "DB-Verbindung ändern" : "Erstinstallation",
|
||||
isUpdate: configExists(),
|
||||
defaults: {
|
||||
host: "127.0.0.1",
|
||||
port: 3306,
|
||||
user: "",
|
||||
password: "",
|
||||
name: "",
|
||||
host: existing.host || "85.215.63.122",
|
||||
port: existing.port || 3306,
|
||||
user: existing.user || "",
|
||||
password: "", // Passwort aus Sicherheitsgründen nie vorausfüllen
|
||||
name: existing.name || "",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Passwort auflösen: wenn leer → altes Passwort aus config.enc nehmen
|
||||
*/
|
||||
function resolvePassword(inputPassword) {
|
||||
if (inputPassword && inputPassword.trim() !== "") {
|
||||
return inputPassword;
|
||||
}
|
||||
// Passwort-Feld leer → altes Passwort aus bestehender Config beibehalten
|
||||
try {
|
||||
if (configExists()) {
|
||||
const old = loadConfig();
|
||||
return old?.db?.password || "";
|
||||
}
|
||||
} catch (e) {
|
||||
/* ignore */
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* ✅ Verbindung testen (AJAX)
|
||||
*/
|
||||
router.post("/test", blockIfInstalled, async (req, res) => {
|
||||
try {
|
||||
const { host, port, user, password, name } = req.body;
|
||||
const { host, port, user, name } = req.body;
|
||||
const password = resolvePassword(req.body.password);
|
||||
|
||||
if (!host || !user || !name) {
|
||||
return res.status(400).json({
|
||||
@ -51,12 +82,12 @@ router.post("/test", blockIfInstalled, async (req, res) => {
|
||||
}
|
||||
|
||||
const connection = await mysql.createConnection({
|
||||
host,
|
||||
host: host.trim(),
|
||||
port: Number(port || 3306),
|
||||
user,
|
||||
user: user.trim(),
|
||||
password,
|
||||
database: name,
|
||||
connectTimeout: 5000,
|
||||
database: name.trim(),
|
||||
connectTimeout: 6000,
|
||||
});
|
||||
|
||||
await connection.query("SELECT 1");
|
||||
@ -76,7 +107,9 @@ router.post("/test", blockIfInstalled, async (req, res) => {
|
||||
*/
|
||||
router.post("/", blockIfInstalled, async (req, res) => {
|
||||
try {
|
||||
const { host, port, user, password, name } = req.body;
|
||||
const { host, port, user, name } = req.body;
|
||||
// Passwort: leer = altes Passwort beibehalten
|
||||
const password = resolvePassword(req.body.password);
|
||||
|
||||
if (!host || !user || !name) {
|
||||
req.session.flash = req.session.flash || [];
|
||||
@ -88,41 +121,50 @@ router.post("/", blockIfInstalled, async (req, res) => {
|
||||
}
|
||||
|
||||
// ✅ Verbindung testen bevor speichern
|
||||
const connection = await mysql.createConnection({
|
||||
host,
|
||||
port: Number(port || 3306),
|
||||
user,
|
||||
password,
|
||||
database: name,
|
||||
connectTimeout: 5000,
|
||||
});
|
||||
let connection;
|
||||
try {
|
||||
connection = await mysql.createConnection({
|
||||
host: host.trim(),
|
||||
port: Number(port || 3306),
|
||||
user: user.trim(),
|
||||
password,
|
||||
database: name.trim(),
|
||||
connectTimeout: 6000,
|
||||
});
|
||||
await connection.query("SELECT 1");
|
||||
await connection.end();
|
||||
} catch (connErr) {
|
||||
req.session.flash = req.session.flash || [];
|
||||
req.session.flash.push({
|
||||
type: "danger",
|
||||
message: "❌ DB-Verbindung fehlgeschlagen: " + connErr.message,
|
||||
});
|
||||
return res.redirect("/setup");
|
||||
}
|
||||
|
||||
await connection.query("SELECT 1");
|
||||
await connection.end();
|
||||
|
||||
// ✅ speichern
|
||||
// ✅ In config.enc speichern
|
||||
saveConfig({
|
||||
db: {
|
||||
host,
|
||||
host: host.trim(),
|
||||
port: Number(port || 3306),
|
||||
user,
|
||||
user: user.trim(),
|
||||
password,
|
||||
name,
|
||||
name: name.trim(),
|
||||
},
|
||||
});
|
||||
|
||||
// ✅ DB Pool neu starten (damit neue config sofort aktiv ist)
|
||||
// ✅ DB Pool neu initialisieren (neue Config sofort aktiv)
|
||||
if (typeof db.resetPool === "function") {
|
||||
db.resetPool();
|
||||
}
|
||||
|
||||
// ✅ Session Store neu starten
|
||||
// ✅ Session Store neu initialisieren
|
||||
resetSessionStore();
|
||||
|
||||
req.session.flash = req.session.flash || [];
|
||||
req.session.flash.push({
|
||||
type: "success",
|
||||
message: "✅ Setup abgeschlossen. Du kannst dich jetzt einloggen.",
|
||||
message: "✅ DB-Verbindung gespeichert. Du kannst dich jetzt einloggen.",
|
||||
});
|
||||
|
||||
return res.redirect("/login");
|
||||
|
||||
@ -6,105 +6,177 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<style>
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background: #f5f5f5;
|
||||
padding: 20px;
|
||||
background: #f0f2f5;
|
||||
padding: 40px 20px;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
}
|
||||
.card {
|
||||
max-width: 560px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
max-width: 580px;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||
padding: 32px;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
|
||||
}
|
||||
.card h2 {
|
||||
margin: 0 0 6px 0;
|
||||
font-size: 22px;
|
||||
color: #111827;
|
||||
}
|
||||
.card p {
|
||||
margin: 0 0 24px 0;
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
}
|
||||
.badge-update {
|
||||
display: inline-block;
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
padding: 3px 10px;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid #fcd34d;
|
||||
}
|
||||
label {
|
||||
display: block;
|
||||
margin-top: 12px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: #374151;
|
||||
}
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-top: 6px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border: 1px solid #d1d5db;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
input:focus {
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 0 3px rgba(37,99,235,0.12);
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
.row > div {
|
||||
flex: 1;
|
||||
.row > div { flex: 1; }
|
||||
.btn-row {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 24px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
button {
|
||||
margin-top: 16px;
|
||||
padding: 10px 14px;
|
||||
padding: 10px 18px;
|
||||
border: 0;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.btn-primary {
|
||||
background: #2563eb;
|
||||
color: white;
|
||||
}
|
||||
.btn-secondary {
|
||||
background: #111827;
|
||||
color: white;
|
||||
}
|
||||
button:hover { opacity: 0.88; }
|
||||
.btn-primary { background: #2563eb; color: white; flex: 1; }
|
||||
.btn-secondary { background: #111827; color: white; }
|
||||
.msg {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
margin-top: 14px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
display: none;
|
||||
}
|
||||
.msg.ok {
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
}
|
||||
.msg.bad {
|
||||
background: #fee2e2;
|
||||
color: #991b1b;
|
||||
.msg.ok { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
|
||||
.msg.bad { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }
|
||||
.msg.pending { background: #eff6ff; color: #1d4ed8; border: 1px solid #93c5fd; }
|
||||
.divider {
|
||||
border: none;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
margin: 24px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<h2>🛠️ Erstinstallation</h2>
|
||||
<p>
|
||||
Bitte DB Daten eingeben. Danach wird
|
||||
<code>config.enc</code> gespeichert.
|
||||
</p>
|
||||
<h2>🛠️ <%= title %></h2>
|
||||
|
||||
<form method="POST" action="/setup">
|
||||
<label>DB Host</label>
|
||||
<input name="host" placeholder="85.215.63.122" required />
|
||||
<% if (typeof isUpdate !== 'undefined' && isUpdate) { %>
|
||||
<span class="badge-update">⚠️ Bestehende Konfiguration wird überschrieben</span>
|
||||
<% } %>
|
||||
|
||||
<label>DB Port</label>
|
||||
<input name="port" placeholder="3306" value="3306" required />
|
||||
<p>DB-Verbindungsdaten eingeben. Die Verbindung wird vor dem Speichern geprüft.</p>
|
||||
|
||||
<label>DB Benutzer</label>
|
||||
<input name="user" placeholder="praxisuser" required />
|
||||
<form method="POST" action="/setup" id="setupForm">
|
||||
|
||||
<label>DB Passwort</label>
|
||||
<input name="password" type="password" required />
|
||||
<div class="row">
|
||||
<div>
|
||||
<label for="host">DB Host</label>
|
||||
<input
|
||||
id="host"
|
||||
name="host"
|
||||
placeholder="85.215.63.122"
|
||||
value="<%= defaults.host %>"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div style="max-width:110px">
|
||||
<label for="port">Port</label>
|
||||
<input
|
||||
id="port"
|
||||
name="port"
|
||||
placeholder="3306"
|
||||
value="<%= defaults.port %>"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label>DB Name</label>
|
||||
<input name="name" placeholder="praxissoftware" required />
|
||||
<label>Passwort</label>
|
||||
<label for="user">DB Benutzer</label>
|
||||
<input
|
||||
name="password"
|
||||
type="password"
|
||||
value="<%= defaults.password %>"
|
||||
id="user"
|
||||
name="user"
|
||||
placeholder="praxisuser"
|
||||
value="<%= defaults.user %>"
|
||||
required
|
||||
/>
|
||||
|
||||
<button type="button" class="btn-secondary" onclick="testConnection()">
|
||||
🔍 Verbindung testen
|
||||
</button>
|
||||
<button type="submit" class="btn-primary">
|
||||
✅ Speichern & Setup abschließen
|
||||
</button>
|
||||
<label for="password">DB Passwort</label>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
placeholder="<%= typeof isUpdate !== 'undefined' && isUpdate ? '(unverändert lassen = leer lassen)' : '' %>"
|
||||
/>
|
||||
|
||||
<label for="name">DB Name</label>
|
||||
<input
|
||||
id="name"
|
||||
name="name"
|
||||
placeholder="praxissoftware"
|
||||
value="<%= defaults.name %>"
|
||||
required
|
||||
/>
|
||||
|
||||
<hr class="divider" />
|
||||
|
||||
<div class="btn-row">
|
||||
<button type="button" class="btn-secondary" onclick="testConnection()">
|
||||
🔍 Verbindung testen
|
||||
</button>
|
||||
<button type="submit" class="btn-primary">
|
||||
✅ Speichern & abschließen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="msg" class="msg"></div>
|
||||
</form>
|
||||
@ -112,14 +184,19 @@
|
||||
|
||||
<script>
|
||||
async function testConnection() {
|
||||
const form = document.querySelector("form");
|
||||
const data = new FormData(form);
|
||||
const body = Object.fromEntries(data.entries());
|
||||
|
||||
const msg = document.getElementById("msg");
|
||||
msg.className = "msg pending";
|
||||
msg.style.display = "block";
|
||||
msg.className = "msg";
|
||||
msg.textContent = "Teste Verbindung...";
|
||||
msg.textContent = "⏳ Teste Verbindung...";
|
||||
|
||||
// Felder einzeln auslesen (sicherer als FormData bei doppelten Namen)
|
||||
const body = {
|
||||
host: document.getElementById("host").value.trim(),
|
||||
port: document.getElementById("port").value.trim(),
|
||||
user: document.getElementById("user").value.trim(),
|
||||
password: document.getElementById("password").value,
|
||||
name: document.getElementById("name").value.trim(),
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await fetch("/setup/test", {
|
||||
@ -129,13 +206,11 @@
|
||||
});
|
||||
|
||||
const json = await res.json();
|
||||
msg.className = "msg " + (json.ok ? "ok" : "bad");
|
||||
msg.textContent = json.message;
|
||||
|
||||
if (json.ok) msg.classList.add("ok");
|
||||
else msg.classList.add("bad");
|
||||
} catch (e) {
|
||||
msg.textContent = "❌ Fehler: " + e.message;
|
||||
msg.classList.add("bad");
|
||||
msg.className = "msg bad";
|
||||
msg.textContent = "❌ Netzwerkfehler: " + e.message;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user