feat: implement rating summary service methods and integrate rating display components into the organization header and pending ratings page

This commit is contained in:
2026-07-22 12:13:50 -03:00
parent 383a5bc6b4
commit da3c3abb52
27 changed files with 1334 additions and 104 deletions
+34
View File
@@ -2,6 +2,10 @@ import { Request, Response, NextFunction } from "express";
import { ApiValidationError } from "../Models/Server.Error.model";
const ipLastRequest = new Map<string, number>();
const ratingIpRequests = new Map<string, number[]>();
const RATING_RATE_LIMIT_WINDOW_MS = 60000;
const RATING_RATE_LIMIT_MAX_REQUESTS = 20;
// Limpia las IPs cada hora
setInterval(() => {
@@ -10,6 +14,14 @@ setInterval(() => {
ipLastRequest.forEach((time, ip) => {
if (now - time > timeLimit) ipLastRequest.delete(ip);
});
ratingIpRequests.forEach((times, ip) => {
const recentTimes = times.filter((time) => now - time <= RATING_RATE_LIMIT_WINDOW_MS);
if (recentTimes.length === 0) {
ratingIpRequests.delete(ip);
return;
}
ratingIpRequests.set(ip, recentTimes);
});
}, 3600000);
export async function rateLimiter(
@@ -31,3 +43,25 @@ export async function rateLimiter(
ipLastRequest.set(ip, currentTime);
next();
}
export async function ratingRateLimiter(
request: Request,
response: Response,
next: NextFunction
): Promise<void | Response | ApiValidationError> {
const ip = request.ip;
const currentTime = Date.now();
const windowStart = currentTime - RATING_RATE_LIMIT_WINDOW_MS;
const recentRequests = (ratingIpRequests.get(ip) || []).filter((time) => time > windowStart);
if (recentRequests.length >= RATING_RATE_LIMIT_MAX_REQUESTS) {
response
.status(429)
.json(new ApiValidationError(429, "Demasiadas solicitudes. Por favor espere!"));
return;
}
recentRequests.push(currentTime);
ratingIpRequests.set(ip, recentRequests);
next();
}