feat: api endpoints throttle (#837)

* feat: api endpoints throttle
This commit is contained in:
Ahmed Bouhuolia
2025-10-30 22:06:05 +02:00
committed by GitHub
parent 844a050c9a
commit 41143d8bbd
8 changed files with 215 additions and 119 deletions

View File

@@ -1,7 +1,7 @@
import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { join } from 'path';
import { ServeStaticModule } from '@nestjs/serve-static';
import { RedisModule } from '@liaoliaots/nestjs-redis';
@@ -95,6 +95,8 @@ import { BankingCategorizeModule } from '../BankingCategorize/BankingCategorize.
import { TenantModelsInitializeModule } from '../Tenancy/TenantModelsInitialize.module';
import { BillLandedCostsModule } from '../BillLandedCosts/BillLandedCosts.module';
import { SocketModule } from '../Socket/Socket.module';
import { ThrottlerGuard } from '@nestjs/throttler';
import { AppThrottleModule } from './AppThrottle.module';
@Module({
imports: [
@@ -126,6 +128,7 @@ import { SocketModule } from '../Socket/Socket.module';
],
}),
PassportModule,
AppThrottleModule,
BullModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
@@ -231,6 +234,10 @@ import { SocketModule } from '../Socket/Socket.module';
],
controllers: [AppController],
providers: [
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
},
{
provide: APP_INTERCEPTOR,
useClass: SerializeInterceptor,

View File

@@ -0,0 +1,48 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerStorageRedisService } from '@nest-lab/throttler-storage-redis';
@Module({
imports: [
ThrottlerModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
const host = configService.get<string>('redis.host') || 'localhost';
const port = Number(configService.get<number>('redis.port') || 6379);
const password = configService.get<string>('redis.password');
const db = configService.get<number>('redis.db');
const globalTtl = configService.get<number>('throttle.global.ttl');
const globalLimit = configService.get<number>('throttle.global.limit');
const authTtl = configService.get<number>('throttle.auth.ttl');
const authLimit = configService.get<number>('throttle.auth.limit');
return {
throttlers: [
{
name: 'default',
ttl: globalTtl,
limit: globalLimit,
},
{
name: 'auth',
ttl: authTtl,
limit: authLimit,
},
],
storage: new ThrottlerStorageRedisService({
host,
port,
password,
db,
}),
};
},
}),
],
})
export class AppThrottleModule { }

View File

@@ -8,6 +8,7 @@ import {
Request,
UseGuards,
} from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import {
ApiTags,
ApiOperation,
@@ -28,6 +29,7 @@ import { SystemUser } from '../System/models/SystemUser';
@ApiTags('Auth')
@ApiExcludeController()
@PublicRoute()
@Throttle({ auth: {} })
export class AuthController {
constructor(
private readonly authApp: AuthenticationApplication,

View File

@@ -6,6 +6,7 @@ import {
} from '@nestjs/swagger';
import { GetAuthenticatedAccount } from './queries/GetAuthedAccount.service';
import { Controller, Get, Post } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import { IgnoreTenantSeededRoute } from '../Tenancy/EnsureTenantIsSeeded.guards';
import { IgnoreTenantInitializedRoute } from '../Tenancy/EnsureTenantIsInitialized.guard';
import { AuthenticationApplication } from './AuthApplication.sevice';
@@ -18,11 +19,12 @@ import { IgnoreUserVerifiedRoute } from './guards/EnsureUserVerified.guard';
@IgnoreTenantSeededRoute()
@IgnoreTenantInitializedRoute()
@IgnoreUserVerifiedRoute()
@Throttle({ auth: {} })
export class AuthedController {
constructor(
private readonly getAuthedAccountService: GetAuthenticatedAccount,
private readonly authApp: AuthenticationApplication,
) {}
) { }
@Post('/signup/verify/resend')
@ApiOperation({ summary: 'Resend the signup confirmation message' })