Files
v3-api/src/auth/guards/ip-rate-limiter.guard.ts

49 lines
1.6 KiB
TypeScript

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Request, Response } from 'express';
import { rateLimit } from 'express-rate-limit';
@Injectable()
export class IpRateLimiterGuard implements CanActivate {
private readonly limiter: ReturnType<typeof rateLimit>;
constructor(private readonly configService: ConfigService) {
const isProduction = this.configService.get('NODE_ENV') === 'production';
this.limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: isProduction ? 50 : 100, // Stricter in production
standardHeaders: false,
legacyHeaders: false,
skip: () =>
!isProduction &&
this.configService.get('DISABLE_RATE_LIMIT') === 'true', // Skip in dev if needed
keyGenerator: (req) => {
// Use IP or user ID if available
return isProduction ? req.ip : ''; // Less strict in development
},
handler: (req, res) => {
res.status(429).json({
statusCode: 429,
message: isProduction
? 'Too many requests'
: 'Dev Mode: Rate limit warning (not enforced)',
});
},
});
}
async canActivate(context: ExecutionContext): Promise<boolean> {
const httpContext = context.switchToHttp();
const req = httpContext.getRequest<Request>();
const res = httpContext.getResponse<Response>();
return new Promise((resolve) => {
this.limiter(req, res, (err?: unknown) => {
if (err) {
return resolve(false);
}
resolve(true);
});
});
}
}