const express = require("express"); const path = require("path"); const session = require("express-session"); const bcrypt = require("bcrypt"); const pool = require("./config/database"); require("dotenv").config(); const app = express(); const MySQLStore = require('express-mysql-session')(session); const sessionStore = new MySQLStore({ clearExpired: true, checkExpirationInterval: 900000, // 15 นาที expiration: 86400000 // 24 ชั่วโมง }, pool); // Middleware isLoggedIn const isLoggedIn = (req, res, next) => { if (req.session.user) { next(); } else { res.redirect('/login'); } }; // Session Configuration app.use(session({ secret: process.env.SESSION_SECRET || "mysecret", resave: false, saveUninitialized: false, store: sessionStore, rolling: true, // ต่ออายุ session ทุก request cookie: { maxAge: 24 * 60 * 60 * 1000, // 24 hours secure: process.env.NODE_ENV === "production", // ใช้ secure ถ้าเป็น production httpOnly: true, sameSite: "strict" }, })); // Middleware app.use(express.static(path.join(__dirname, "public"))); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Middleware เช็ค Session app.use((req, res, next) => { console.log("Session Middleware Checked"); console.log("🔹 Session ID:", req.sessionID); console.log("🔹 Session Data:", req.session); next(); }); // View Engine app.set("view engine", "ejs"); app.set("views", path.join(__dirname, "views")); // Routes const orderRoutes = require("./shop-routes/order"); const cartRoutes = require("./shop-routes/cart"); const indexRoutes = require("./shop-routes/index"); app.use((req, res, next) => { res.locals.session = req.session; next(); }); app.use("/", indexRoutes); app.use("/cart", cartRoutes); app.use("/order", orderRoutes); // Checkout Route app.get('/order/checkout', isLoggedIn, (req, res) => { console.log("Session:", req.session); res.render('checkout', { user: req.session.user }); }); // Register Route (POST) app.post("/register", async (req, res) => { try { const { email, password, name } = req.body; if (!email || !password || !name) { return res.status(400).json({ message: "All fields are required." }); } const hashedPassword = await bcrypt.hash(password, 10); const [existingUser] = await pool.execute("SELECT * FROM users WHERE email = ?", [email]); if (existingUser.length > 0) { return res.status(400).json({ message: "Email is already registered." }); } await pool.execute("INSERT INTO users (email, password, name) VALUES (?, ?, ?)", [email, hashedPassword, name]); res.status(201).json({ success: true, message: "Registration successful." }); } catch (error) { console.error("Registration error:", error); res.status(500).json({ message: "Registration failed." }); } }); // Login Route (POST) app.post("/login", async (req, res) => { try { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ message: "All fields are required." }); } const [users] = await pool.execute("SELECT * FROM users WHERE email = ?", [email]); if (users.length === 0) { return res.status(400).json({ message: "Invalid email or password." }); } const user = users[0]; const passwordMatch = await bcrypt.compare(password, user.password); if (!passwordMatch) { return res.status(400).json({ message: "Invalid email or password." }); } req.session.regenerate((err) => { if (err) { console.error("Session regeneration failed:", err); return res.status(500).json({ message: "Login failed." }); } req.session.user = { id: user.id, email: user.email }; res.redirect('/order/checkout'); }); } catch (error) { console.error("Login error:", error); res.status(500).json({ message: "Login failed." }); } }); // เพิ่มฟังก์ชัน Logout router.get('/logout', (req, res) => { req.session.destroy((err) => { if (err) { console.error("Logout Error:", err); return res.status(500).json({ message: "เกิดข้อผิดพลาดขณะออกจากระบบ" }); } res.redirect('/login'); // หรือเปลี่ยนเป็นหน้าหลัก เช่น '/' }); }); // Logout Route app.post('/logout', (req, res) => { req.session.destroy(err => { if (err) { return res.status(500).json({ message: "Logout failed" }); } res.clearCookie('connect.sid'); res.status(200).json({ message: "Logged out successfully" }); }); }); // Search Route (ป้องกัน SQL Injection) app.get("/search", async (req, res) => { const searchQuery = req.query.query; try { const sanitizedQuery = searchQuery.replace(/[%_]/g, "\\$&"); const [results] = await pool.execute( "SELECT * FROM products WHERE name LIKE ? OR description LIKE ?", [`%${sanitizedQuery}%`, `%${sanitizedQuery}%`] ); res.render("index", { products: results }); } catch (err) { console.error(err); res.status(500).send("Error retrieving search results"); } }); // Error handler app.use((err, req, res, next) => { console.error("Error:", err.stack); res.status(500).json({ message: "Something went wrong." }); }); // Start Server const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`));