generated from bastian/boilerplate
Initial commit
This commit is contained in:
101
apps/backend/src/app.module.ts
Normal file
101
apps/backend/src/app.module.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||
import { APP_FILTER, APP_GUARD, Reflector } from '@nestjs/core';
|
||||
import {
|
||||
ThrottlerGuard,
|
||||
ThrottlerModule,
|
||||
type ThrottlerGenerateKeyFunction,
|
||||
type ThrottlerGetTrackerFunction,
|
||||
} from '@nestjs/throttler';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AuditModule } from './audit/audit.module';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { CsrfGuard } from './auth/guards/csrf.guard';
|
||||
import { PermissionsGuard } from './auth/guards/permissions.guard';
|
||||
import { AppConfigModule } from './config/config.module';
|
||||
import { AppConfigService } from './config/config.service';
|
||||
import { ApiExceptionFilter } from './common/errors/api-exception.filter';
|
||||
import { RequestIdMiddleware } from './common/request-context/request-id.middleware';
|
||||
import { SENSITIVE_RATE_LIMIT_KEY } from './common/rate-limit/sensitive-rate-limit.decorator';
|
||||
import { typeOrmOptionsFactory } from './database/typeorm-options';
|
||||
import { DatabaseModule } from './database/database.module';
|
||||
import { DashboardModule } from './dashboard/dashboard.module';
|
||||
import { HealthModule } from './health/health.module';
|
||||
import { ItemsModule } from './items/items.module';
|
||||
import { NotificationsModule } from './notifications/notifications.module';
|
||||
import { RolesModule } from './roles/roles.module';
|
||||
import { SessionsModule } from './sessions/sessions.module';
|
||||
import { UsersModule } from './users/users.module';
|
||||
|
||||
const getIpTracker: ThrottlerGetTrackerFunction = (req) => {
|
||||
const ip = typeof req['ip'] === 'string' ? req['ip'] : undefined;
|
||||
const socket = req['socket'] as { remoteAddress?: unknown } | undefined;
|
||||
const remoteAddress =
|
||||
typeof socket?.remoteAddress === 'string'
|
||||
? socket.remoteAddress
|
||||
: undefined;
|
||||
return ip ?? remoteAddress ?? 'unknown';
|
||||
};
|
||||
|
||||
const generateGlobalKey: ThrottlerGenerateKeyFunction = (
|
||||
_context,
|
||||
tracker,
|
||||
throttlerName,
|
||||
) => createHash('sha256').update(`${throttlerName}:${tracker}`).digest('hex');
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
TypeOrmModule.forRootAsync({
|
||||
imports: [AppConfigModule],
|
||||
inject: [AppConfigService],
|
||||
useFactory: typeOrmOptionsFactory,
|
||||
}),
|
||||
DatabaseModule,
|
||||
DashboardModule,
|
||||
ThrottlerModule.forRootAsync({
|
||||
imports: [AppConfigModule],
|
||||
inject: [AppConfigService, Reflector],
|
||||
useFactory: (config: AppConfigService, reflector: Reflector) => ({
|
||||
getTracker: getIpTracker,
|
||||
generateKey: generateGlobalKey,
|
||||
throttlers: [
|
||||
{
|
||||
name: 'default',
|
||||
ttl: config.rateLimit.global.windowSeconds * 1000,
|
||||
limit: config.rateLimit.global.maxRequests,
|
||||
},
|
||||
{
|
||||
name: 'sensitive',
|
||||
ttl: config.rateLimit.sensitive.windowSeconds * 1000,
|
||||
limit: config.rateLimit.sensitive.maxRequests,
|
||||
skipIf: (context) =>
|
||||
!reflector.getAllAndOverride<boolean>(SENSITIVE_RATE_LIMIT_KEY, [
|
||||
context.getHandler(),
|
||||
context.getClass(),
|
||||
]),
|
||||
},
|
||||
],
|
||||
}),
|
||||
}),
|
||||
AuthModule,
|
||||
UsersModule,
|
||||
RolesModule,
|
||||
SessionsModule,
|
||||
NotificationsModule,
|
||||
AuditModule,
|
||||
ItemsModule,
|
||||
HealthModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: APP_FILTER, useClass: ApiExceptionFilter },
|
||||
{ provide: APP_GUARD, useClass: ThrottlerGuard },
|
||||
{ provide: APP_GUARD, useClass: CsrfGuard },
|
||||
{ provide: APP_GUARD, useClass: PermissionsGuard },
|
||||
],
|
||||
})
|
||||
export class AppModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer): void {
|
||||
consumer.apply(RequestIdMiddleware).forRoutes('*');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user