import express from 'express'; import helmet from 'helmet'; import morgan from 'morgan'; import dotenv from 'dotenv'; import cookieParser from 'cookie-parser'; import { UserService } from './services/user.service'; import { SSOUserData } from './types/auth.types'; import { sequelize } from './config/database'; import { corsMiddleware } from './middlewares/cors.middleware'; import routes from './routes/index'; import { ensureUploadDir, UPLOAD_DIR } from './config/storage'; import path from 'path'; // Load environment variables dotenv.config(); const app: express.Application = express(); const userService = new UserService(); // Initialize database connection const initializeDatabase = async () => { try { await sequelize.authenticate(); } catch (error) { console.error('❌ Database connection failed:', error); } }; // Initialize database initializeDatabase(); // CORS middleware - MUST be before other middleware app.use(corsMiddleware); // Security middleware - Configure Helmet to work with CORS app.use(helmet({ crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: { policy: "cross-origin" }, contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], scriptSrc: ["'self'"], imgSrc: ["'self'", "data:", "https:"], }, }, })); // Cookie parser middleware - MUST be before routes app.use(cookieParser()); // Body parsing middleware app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); // Logging middleware app.use(morgan('combined')); // Health check endpoint app.get('/health', (_req: express.Request, res: express.Response) => { res.status(200).json({ status: 'OK', timestamp: new Date(), uptime: process.uptime(), environment: process.env.NODE_ENV || 'development' }); }); // Mount API routes app.use('/api/v1', routes); // Serve uploaded files statically ensureUploadDir(); app.use('/uploads', express.static(UPLOAD_DIR)); // Root endpoint app.get('/', (_req: express.Request, res: express.Response) => { res.status(200).json({ message: 'Royal Enfield Workflow Management System API', version: '1.0.0', status: 'running', timestamp: new Date() }); }); // Legacy SSO Callback endpoint for user creation/update (kept for backward compatibility) app.post('/api/v1/auth/sso-callback', async (req: express.Request, res: express.Response): Promise => { try { const ssoData: SSOUserData = req.body; // Validate required fields - email and oktaSub are required if (!ssoData.email || !ssoData.oktaSub) { res.status(400).json({ success: false, message: 'Missing required fields: email and oktaSub are required', timestamp: new Date() }); return; } // Create or update user const user = await userService.createOrUpdateUser(ssoData); res.status(200).json({ success: true, message: 'User processed successfully', data: { user: { userId: user.userId, employeeId: user.employeeId || null, oktaSub: user.oktaSub, email: user.email, firstName: user.firstName || null, lastName: user.lastName || null, displayName: user.displayName || null, department: user.department || null, designation: user.designation || null, phone: user.phone || null, location: user.location || null, isAdmin: user.isAdmin, lastLogin: user.lastLogin }, isNewUser: user.createdAt.getTime() === user.updatedAt.getTime() }, timestamp: new Date() }); } catch (error) { console.error('❌ SSO Callback failed:', error); res.status(500).json({ success: false, message: 'Internal server error', timestamp: new Date() }); } }); // Get all users endpoint app.get('/api/v1/users', async (_req: express.Request, res: express.Response): Promise => { try { const users = await userService.getAllUsers(); res.status(200).json({ success: true, message: 'Users retrieved successfully', data: { users: users.map(user => ({ userId: user.userId, employeeId: user.employeeId || null, oktaSub: user.oktaSub, email: user.email, firstName: user.firstName || null, lastName: user.lastName || null, displayName: user.displayName || null, department: user.department || null, designation: user.designation || null, phone: user.phone || null, location: user.location || null, isAdmin: user.isAdmin, lastLogin: user.lastLogin, createdAt: user.createdAt })), total: users.length }, timestamp: new Date() }); } catch (error) { console.error('❌ Get Users failed:', error); res.status(500).json({ success: false, message: 'Internal server error', timestamp: new Date() }); } }); // Error handling middleware app.use((req: express.Request, res: express.Response) => { res.status(404).json({ success: false, message: `Route ${req.originalUrl} not found`, timestamp: new Date(), }); }); export default app;