All checks were successful
Build & Push Docker Image / build (push) Successful in 6m25s
82 lines
2.9 KiB
JavaScript
82 lines
2.9 KiB
JavaScript
import 'dotenv/config';
|
||
import express from 'express';
|
||
import cors from 'cors';
|
||
import path from 'path';
|
||
import { fileURLToPath } from 'url';
|
||
import { log } from './config/logger.js';
|
||
import requestResponseLogger from './middleware/logging.js';
|
||
import { initDatabase } from './config/database.js';
|
||
import { initMailer } from './config/mailer.js';
|
||
import authRoutes from './routes/auth.js';
|
||
import roomRoutes from './routes/rooms.js';
|
||
import recordingRoutes from './routes/recordings.js';
|
||
import adminRoutes from './routes/admin.js';
|
||
import brandingRoutes from './routes/branding.js';
|
||
import federationRoutes, { wellKnownHandler } from './routes/federation.js';
|
||
import calendarRoutes from './routes/calendar.js';
|
||
import { startFederationSync } from './jobs/federationSync.js';
|
||
|
||
const __filename = fileURLToPath(import.meta.url);
|
||
const __dirname = path.dirname(__filename);
|
||
|
||
const app = express();
|
||
const PORT = process.env.PORT || 3001;
|
||
|
||
// Trust proxy – configurable via TRUST_PROXY env var (default: 1 = one local reverse proxy)
|
||
// Use a number to trust that many hops, or a string like 'loopback' / an IP/CIDR.
|
||
const rawTrustProxy = process.env.TRUST_PROXY ?? 'loopback';
|
||
const trustProxy = /^\d+$/.test(rawTrustProxy) ? parseInt(rawTrustProxy, 10) : rawTrustProxy;
|
||
app.set('trust proxy', trustProxy);
|
||
|
||
// Middleware
|
||
// M10: restrict CORS in production; allow all in development
|
||
const corsOptions = process.env.APP_URL
|
||
? { origin: process.env.APP_URL, credentials: true }
|
||
: {};
|
||
app.use(cors(corsOptions));
|
||
app.use(express.json());
|
||
// Request/Response logging (filters sensitive fields)
|
||
app.use(requestResponseLogger);
|
||
|
||
// Initialize database & start server
|
||
async function start() {
|
||
await initDatabase();
|
||
initMailer();
|
||
|
||
// Serve uploaded files (avatars, presentations)
|
||
const uploadsPath = path.join(__dirname, '..', 'uploads');
|
||
app.use('/uploads', express.static(uploadsPath));
|
||
|
||
// API Routes
|
||
app.use('/api/auth', authRoutes);
|
||
app.use('/api/rooms', roomRoutes);
|
||
app.use('/api/recordings', recordingRoutes);
|
||
app.use('/api/admin', adminRoutes);
|
||
app.use('/api/branding', brandingRoutes);
|
||
app.use('/api/federation', federationRoutes);
|
||
app.use('/api/calendar', calendarRoutes);
|
||
// Mount calendar federation receive also under /api/federation for remote instances
|
||
app.use('/api/federation', calendarRoutes);
|
||
app.get('/.well-known/redlight', wellKnownHandler);
|
||
|
||
// Serve static files in production
|
||
if (process.env.NODE_ENV === 'production') {
|
||
app.use(express.static(path.join(__dirname, '..', 'dist')));
|
||
app.get('*', (req, res) => {
|
||
res.sendFile(path.join(__dirname, '..', 'dist', 'index.html'));
|
||
});
|
||
}
|
||
|
||
app.listen(PORT, () => {
|
||
log.server.info(`Redlight server running on http://localhost:${PORT}`);
|
||
});
|
||
|
||
// Start periodic federation sync job (checks remote room settings every 60s)
|
||
startFederationSync();
|
||
}
|
||
|
||
start().catch(err => {
|
||
log.server.error(`Failed to start server: ${err.message}`);
|
||
process.exit(1);
|
||
});
|