- Add scan login service with Redis-based token management - Add scan login API routes for token generation and validation - Add QRCodeLogin component for PC-side QR code display - Add EntryQRCode component for mass login scenarios - Add ScanLoginView for mobile-side login form - Add localStorage persistence for user identity - Add logout functionality to mobile client - Add auto-redirect for logged-in users - Add admin console control for QR code display on big screen - Add socket event forwarding from admin to screen display Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
72 lines
1.7 KiB
TypeScript
72 lines
1.7 KiB
TypeScript
import express, { Application } from 'express';
|
|
import cors from 'cors';
|
|
import helmet from 'helmet';
|
|
import compression from 'compression';
|
|
import { config } from './config';
|
|
import { logger } from './utils/logger';
|
|
import { errorHandler } from './middleware/errorHandler';
|
|
import { requestLogger } from './middleware/requestLogger';
|
|
import voteRoutes from './routes/vote.routes';
|
|
import adminRoutes from './routes/admin.routes';
|
|
import scanRoutes from './routes/scan.routes';
|
|
|
|
export const app: Application = express();
|
|
|
|
// CORS - must be before helmet
|
|
app.use(
|
|
cors({
|
|
origin: function (origin, callback) {
|
|
// Allow requests with no origin (like mobile apps or curl)
|
|
if (!origin) return callback(null, true);
|
|
|
|
const allowedOrigins = [
|
|
'http://localhost:5173',
|
|
'http://localhost:5174',
|
|
'http://192.168.1.5:5173',
|
|
'http://192.168.1.5:5174',
|
|
];
|
|
|
|
if (allowedOrigins.includes(origin)) {
|
|
callback(null, true);
|
|
} else {
|
|
console.log('CORS blocked origin:', origin);
|
|
callback(null, true); // Allow all for development
|
|
}
|
|
},
|
|
credentials: true,
|
|
})
|
|
);
|
|
|
|
// Security middleware
|
|
app.use(helmet());
|
|
|
|
// Compression
|
|
app.use(compression());
|
|
|
|
// Body parsing
|
|
app.use(express.json({ limit: '1mb' }));
|
|
app.use(express.urlencoded({ extended: true }));
|
|
|
|
// Request logging
|
|
app.use(requestLogger);
|
|
|
|
// Health check
|
|
app.get('/health', (_req, res) => {
|
|
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
});
|
|
|
|
// API routes
|
|
app.use('/api/vote', voteRoutes);
|
|
app.use('/api/admin', adminRoutes);
|
|
app.use('/api/scan', scanRoutes);
|
|
|
|
// 404 handler
|
|
app.use((_req, res) => {
|
|
res.status(404).json({ error: 'Not Found' });
|
|
});
|
|
|
|
// Error handler
|
|
app.use(errorHandler);
|
|
|
|
export { logger };
|