From ee002df110d9d0c6b7e14d138b4f5bdbe705a42e Mon Sep 17 00:00:00 2001 From: ankitsridhar16 Date: Wed, 7 Dec 2022 23:09:15 +0530 Subject: [PATCH] chore: added gql decorator and complexity plugin --- .../src/decorators/gql-user.decorator.ts | 17 +++++++ .../src/plugins/GQLComplexityPlugin.ts | 44 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 packages/hoppscotch-backend/src/decorators/gql-user.decorator.ts create mode 100644 packages/hoppscotch-backend/src/plugins/GQLComplexityPlugin.ts diff --git a/packages/hoppscotch-backend/src/decorators/gql-user.decorator.ts b/packages/hoppscotch-backend/src/decorators/gql-user.decorator.ts new file mode 100644 index 000000000..2c4da3b52 --- /dev/null +++ b/packages/hoppscotch-backend/src/decorators/gql-user.decorator.ts @@ -0,0 +1,17 @@ +import { createParamDecorator, ExecutionContext } from '@nestjs/common'; +import { User } from '../user/user.model'; +import { GqlExecutionContext } from '@nestjs/graphql'; + +export const GqlUser = createParamDecorator( + (_data: any, context: ExecutionContext) => { + const { user } = GqlExecutionContext.create(context).getContext<{ + user: User; + }>(); + if (!user) + throw new Error( + '@GqlUser decorator use with null user. Make sure the resolve has the @GqlAuthGuard present.', + ); + + return user; + }, +); diff --git a/packages/hoppscotch-backend/src/plugins/GQLComplexityPlugin.ts b/packages/hoppscotch-backend/src/plugins/GQLComplexityPlugin.ts new file mode 100644 index 000000000..f3b8fca08 --- /dev/null +++ b/packages/hoppscotch-backend/src/plugins/GQLComplexityPlugin.ts @@ -0,0 +1,44 @@ +import { GraphQLSchemaHost } from '@nestjs/graphql'; +import { + ApolloServerPlugin, + GraphQLRequestListener, +} from 'apollo-server-plugin-base'; +import { Plugin } from '@nestjs/apollo'; +import { GraphQLError } from 'graphql'; +import { + fieldExtensionsEstimator, + getComplexity, + simpleEstimator, +} from 'graphql-query-complexity'; + +const COMPLEXITY_LIMIT = 50; + +@Plugin() +export class GQLComplexityPlugin implements ApolloServerPlugin { + constructor(private gqlSchemaHost: GraphQLSchemaHost) {} + + async requestDidStart(): Promise { + const { schema } = this.gqlSchemaHost; + + return { + async didResolveOperation({ request, document }) { + const complexity = getComplexity({ + schema, + operationName: request.operationName, + query: document, + variables: request.variables, + estimators: [ + fieldExtensionsEstimator(), + simpleEstimator({ defaultComplexity: 1 }), + ], + }); + if (complexity > COMPLEXITY_LIMIT) { + throw new GraphQLError( + `Query is too complex: ${complexity}. Maximum allowed complexity: ${COMPLEXITY_LIMIT}`, + ); + } + console.log('Query Complexity:', complexity); + }, + }; + } +}