File: /var/www/api-management/src/middleware/auditor.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { AuditService } from '../app/auditor/services/auditor.service';
import { JwtService } from '@nestjs/jwt';
import { TokenExpiredError } from 'jsonwebtoken';
import { Audit } from '../app/auditor/schemas/audit.schema';
import { Types } from 'mongoose';
import messages from '../shared/messages/messages';
@Injectable()
export class AuditMiddleware implements NestMiddleware {
constructor(
private readonly auditService: AuditService,
private readonly jwtService: JwtService,
) {}
async use(req: Request, res: Response, next: NextFunction) {
const { method, originalUrl, headers, body } = req;
const originalSend = res.send;
res.send = function (data, ...restArgs) {
res.locals.data = data;
return originalSend.apply(res, [data, ...restArgs]);
};
let tokenExpiredAt: Date | null = null;
let userId: Types.ObjectId | null = null;
if (headers.authorization) {
const token = headers.authorization.split(' ')[1];
try {
const decoded = this.jwtService.verify(token, {
secret: process.env.JWT_SECRET,
});
userId = new Types.ObjectId(decoded.sub);
} catch (e) {
if (e instanceof TokenExpiredError) {
tokenExpiredAt = e.expiredAt;
return res.status(401).json({
status: 401,
message: messages.error.token.message,
error: messages.error.token.summary,
});
} else {
return res.status(401).json({
status: 401,
message: messages.error.token.message,
error: messages.error.token.summary,
});
}
}
}
res.on('finish', async () => {
const response = res.locals.data || {};
// Verificar si `userId` es `null` antes de intentar registrar la auditorÃa
if (userId) {
const auditLog = {
userId,
method,
url: originalUrl,
headers,
body,
response:
typeof response === 'string' ? JSON.parse(response) : response,
tokenExpiredAt,
} as unknown as Partial<Audit>;
await this.auditService.log(auditLog);
}
});
next();
}
}