/** * More info about this file: * https://v2.quasar.dev/quasar-cli-vite/developing-ssr/ssr-webserver * * Runs in Node context. */ /** * Make sure to yarn add / npm install (in your project root) * anything you import here (except for express and compression). */ import dotenv from 'dotenv'; import express from 'express'; import compression from 'compression'; import session from 'express-session'; import { PrismaSessionStore } from '@quixo3/prisma-session-store'; import { PrismaClient } from '@prisma/client'; import { v4 as uuidv4 } from 'uuid'; import pinoHttp from 'pino-http'; import apiRoutes from './routes/api.js'; import authRoutes from './routes/auth.js'; import chatRoutes from './routes/chat.js'; import settingsRoutes from './routes/settings.js'; import userPreferencesRoutes from './routes/userPreferences.js'; import mantisRoutes from './routes/mantis.js'; import cron from 'node-cron'; import { generateAndStoreMantisSummary } from './services/mantisSummarizer.js'; import { requireAuth } from './middlewares/authMiddleware.js'; import { setup as setupMantisDownloader } from './services/mantisDownloader.js'; import { logger } from './utils/logging.js'; import SuperJSON from 'superjson'; dotenv.config(); const httpLogger = pinoHttp({ logger }); // Define host and port with defaults const HOST = process.env.HOST || '0.0.0.0'; // Listen on all interfaces by default const PORT = parseInt(process.env.BACKEND_PORT || '9101', 10); const FRONTEND_PORT = parseInt(process.env.FRONTEND_PORT || '9100', 10); // Define Relying Party details (Update with your actual details) export const rpID = process.env.NODE_ENV === 'production' ? 'stylepoint.uk' : 'localhost'; export const rpName = 'StylePoint'; // Use the configured PORT for the origin URL export const origin = process.env.NODE_ENV === 'production' ? `https://${rpID}` : `http://${rpID}:${FRONTEND_PORT}`; export const challengeStore = new Map(); const prisma = new PrismaClient(); const app = express(); app.use(httpLogger); if(!process.env.SESSION_SECRET) { logger.error('SESSION_SECRET environment variable is not set. Please set it to a strong secret key.'); process.exit(1); // Exit the process if the secret is not set } // Session middleware configuration app.use(session({ genid: (req) => uuidv4(), // Use UUIDs for session IDs secret: process.env.SESSION_SECRET, // Use an environment variable for the secret resave: false, saveUninitialized: false, // Changed to false as recommended for session stores store: new PrismaSessionStore( // Use PrismaSessionStore prisma, { checkPeriod: 2 * 60 * 1000, //ms dbRecordIdIsSessionId: true, dbRecordIdFunction: undefined, } ), cookie: { secure: process.env.NODE_ENV === 'production', // Use secure cookies in production httpOnly: true, maxAge: 1000 * 60 * 60 * 24 // 1 day } })); // Schedule the Mantis summary task // Run daily at 1:00 AM server time (adjust as needed) cron.schedule('0 1 * * *', async() => { try { await generateAndStoreMantisSummary(); logger.info('Scheduled Mantis summary task completed successfully.'); } catch (error) { logger.error({ error }, 'Error running scheduled Mantis summary task'); } }, { scheduled: true, timezone: 'Europe/London' // Example: Set to your server's timezone }); // attackers can use this header to detect apps running Express // and then launch specifically-targeted attacks app.disable('x-powered-by'); // Add JSON body parsing middleware app.use(express.json()); app.use((req, res, next) => { res.json = (data) => { if (res.headersSent) { return; } res.setHeader('Content-Type', 'application/json'); res.send(SuperJSON.stringify(data)); }; next(); }); // Add API routes app.use('/api/auth', authRoutes); app.use('/api/chat', requireAuth, chatRoutes); app.use('/api/user-preferences', requireAuth, userPreferencesRoutes); app.use('/api/settings', requireAuth, settingsRoutes); app.use('/api/mantis', requireAuth, mantisRoutes); app.use('/api', requireAuth, apiRoutes); if (process.env.PROD) { app.use(compression()); } app.use(express.static('public', { index: false })); app.listen(PORT, HOST, () => { // Use the configured HOST and PORT in the log message logger.info(`Server is running on http://${HOST}:${PORT}`); setupMantisDownloader(); });