feat: add some security packages

This commit is contained in:
2026-07-08 07:46:37 +03:30
parent 03ba4ceabe
commit b4570f6df9
5 changed files with 58 additions and 1 deletions
+25
View File
@@ -17,11 +17,13 @@
"@nestjs/platform-express": "^11.0.1",
"@nestjs/schedule": "^6.1.1",
"@nestjs/swagger": "^11.2.6",
"@nestjs/throttler": "^6.5.0",
"@nestjs/typeorm": "^11.0.0",
"bcrypt": "^6.0.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.3",
"dotenv": "^17.4.2",
"helmet": "^8.2.0",
"ioredis": "^5.10.1",
"joi": "^18.0.2",
"nestjs-i18n": "^10.6.0",
@@ -2538,6 +2540,17 @@
}
}
},
"node_modules/@nestjs/throttler": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@nestjs/throttler/-/throttler-6.5.0.tgz",
"integrity": "sha512-9j0ZRfH0QE1qyrj9JjIRDz5gQLPqq9yVC2nHsrosDVAfI5HHw08/aUAWx9DZLSdQf4HDkmhTTEGLrRFHENvchQ==",
"license": "MIT",
"peerDependencies": {
"@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0",
"@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0",
"reflect-metadata": "^0.1.13 || ^0.2.0"
}
},
"node_modules/@nestjs/typeorm": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-11.0.0.tgz",
@@ -6091,6 +6104,18 @@
"node": ">= 0.4"
}
},
"node_modules/helmet": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-8.2.0.tgz",
"integrity": "sha512-DRgTIUgnWcJ62KyarxxziuqYxKGnR6Rgg19BlbucN/dpmJbl1XOit6qvoOX0ZT+HhWe5OUVhU/a1zpGyc1xA0Q==",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
},
"funding": {
"url": "https://github.com/sponsors/EvanHahn"
}
},
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+2
View File
@@ -28,11 +28,13 @@
"@nestjs/platform-express": "^11.0.1",
"@nestjs/schedule": "^6.1.1",
"@nestjs/swagger": "^11.2.6",
"@nestjs/throttler": "^6.5.0",
"@nestjs/typeorm": "^11.0.0",
"bcrypt": "^6.0.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.3",
"dotenv": "^17.4.2",
"helmet": "^8.2.0",
"ioredis": "^5.10.1",
"joi": "^18.0.2",
"nestjs-i18n": "^10.6.0",
+15 -1
View File
@@ -13,7 +13,7 @@ import { RedisModule } from './common/modules/redis/redis.module';
import path from 'path';
import jwtConfig from './config/jwt.config';
import redisConfig from './config/redis.config';
import { APP_FILTER } from '@nestjs/core';
import { APP_FILTER, APP_GUARD } from '@nestjs/core';
import { GlobalExceptionFilter } from './common/filters/global-exception.filter';
import { ScheduleModule } from '@nestjs/schedule';
import { TestsModule } from './modules/tests/tests.module';
@@ -21,6 +21,8 @@ import { QuestionsModule } from './modules/questions/questions.module';
import { SubmissionsModule } from './modules/submissions/submissions.module';
import { ScoringModule } from './modules/scoring/scoring.module';
import { AdminModule } from './modules/admin/admin.module';
import { ThrottlerModule } from '@nestjs/throttler';
import { AppThrottlerGuard } from './common/guards/app-throttler.guard';
const ENV = process.env.NODE_ENV;
@@ -68,6 +70,14 @@ const ENV = process.env.NODE_ENV;
// Schedule
ScheduleModule.forRoot(),
// Throttler
ThrottlerModule.forRoot([
{ name: 'default', limit: 100, ttl: 60_000 },
{ name: 'login', limit: 5, ttl: 60_000 },
{ name: 'otp', limit: 3, ttl: 300_000 },
{ name: 'admin', limit: 30, ttl: 60_000 },
]),
/**
* Local Modules
*/
@@ -87,6 +97,10 @@ const ENV = process.env.NODE_ENV;
provide: APP_FILTER,
useClass: GlobalExceptionFilter,
},
{
provide: APP_GUARD,
useClass: AppThrottlerGuard,
},
],
})
export class AppModule {}
+13
View File
@@ -0,0 +1,13 @@
import { HttpStatus } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';
import { AppException } from '../exceptions/app.exception';
export class AppThrottlerGuard extends ThrottlerGuard {
protected throwThrottlingException(): Promise<void> {
throw new AppException(
'common.errors.tooManyRequests',
HttpStatus.TOO_MANY_REQUESTS,
{ minutes: 1 },
);
}
}
+3
View File
@@ -3,6 +3,7 @@ import { AppModule } from './app.module';
import { I18nValidationExceptionFilter, I18nValidationPipe } from 'nestjs-i18n';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { ResponseInterceptor } from './common/interceptors/response.interceptor';
import helmet from 'helmet';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
@@ -36,6 +37,8 @@ async function bootstrap() {
credentials: true,
});
app.use(helmet());
const config = new DocumentBuilder()
.setTitle('Borna API')
.setDescription('Borna API Documentation')