refactoring: TypeScript migration, security fixes,

This commit is contained in:
Maurice
2026-03-27 18:40:18 +01:00
parent 510475a46f
commit 8396a75223
150 changed files with 8116 additions and 8467 deletions

View File

@@ -0,0 +1,71 @@
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import { db } from '../db/database';
import { JWT_SECRET } from '../config';
import { AuthRequest, OptionalAuthRequest, User } from '../types';
const authenticate = (req: Request, res: Response, next: NextFunction): void => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
res.status(401).json({ error: 'Access token required' });
return;
}
try {
const decoded = jwt.verify(token, JWT_SECRET) as { id: number };
const user = db.prepare(
'SELECT id, username, email, role FROM users WHERE id = ?'
).get(decoded.id) as User | undefined;
if (!user) {
res.status(401).json({ error: 'User not found' });
return;
}
(req as AuthRequest).user = user;
next();
} catch (err: unknown) {
res.status(401).json({ error: 'Invalid or expired token' });
}
};
const optionalAuth = (req: Request, res: Response, next: NextFunction): void => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
(req as OptionalAuthRequest).user = null;
return next();
}
try {
const decoded = jwt.verify(token, JWT_SECRET) as { id: number };
const user = db.prepare(
'SELECT id, username, email, role FROM users WHERE id = ?'
).get(decoded.id) as User | undefined;
(req as OptionalAuthRequest).user = user || null;
} catch (err: unknown) {
(req as OptionalAuthRequest).user = null;
}
next();
};
const adminOnly = (req: Request, res: Response, next: NextFunction): void => {
const authReq = req as AuthRequest;
if (!authReq.user || authReq.user.role !== 'admin') {
res.status(403).json({ error: 'Admin access required' });
return;
}
next();
};
const demoUploadBlock = (req: Request, res: Response, next: NextFunction): void => {
const authReq = req as AuthRequest;
if (process.env.DEMO_MODE === 'true' && authReq.user?.email === 'demo@nomad.app') {
res.status(403).json({ error: 'Uploads are disabled in demo mode. Self-host NOMAD for full functionality.' });
return;
}
next();
};
export { authenticate, optionalAuth, adminOnly, demoUploadBlock };