diff --git a/apps/api/src/config/graphql-complexity.plugin.ts b/apps/api/src/config/graphql-complexity.plugin.ts index 59fbd07..9f92a6b 100644 --- a/apps/api/src/config/graphql-complexity.plugin.ts +++ b/apps/api/src/config/graphql-complexity.plugin.ts @@ -2,7 +2,7 @@ import { ApolloServerPlugin, GraphQLRequestListener } from "@apollo/server"; import { UserRole } from "@cv/core"; import { Plugin } from "@nestjs/apollo"; import { Request } from "express"; -import { GraphQLError } from "graphql"; +import { DocumentNode, GraphQLError } from "graphql"; import { fieldExtensionsEstimator, getComplexity, @@ -25,6 +25,16 @@ const limitFor = (req: Request | undefined): number => { return COMPLEXITY_BY_ROLE[role] ?? COMPLEXITY_BY_ROLE.anonymous; }; +const isIntrospectionOnly = (document: DocumentNode): boolean => + document.definitions.every((def) => { + if (def.kind !== "OperationDefinition") { + return true; + } + return def.selectionSet.selections.every( + (sel) => sel.kind === "Field" && sel.name.value.startsWith("__"), + ); + }); + /** * Reject GraphQL queries whose total field-complexity exceeds the role-specific * limit. Anonymous callers get a tight cap (login + register only); authenticated @@ -45,6 +55,12 @@ export class GraphQLComplexityPlugin implements ApolloServerPlugin { > { return { async didResolveOperation({ request, document, schema, contextValue }) { + if ( + process.env["NODE_ENV"] !== "production" && + isIntrospectionOnly(document) + ) { + return; + } const complexity = getComplexity({ schema, query: document, diff --git a/apps/api/src/modules/app.module.ts b/apps/api/src/modules/app.module.ts index a0dcfcc..a481244 100644 --- a/apps/api/src/modules/app.module.ts +++ b/apps/api/src/modules/app.module.ts @@ -96,6 +96,7 @@ import { VacancyModule } from "./vacancies/vacancy.module"; ? true : join(__dirname, "../../schema.gql"), sortSchema: true, + introspection: process.env["NODE_ENV"] !== "production", context: ({ req, res }: { req: Request; res: Response }) => ({ req, res,