Add rate limiting in the server using built in Nest.js capability (#3566)

* Add rate limiting in the server using built in Nest.js capability

* Generatekey based on ip address when an http request is sent

* Update env var types to number for ttl and limit

* Remove unused env variables

* Use getRequest utility function

* fix: remove dist from path

* fix: adding .env variables

* fix: remove unused functions

* feat: throttler plugin

* Fix according to review

---------

Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Joe S
2024-02-07 11:11:32 -06:00
committed by GitHub
parent 3831ddc002
commit 850eab8f8f
16 changed files with 413 additions and 59 deletions

View File

@ -1,20 +1,23 @@
import { YogaDriverConfig } from '@graphql-yoga/nestjs';
import GraphQLJSON from 'graphql-type-json';
import { TokenService } from 'src/core/auth/services/token.service';
import { CreateContextFactory } from 'src/graphql-config/factories/create-context.factory';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { ExceptionHandlerService } from 'src/integrations/exception-handler/exception-handler.service';
import { useExceptionHandler } from 'src/integrations/exception-handler/hooks/use-exception-handler.hook';
import { useThrottler } from 'src/integrations/throttler/hooks/use-throttler';
import { MetadataModule } from 'src/metadata/metadata.module';
import { renderApolloPlayground } from 'src/workspace/utils/render-apollo-playground.util';
export const metadataModuleFactory = async (
environmentService: EnvironmentService,
exceptionHandlerService: ExceptionHandlerService,
tokenService: TokenService,
createContextFactory: CreateContextFactory,
): Promise<YogaDriverConfig> => {
const config: YogaDriverConfig = {
context: ({ req }) => ({ req }),
context(context) {
return createContextFactory.create(context);
},
autoSchemaFile: true,
include: [MetadataModule],
renderGraphiQL() {
@ -22,9 +25,15 @@ export const metadataModuleFactory = async (
},
resolvers: { JSON: GraphQLJSON },
plugins: [
useThrottler({
ttl: environmentService.getApiRateLimitingTtl(),
limit: environmentService.getApiRateLimitingLimit(),
identifyFn: (context) => {
return context.user?.id ?? context.req.ip ?? 'anonymous';
},
}),
useExceptionHandler({
exceptionHandlerService,
tokenService,
}),
],
path: '/metadata',

View File

@ -8,20 +8,25 @@ import { WorkspaceMigrationModule } from 'src/metadata/workspace-migration/works
import { metadataModuleFactory } from 'src/metadata/metadata.module-factory';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { ExceptionHandlerService } from 'src/integrations/exception-handler/exception-handler.service';
import { TokenService } from 'src/core/auth/services/token.service';
import { AuthModule } from 'src/core/auth/auth.module';
import { GraphQLConfigModule } from 'src/graphql-config/graphql-config.module';
import { CreateContextFactory } from 'src/graphql-config/factories/create-context.factory';
import { DataSourceModule } from './data-source/data-source.module';
import { FieldMetadataModule } from './field-metadata/field-metadata.module';
import { ObjectMetadataModule } from './object-metadata/object-metadata.module';
import { RelationMetadataModule } from './relation-metadata/relation-metadata.module';
@Module({
imports: [
GraphQLModule.forRootAsync<YogaDriverConfig>({
driver: YogaDriver,
useFactory: metadataModuleFactory,
imports: [AuthModule],
inject: [EnvironmentService, ExceptionHandlerService, TokenService],
imports: [GraphQLConfigModule],
inject: [
EnvironmentService,
ExceptionHandlerService,
CreateContextFactory,
],
}),
DataSourceModule,
FieldMetadataModule,