feat(auth): wire auth middleware in app, protect all /api endpoints

This commit is contained in:
2026-05-20 23:00:20 +02:00
parent 9ca025f128
commit bb0d9d7d01

View File

@@ -1,24 +1,41 @@
import express, { type Express, type NextFunction, type Request, type Response } from 'express';
import cookieParser from 'cookie-parser';
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
import express, { type Express, type NextFunction, type Request, type Response } from 'express';
import { ZodError } from 'zod';
import type { Db } from './db/client.js';
import { ApiError } from './lib/errors.js';
import { cardsRouter } from './routes/cards.js';
import { currentUserOrNull, requireAuth, requireRole } from './middleware/auth.js';
import { ensureCsrfToken, verifyCsrf } from './middleware/csrf.js';
import { authRouter } from './routes/auth.js';
import { adminUsersRouter } from './routes/admin-users.js';
import { lessonsRouter } from './routes/lessons.js';
import { cardsRouter } from './routes/cards.js';
import { sessionsRouter } from './routes/sessions.js';
import { statsRouter } from './routes/stats.js';
export function createApp(db: Db): Express {
const app = express();
app.set('trust proxy', 1);
app.use(cookieParser());
app.use(express.json({ limit: '5mb' }));
app.use(ensureCsrfToken);
app.use(currentUserOrNull(db));
app.get('/api/health', (_req, res) => res.json({ ok: true }));
app.use('/api/lessons', lessonsRouter(db));
app.use('/api', cardsRouter(db));
app.use('/api/sessions', sessionsRouter(db));
app.use('/api/stats', statsRouter(db));
// Public auth endpoints (logout/profile/change-password have their own requireAuth + verifyCsrf
// applied inside the router; public ones bootstrap cookies so CSRF cannot apply yet).
app.use('/api/auth', authRouter(db));
// Protected app routes
app.use('/api/lessons', requireAuth, verifyCsrf, lessonsRouter(db));
app.use('/api', requireAuth, verifyCsrf, cardsRouter(db));
app.use('/api/sessions', requireAuth, verifyCsrf, sessionsRouter(db));
app.use('/api/stats', requireAuth, statsRouter(db));
app.use('/api/admin/users', requireAuth, requireRole('sysadmin'), verifyCsrf, adminUsersRouter(db));
// Static frontend in production
const frontendDist = resolve(import.meta.dirname, '../../frontend/dist');
if (existsSync(frontendDist)) {
app.use(express.static(frontendDist));