import { Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; import { PrismaClient } from '@prisma/client'; import { AuthRequest, JwtPayload } from '../types/index.js'; const prisma = new PrismaClient(); export async function authenticate( req: AuthRequest, res: Response, next: NextFunction ): Promise { const authHeader = req.headers.authorization; // Token aus Header oder Query-Parameter (für Downloads) let token: string | null = null; if (authHeader && authHeader.startsWith('Bearer ')) { token = authHeader.split(' ')[1]; } else if (req.query.token && typeof req.query.token === 'string') { // Fallback für Downloads: Token als Query-Parameter token = req.query.token; } if (!token) { res.status(401).json({ success: false, error: 'Nicht authentifiziert' }); return; } try { const decoded = jwt.verify( token, process.env.JWT_SECRET || 'fallback-secret' ) as JwtPayload; // Prüfen ob Token durch Rechteänderung invalidiert wurde (nur für Mitarbeiter) if (decoded.userId && decoded.iat) { const user = await prisma.user.findUnique({ where: { id: decoded.userId }, select: { tokenInvalidatedAt: true, isActive: true }, }); // Benutzer nicht gefunden oder deaktiviert if (!user || !user.isActive) { res.status(401).json({ success: false, error: 'Benutzer nicht mehr aktiv' }); return; } // Token wurde vor der Invalidierung ausgestellt if (user.tokenInvalidatedAt) { const tokenIssuedAt = decoded.iat * 1000; // iat ist in Sekunden, Date ist in Millisekunden if (tokenIssuedAt < user.tokenInvalidatedAt.getTime()) { res.status(401).json({ success: false, error: 'Ihre Berechtigungen wurden geändert. Bitte melden Sie sich erneut an.', }); return; } } } req.user = decoded; next(); } catch { res.status(401).json({ success: false, error: 'Ungültiger Token' }); } } export function requirePermission(...requiredPermissions: string[]) { return (req: AuthRequest, res: Response, next: NextFunction): void => { if (!req.user) { res.status(401).json({ success: false, error: 'Nicht authentifiziert' }); return; } const userPermissions = req.user.permissions || []; // Check if user has any of the required permissions const hasPermission = requiredPermissions.some((perm) => userPermissions.includes(perm) ); if (!hasPermission) { res.status(403).json({ success: false, error: 'Keine Berechtigung für diese Aktion', }); return; } next(); }; } // Middleware to check if user can access specific customer data export function requireCustomerAccess( req: AuthRequest, res: Response, next: NextFunction ): void { if (!req.user) { res.status(401).json({ success: false, error: 'Nicht authentifiziert' }); return; } const userPermissions = req.user.permissions || []; // Admins and employees can access all customers if ( userPermissions.includes('customers:read') || userPermissions.includes('customers:update') ) { next(); return; } // Customers can only access their own data const customerId = parseInt(req.params.customerId || req.params.id); if (req.user.customerId && req.user.customerId === customerId) { next(); return; } res.status(403).json({ success: false, error: 'Kein Zugriff auf diese Kundendaten', }); }