import { ErrorRequestHandler, Request, RequestHandler } from 'express'; import { randomUUID } from 'crypto'; import { validationResult, matchedData } from 'express-validator'; import { UserInfo, UserRoles } from '@core'; declare module 'express-session' { interface SessionData { user: UserInfo | null; } } export function getRequestId(req: Request): string { return req.header('x-request-id') || 'unknown'; } export function RequestId(): RequestHandler { return (req, res, next) => { req.headers['x-request-id'] = randomUUID(); next(); }; } export function CheckPermissions(): RequestHandler { function getResourceId(req: Request): string | undefined { if (req.params.uuid) return req.params.uuid; if (req.body.uuid) return req.body.uuid; return undefined; } function canAccessRessource(user: UserInfo, uuid: string): boolean { if (user.uuid === uuid) return true; return false; } return (req, res, next) => { if (!req.session.user) { return next({ status: 401, messsage: 'Unauthorized' }); } if (req.session.user.role === UserRoles.ADMIN) { return next(); } const ressourceId = getResourceId(req); if (!ressourceId) { return next({ status: 403, messsage: 'Forbidden' }); } if (canAccessRessource(req.session.user, ressourceId)) { return next(); } next({ status: 403, messsage: 'Forbidden' }); }; } export function ValidateSchema(): RequestHandler { return (req, res, next) => { const error = validationResult(req); const oldBody = req.body; req.body = matchedData(req, { locations: ['body'] }); if (JSON.stringify(oldBody) !== JSON.stringify(req.body)) return next({ status: 422, message: 'Unprocessable Entity', }); error.isEmpty() ? next() : next({ status: 400, ...error, }); }; } export function ErrorHandler(): ErrorRequestHandler { return (error, req, res, next) => { error.status ? res.status(error.status).send(error) : res.status(500).send({ status: 500, message: error.message }); }; }