90 lines
2.4 KiB
JavaScript
90 lines
2.4 KiB
JavaScript
require('dotenv').config();
|
|
const express = require('express');
|
|
const { configureSecurityHeaders } = require('./middleware/securityHeaders');
|
|
const { adminLimiter } = require('./middleware/rateLimiter');
|
|
const adminRoutes = require('./routes/admin');
|
|
|
|
const adminApp = express();
|
|
const ADMIN_PORT = Number(process.env.ADMIN_PORT || 3005);
|
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
|
|
|
/**
|
|
* Trust proxy for correct IP detection
|
|
* Important: Only enable if behind a reverse proxy
|
|
*/
|
|
adminApp.set('trust proxy', process.env.TRUST_PROXY === 'true' ? true : 1);
|
|
|
|
configureSecurityHeaders(adminApp, isDevelopment);
|
|
|
|
adminApp.use((req, res, next) => {
|
|
const allowedOrigins = [
|
|
'http://localhost:3005',
|
|
'http://localhost:3000',
|
|
process.env.ADMIN_ORIGIN || '',
|
|
].filter(Boolean);
|
|
|
|
const origin = req.get('origin');
|
|
if (allowedOrigins.includes(origin)) {
|
|
res.setHeader('Access-Control-Allow-Origin', 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');
|
|
}
|
|
|
|
if (req.method === 'OPTIONS') {
|
|
return res.sendStatus(204);
|
|
}
|
|
|
|
next();
|
|
});
|
|
|
|
// Body parser
|
|
adminApp.use(express.json({ limit: '10mb' }));
|
|
adminApp.use(express.urlencoded({ limit: '10mb', extended: true }));
|
|
|
|
// Global rate limiting
|
|
adminApp.use(adminLimiter);
|
|
|
|
// Admin routes with /api/admin prefix
|
|
adminApp.use('/api/admin', adminRoutes);
|
|
|
|
// Health check endpoint
|
|
adminApp.get('/health', (req, res) => {
|
|
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
});
|
|
|
|
// 404 handler
|
|
adminApp.use((req, res) => {
|
|
res.status(404).json({
|
|
error: 'Not found',
|
|
path: req.path,
|
|
});
|
|
});
|
|
|
|
// Error handler
|
|
adminApp.use((err, req, res, next) => {
|
|
console.error('Unhandled error:', err);
|
|
|
|
if (isDevelopment) {
|
|
return res.status(500).json({
|
|
error: 'Internal server error',
|
|
message: err.message,
|
|
stack: err.stack,
|
|
});
|
|
}
|
|
|
|
return res.status(500).json({
|
|
error: 'Internal server error',
|
|
});
|
|
});
|
|
|
|
// Start admin server
|
|
function startAdminServer() {
|
|
adminApp.listen(ADMIN_PORT, () => {
|
|
console.log(`EaglerTiers Admin API running on http://localhost:${ADMIN_PORT}`);
|
|
console.log(`Admin endpoints require API key via Authorization header or ?key parameter`);
|
|
});
|
|
}
|
|
|
|
module.exports = { adminApp, startAdminServer };
|