require("dotenv").config();
const express = require("express");
const session = require("express-session");
const helmet = require("helmet");
const mysql = require("mysql2/promise");
const fs = require("fs");
const path = require("path");
// ✅ Verschlüsselte Config
const { configExists, saveConfig } = require("./config-manager");
// ✅ Reset-Funktionen (Soft-Restart)
const db = require("./db");
const { getSessionStore, resetSessionStore } = require("./config/session");
// ✅ Deine Routes (unverändert)
const adminRoutes = require("./routes/admin.routes");
const dashboardRoutes = require("./routes/dashboard.routes");
const patientRoutes = require("./routes/patient.routes");
const medicationRoutes = require("./routes/medications.routes");
const patientMedicationRoutes = require("./routes/patientMedication.routes");
const waitingRoomRoutes = require("./routes/waitingRoom.routes");
const serviceRoutes = require("./routes/service.routes");
const patientServiceRoutes = require("./routes/patientService.routes");
const invoiceRoutes = require("./routes/invoice.routes");
const patientFileRoutes = require("./routes/patientFile.routes");
const companySettingsRoutes = require("./routes/companySettings.routes");
const authRoutes = require("./routes/auth.routes");
const app = express();
/* ===============================
SETUP HTML
================================ */
function setupHtml(error = "") {
return `
Praxissoftware Setup
🔧 Datenbank Einrichtung
${error ? `
❌ ${error}
` : ""}
Die Daten werden verschlüsselt gespeichert (config.enc).
Danach wirst du automatisch auf die Loginseite weitergeleitet.
`;
}
/* ===============================
MIDDLEWARE
================================ */
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(helmet());
// ✅ SessionStore dynamisch (Setup: MemoryStore, normal: MySQLStore)
app.use(
session({
name: "praxis.sid",
secret: process.env.SESSION_SECRET,
store: getSessionStore(),
resave: false,
saveUninitialized: false,
}),
);
// ✅ i18n Middleware
app.use((req, res, next) => {
const lang = req.session.lang || "de"; // Standard DE
const filePath = path.join(__dirname, "locales", `${lang}.json`);
const raw = fs.readFileSync(filePath, "utf-8");
res.locals.t = JSON.parse(raw); // t = translations
res.locals.lang = lang;
next();
});
const flashMiddleware = require("./middleware/flash.middleware");
app.use(flashMiddleware);
app.use(express.static("public"));
app.use("/uploads", express.static("uploads"));
app.set("view engine", "ejs");
app.use((req, res, next) => {
res.locals.user = req.session.user || null;
next();
});
/* ===============================
SETUP ROUTES
================================ */
// Setup-Seite
app.get("/setup", (req, res) => {
if (configExists()) return res.redirect("/");
return res.status(200).send(setupHtml());
});
// Setup speichern + DB testen + Soft-Restart + Login redirect
app.post("/setup", async (req, res) => {
try {
const { host, user, password, name } = req.body;
if (!host || !user || !password || !name) {
return res.status(400).send(setupHtml("Bitte alle Felder ausfüllen."));
}
// ✅ DB Verbindung testen
const conn = await mysql.createConnection({
host,
user,
password,
database: name,
});
await conn.query("SELECT 1");
await conn.end();
// ✅ verschlüsselt speichern
saveConfig({
db: { host, user, password, name },
});
// ✅ Soft-Restart (DB Pool + SessionStore neu laden)
if (typeof db.resetPool === "function") {
db.resetPool();
}
resetSessionStore();
// ✅ automatisch zurück zur Loginseite
return res.redirect("/");
} catch (err) {
return res
.status(500)
.send(setupHtml("DB Verbindung fehlgeschlagen: " + err.message));
}
});
// Wenn keine config.enc → alles außer /setup auf Setup umleiten
app.use((req, res, next) => {
if (!configExists() && req.path !== "/setup") {
return res.redirect("/setup");
}
next();
});
//Sprachen Route
// ✅ i18n Middleware (Sprache pro Benutzer über Session)
app.use((req, res, next) => {
const lang = req.session.lang || "de"; // Standard: Deutsch
let translations = {};
try {
const filePath = path.join(__dirname, "locales", `${lang}.json`);
translations = JSON.parse(fs.readFileSync(filePath, "utf-8"));
} catch (err) {
console.error("❌ i18n Fehler:", err.message);
}
// ✅ In EJS verfügbar machen
res.locals.t = translations;
res.locals.lang = lang;
next();
});
app.get("/lang/:lang", (req, res) => {
const newLang = req.params.lang;
if (!["de", "es"].includes(newLang)) {
return res.redirect(req.get("Referrer") || "/dashboard");
}
req.session.lang = newLang;
// ✅ WICHTIG: Session speichern bevor redirect
req.session.save((err) => {
if (err) console.error("❌ Session save error:", err);
return res.redirect(req.get("Referrer") || "/dashboard");
});
});
/* ===============================
DEINE LOGIK (unverändert)
================================ */
app.use(companySettingsRoutes);
app.use("/", authRoutes);
app.use("/dashboard", dashboardRoutes);
app.use("/admin", adminRoutes);
app.use("/patients", patientRoutes);
app.use("/patients", patientMedicationRoutes);
app.use("/patients", patientServiceRoutes);
app.use("/medications", medicationRoutes);
console.log("🧪 /medications Router mounted");
app.use("/services", serviceRoutes);
app.use("/", patientFileRoutes);
app.use("/", waitingRoomRoutes);
app.use("/", invoiceRoutes);
app.get("/logout", (req, res) => {
req.session.destroy(() => res.redirect("/"));
});
/* ===============================
ERROR HANDLING
================================ */
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send("Interner Serverfehler");
});
/* ===============================
SERVER
================================ */
const PORT = process.env.PORT || 51777;
const HOST = "127.0.0.1";
app.listen(PORT, HOST, () => {
console.log(`Server läuft auf http://${HOST}:${PORT}`);
});