Files
edr-platform/apps/edr-passenger-api/src/common/dynamic-throttler.guard.ts
2026-07-02 22:42:15 +03:00

58 lines
2.4 KiB
TypeScript

import { Injectable, ExecutionContext, Inject } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ThrottlerGuard, ThrottlerStorage, getOptionsToken, getStorageToken } from '@nestjs/throttler';
import { SystemConfigService, CONFIG_KEYS } from '../modules/system-config/system-config.service';
// Route-prefix → throttler tier mapping.
// Evaluated in order; first match wins.
const ROUTE_TIERS: Array<{ prefix: string; tier: 'auth' | 'strict' | 'default' }> = [
{ prefix: '/auth', tier: 'auth' },
{ prefix: '/fayda/verification',tier: 'auth' },
{ prefix: '/bookings', tier: 'strict' },
{ prefix: '/passengers', tier: 'strict' },
{ prefix: '/payments', tier: 'strict' },
{ prefix: '/wallet', tier: 'strict' },
];
@Injectable()
export class DynamicThrottlerGuard extends ThrottlerGuard {
constructor(
@Inject(getOptionsToken()) options: any,
@Inject(getStorageToken()) storageService: ThrottlerStorage,
reflector: Reflector,
private readonly systemConfig: SystemConfigService,
) {
super(options, storageService, reflector);
}
async canActivate(context: ExecutionContext): Promise<boolean> {
if (context.getType() !== 'http') {
return true;
}
const [authLimit, authTtl, strictLimit, strictTtl, defaultLimit, defaultTtl] =
await Promise.all([
this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_AUTH_LIMIT),
this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_AUTH_TTL_MS),
this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_STRICT_LIMIT),
this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_STRICT_TTL_MS),
this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_DEFAULT_LIMIT),
this.systemConfig.getNumber(CONFIG_KEYS.THROTTLE_DEFAULT_TTL_MS),
]);
const url: string = context.switchToHttp().getRequest<{ url: string }>().url ?? '';
const matched = ROUTE_TIERS.find(({ prefix }) => url.startsWith(prefix));
const tier = matched?.tier ?? 'default';
if (tier === 'auth') {
this.throttlers = [{ name: 'auth', ttl: authTtl, limit: authLimit }];
} else if (tier === 'strict') {
this.throttlers = [{ name: 'strict', ttl: strictTtl, limit: strictLimit }];
} else {
this.throttlers = [{ name: 'default', ttl: defaultTtl, limit: defaultLimit }];
}
return super.canActivate(context);
}
}