import express, { Router } from 'express'; import cors from 'cors'; import path from 'path'; import { fileURLToPath } from 'url'; import { apiRouter } from './routes.js'; import { sseRouter } from './sse.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); const PORT = parseInt(process.env.PORT || '3001', 10); const APP_PASSWORD = process.env.APP_PASSWORD || 'UNIKAT_jury'; app.use(cors()); app.use(express.json()); // Health check (no auth required) app.get('/api/health', (_req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); // Password protection middleware app.use((req, res, next) => { if (req.path === '/api/health') { next(); return; } // Check query param const token = req.query.token as string | undefined; if (token === APP_PASSWORD) { res.cookie('jury_auth', APP_PASSWORD, { httpOnly: true, maxAge: 24 * 60 * 60 * 1000 }); if (!req.path.startsWith('/api')) { res.redirect(req.path || '/'); return; } next(); return; } // Check cookie const cookieHeader = req.headers.cookie || ''; const cookies = Object.fromEntries( cookieHeader.split(';').map(c => { const [key, ...val] = c.trim().split('='); return [key, val.join('=')]; }) ); if (cookies.jury_auth === APP_PASSWORD) { next(); return; } // Not authenticated if (req.path.startsWith('/api')) { res.status(401).json({ error: 'Unauthorized' }); return; } // Login page res.status(401).send(` UNIKAT Jury Voting

🗳️ Jury Voting

15. UNIKAT Ideenwettbewerb

`); }); // API routes app.use(apiRouter); app.use(sseRouter); // Serve static frontend in production const distPath = path.resolve(__dirname, '..', 'dist'); if (process.env.NODE_ENV === 'production') { app.use(express.static(distPath)); app.use((_req, res) => { res.sendFile(path.join(distPath, 'index.html')); }); } app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); }); export default app;