/*********************************************************************************************************************************************************************** * File Name: server.js * Type of Program: Application Entry Point * Description: Bootstraps the Express application. * Registers global middleware (CORS, rate-limit, cookie-parser, * session, Passport) and mounts all route groups. * Syncs Sequelize models to the database on startup. * * Author: rgrgogu * Date Created: Oct. 6, 2025 *********************************************************************************************************************************************************************** * HOW TO RUN: * 1. cp .env.example .env (fill in your values) * 2. npm install * 3. npm run dev (development) * npm start (production) ***********************************************************************************************************************************************************************/ require('dotenv').config(); const express = require('express'); const cors = require('cors'); const cookieParser = require('cookie-parser'); const session = require('express-session'); const passport = require('./config/passport.config'); const sequelize = require('./config/db.config'); // ── Middleware ────────────────────────────────────────────────────────────────── const { globalLimiter } = require('./middleware/rateLimiter.middleware'); const { csrfErrorHandler } = require('./middleware/csrf.middleware'); // ── Routes ───────────────────────────────────────────────────────────────────── const authRoutes = require('./routes/auth.routes'); const clientRoutes = require('./routes/client/client.routes'); const staffRoutes = require('./routes/staff/staff.routes'); const adminRoutes = require('./routes/admin/admin.routes'); // ── Models (ensure associations are loaded) ──────────────────────────────────── require('./models/users/users.mdl'); require('./models/users/user_sessions.mdl'); require('./models/users/user_groups.mdl'); const app = express(); const PORT = process.env.PORT || 3000; // ────────────────────────────────────────────────────────────────────────────── // Global Middleware Stack // ────────────────────────────────────────────────────────────────────────────── app.set('trust proxy', 1); // Required for rate-limiter behind proxies/load balancers app.use(cors({ origin: process.env.APP_URL || '*', credentials: true, })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(cookieParser()); // Session — used only by csurf; JWT handles auth state app.use(session({ secret: process.env.SESSION_SECRET || 'change-me', resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', httpOnly: true, sameSite: 'strict' }, })); app.use(passport.initialize()); // Global rate limiter (1000 req / 15 min) app.use(globalLimiter); // ────────────────────────────────────────────────────────────────────────────── // Routes // ────────────────────────────────────────────────────────────────────────────── app.use('/api/auth', authRoutes); app.use('/api/client', clientRoutes); app.use('/api/staff', staffRoutes); app.use('/api/admin', adminRoutes); // Health check app.get('/api/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), env: process.env.NODE_ENV }); }); // 404 handler app.use((req, res) => { res.status(404).json({ status: 'error', message: 'Route not found.' }); }); // CSRF error handler (must be after routes) app.use(csrfErrorHandler); // Global error handler app.use((err, req, res, next) => { console.error('[UNHANDLED ERROR]', err); res.status(500).json({ status: 'error', message: 'Internal server error.' }); }); // ────────────────────────────────────────────────────────────────────────────── // Database Sync + Listen // ────────────────────────────────────────────────────────────────────────────── (async () => { try { await sequelize.authenticate(); console.log('✅ Database connected.'); app.listen(PORT, () => { console.log(`🚀 STARR Server running on http://localhost:${PORT}`); console.log(` Environment : ${process.env.NODE_ENV}`); }); } catch (err) { console.error('❌ Failed to start server:', err); process.exit(1); } })();