Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions meridian-api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { JwtModule } from '@nestjs/jwt';
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { APP_INTERCEPTOR, APP_GUARD } from '@nestjs/core';
import { CustomThrottlerGuard } from './common/guards/custom-throttler.guard';
import { DataSource } from 'typeorm';

import { AppController } from './app.controller';
Expand Down Expand Up @@ -50,8 +51,14 @@ import { AuditModule } from './audit/audit.module';
*/
ThrottlerModule.forRoot([
{
name: 'read',
ttl: 60000,
limit: 10,
limit: 100, // 100 requests per minute for GET
},
{
name: 'write',
ttl: 60000,
limit: 20, // 20 requests per minute for POST/PUT/PATCH/DELETE
},
]),

Expand Down Expand Up @@ -117,7 +124,7 @@ import { AuditModule } from './audit/audit.module';
},
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
useClass: CustomThrottlerGuard,
},
AccessTokenGuard,
MailProvider,
Expand Down
8 changes: 4 additions & 4 deletions meridian-api/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class AuthController {
constructor(private readonly authService: AuthService) {}

@Post('/sign-in')
@Throttle({ default: { limit: 5, ttl: 15000 } })
@Throttle({ write: { limit: 5, ttl: 15000 } })
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Sign in with user credentials' })
@ApiResponse({
Expand All @@ -42,7 +42,7 @@ export class AuthController {
}

@Post('/refresh-token')
@Throttle({ default: { limit: 10, ttl: 60000 } })
@Throttle({ write: { limit: 10, ttl: 60000 } })
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Refresh Auth Token' })
@ApiResponse({ status: 200, description: 'Successfully refreshed token' })
Expand Down Expand Up @@ -97,7 +97,7 @@ export class AuthController {
}

@Post('/verify-email')
@Throttle({ default: { limit: 10, ttl: 60000 } })
@Throttle({ write: { limit: 10, ttl: 60000 } })
@HttpCode(HttpStatus.OK)
@ApiOperation({
summary: 'Verify email with one-time token from signup mail',
Expand All @@ -113,7 +113,7 @@ export class AuthController {
}

@Post('/resend-verification')
@Throttle({ default: { limit: 3, ttl: 60000 } })
@Throttle({ write: { limit: 3, ttl: 60000 } })
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Resend the email verification mail' })
@ApiResponse({
Expand Down
27 changes: 27 additions & 0 deletions meridian-api/src/common/guards/custom-throttler.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ExecutionContext, Injectable } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';

@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
protected async handleRequest(
requestProps: any,
): Promise<boolean> {
const { context, throttler } = requestProps;

const req = context.switchToHttp().getRequest();
const isWrite = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method);
const throttlerName = throttler.name || 'default';

// If it's a read request, ignore the "write" throttler
if (!isWrite && throttlerName === 'write') {
return true;
}

// If it's a write request, ignore the "read" throttler
if (isWrite && throttlerName === 'read') {
return true;
}

return super.handleRequest(requestProps);
}
}
2 changes: 2 additions & 0 deletions meridian-api/src/health/health.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Controller, Get } from '@nestjs/common';
import { SkipThrottle } from '@nestjs/throttler';
import {
HealthCheckService,
HealthCheck,
Expand All @@ -8,6 +9,7 @@ import {
} from '@nestjs/terminus';
import { ApiTags, ApiOperation } from '@nestjs/swagger';

@SkipThrottle()
@ApiTags('Health')
@Controller('health')
export class HealthController {
Expand Down
Loading