const express = require("express"); const dotenv = require("dotenv"); const path = require("path"); const cookieParser = require("cookie-parser"); const session = require("express-session"); const flash = require("connect-flash"); const expressLayouts = require("express-ejs-layouts"); const fs = require("fs"); // Load environment variables dotenv.config(); const connectDB = require("./config/database"); // Connect to MongoDB connectDB(); // Initialize express app const app = express(); // Set view engine app.set("view engine", "ejs"); app.set("views", path.join(__dirname, "views")); // Set up express-ejs-layouts app.use(expressLayouts); app.set("layout", "layouts/main"); app.set("layout extractScripts", true); app.set("layout extractStyles", true); // Middlewares app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cookieParser()); app.use( "/assets", (req, res, next) => { // Cho phép mọi domain truy cập tài nguyên tĩnh res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Methods", "GET"); next(); }, express.static(path.join(__dirname, "assets")), ); // Session configuration app.use( session({ secret: process.env.SESSION_SECRET || "secret", resave: false, saveUninitialized: false, cookie: { maxAge: 1000 * 60 * 60 * 24 }, // 24 hours }), ); // Flash messages app.use(flash()); // Global variables app.use((req, res, next) => { // Lấy flash messages const success_msg = req.flash("success_msg"); const error_msg = req.flash("error_msg"); const error = req.flash("error"); // Lưu vào res.locals để sử dụng trong views res.locals.success_msg = success_msg.length > 0 ? success_msg[0] : null; res.locals.error_msg = error_msg.length > 0 ? error_msg[0] : null; res.locals.error = error.length > 0 ? error[0] : null; // Tạo object flashMessages để sử dụng trong client-side JavaScript res.locals.flashMessagesJSON = JSON.stringify({ success_msg: res.locals.success_msg, error_msg: res.locals.error_msg, error: res.locals.error, }); res.locals.user = req.session.user || null; res.locals.currentPath = req.path; next(); }); // Kiểm tra và tạo thư mục data nếu chưa tồn tại const dataDir = path.join(__dirname, "data"); if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir); } // Frontend URL configuration const FRONTEND_URL = process.env.FRONTEND_URL; // Add frontend URL to res.locals for all requests app.use((req, res, next) => { res.locals.frontendUrl = FRONTEND_URL; res.locals.currentPath = req.path; next(); }); // Simple CORS middleware for API endpoints app.use((req, res, next) => { // Allow requests from configured FRONTEND_URL or allow all if not set const origin = req.headers.origin; const allowedOrigin = FRONTEND_URL || "*"; if (allowedOrigin === "*" || origin === allowedOrigin) { res.setHeader( "Access-Control-Allow-Origin", allowedOrigin === "*" ? "*" : origin, ); res.setHeader( "Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS", ); res.setHeader( "Access-Control-Allow-Headers", "Content-Type, Authorization", ); res.setHeader("Access-Control-Allow-Credentials", "true"); } // Handle preflight if (req.method === "OPTIONS") { return res.sendStatus(204); } next(); }); // Routes const authRoutes = require("./routes/auth"); const adminRoutes = require("./routes/admin"); const indexRoutes = require("./routes/index"); app.use("/auth", authRoutes); app.use("/admin", adminRoutes); app.use("/", indexRoutes); // 404 handler app.use((req, res) => { res.status(404); if (req.accepts("html")) return res.render("page/404", { title: "404 - Page Not Found", layout: "layouts/main", }); if (req.accepts("json")) return res.json({ error: "Not found" }); res.type("txt").send("Not found"); }); // Start server const PORT = process.env.PORT || 3001; const HOST = process.env.HOST || "localhost"; app.listen(PORT, HOST, () => { console.log(`🚀 SERVER:[ http://${HOST}:${PORT} ]`); });