import { Request, Response, NextFunction } from 'express';
import { ApiKeyService } from './api-key-service.js';
// Extend Express session type
declare module 'express-session' {
interface SessionData {
userId?: number;
username?: string;
}
}
// Session-based auth for web UI
export function requireSession(req: Request, res: Response, next: NextFunction): void {
if (req.session?.userId) {
return next();
}
// If it's an HTML page request, redirect to login
if (req.accepts('html')) {
res.redirect('/login');
return;
}
res.status(401).json({ error: 'Authentication required' });
}
// API Key auth for API endpoints
export function createApiKeyAuth(apiKeyService: ApiKeyService) {
return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
// Skip auth for public routes
const publicPaths = ['/health', '/', '/login', '/api/auth/login', '/docs'];
if (publicPaths.includes(req.path) || req.path.startsWith('/public/')) {
return next();
}
// For web portal routes, check session
if (req.path === '/dashboard') {
if (req.session?.userId) {
return next();
}
res.redirect('/login');
return;
}
// For API routes, check API key OR session
const apiKey = req.headers['x-api-key'] as string;
if (apiKey) {
const result = await apiKeyService.validateApiKey(apiKey);
if (result) {
(req as any).apiUser = result;
return next();
}
res.status(403).json({ error: 'Invalid API key' });
return;
}
// Allow session-authenticated users to use API
if (req.session?.userId) {
return next();
}
res.status(401).json({ error: 'API key required. Include x-api-key header.' });
};
}