From ef9d94f53d19646a8985be9517810bdb03bc8e67 Mon Sep 17 00:00:00 2001 From: Omri Levy Date: Mon, 3 Jun 2024 10:53:33 +0300 Subject: [PATCH] addressed pr comments --- package.json | 7 +++++-- pnpm-lock.yaml | 7 +++++++ src/decorators.ts | 12 +++++++++++- src/types.ts | 18 ++++++++---------- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index e0c51a5..c433cc7 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,8 @@ "@nestjs/core": "^9.0.1 || ^10.0.3", "@nestjs/swagger": "^6.1.1 || ^7.0.11", "@sinclair/typebox": "^0.32.4", - "rxjs": "^7.5.6", - "ajv": "^8.14.0" + "ajv": "^8.14.0", + "rxjs": "^7.5.6" }, "devDependencies": { "@changesets/cli": "^2.26.2", @@ -63,5 +63,8 @@ "repository": { "type": "git", "url": "https://github.com/jayalfredprufrock/nestjs-typebox" + }, + "dependencies": { + "fast-uri": "^2.3.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da2721a..b137295 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: ajv: specifier: ^8.14.0 version: 8.14.0 + fast-uri: + specifier: ^2.3.0 + version: 2.3.0 devDependencies: '@changesets/cli': @@ -1591,6 +1594,10 @@ packages: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} dev: true + /fast-uri@2.3.0: + resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} + dev: false + /fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: diff --git a/src/decorators.ts b/src/decorators.ts index 2605b48..ac38cf7 100644 --- a/src/decorators.ts +++ b/src/decorators.ts @@ -6,6 +6,7 @@ import { ApiBody, ApiOperation, ApiParam, ApiQuery } from '@nestjs/swagger'; import { DECORATORS } from '@nestjs/swagger/dist/constants.js'; import { Static, TSchema, Type, TypeGuard } from '@sinclair/typebox'; import { Ajv } from 'ajv'; +import fastUri from 'fast-uri'; import { AjvValidationException } from './exceptions.js'; import { TypeboxTransformInterceptor } from './interceptors.js'; @@ -22,7 +23,16 @@ import type { } from './types.js'; import { capitalize, coerceType, isObj } from './util.js'; -const ajv = new Ajv(); +const ajv = new Ajv({ + coerceTypes: 'array', + useDefaults: true, + removeAdditional: true, + uriResolver: fastUri, + addUsedSchema: false, + // Explicitly set allErrors to `false`. + // When set to `true`, a DoS attack is possible. + allErrors: false, +}); // eslint-disable-next-line @typescript-eslint/no-explicit-any export function isSchemaValidator(type: any): type is SchemaValidator { diff --git a/src/types.ts b/src/types.ts index 078d7a5..537cb79 100644 --- a/src/types.ts +++ b/src/types.ts @@ -16,7 +16,7 @@ export type MethodDecorator = ( ) => TypedPropertyDescriptor | void; export interface HttpEndpointDecoratorConfig< - TTSchema extends TSchema = TSchema, + TTSchema extends TSchema, ResponseConfig extends ResponseValidatorConfig = ResponseValidatorConfig, RequestConfigs extends RequestValidatorConfig[] = RequestValidatorConfig[], > extends Omit { @@ -26,7 +26,7 @@ export interface HttpEndpointDecoratorConfig< validate?: ValidatorConfig; } -export interface SchemaValidator { +export interface SchemaValidator { schema: TTSchema; name: string; check: ValidateFunction>; @@ -40,7 +40,7 @@ export interface ValidatorConfigBase { required?: boolean; pipes?: (PipeTransform | Type)[]; } -export interface ResponseValidatorConfig extends ValidatorConfigBase { +export interface ResponseValidatorConfig extends ValidatorConfigBase { schema: TTSchema; type?: 'response'; responseCode?: number; @@ -48,32 +48,30 @@ export interface ResponseValidatorConfig ext pipes?: never; } -export interface ParamValidatorConfig extends ValidatorConfigBase { +export interface ParamValidatorConfig extends ValidatorConfigBase { schema?: TTSchema; type: 'param'; name: string; stripUnknownProps?: never; } -export interface QueryValidatorConfig extends ValidatorConfigBase { +export interface QueryValidatorConfig extends ValidatorConfigBase { schema?: TTSchema; type: 'query'; name: string; stripUnknownProps?: never; } -export interface BodyValidatorConfig extends ValidatorConfigBase { +export interface BodyValidatorConfig extends ValidatorConfigBase { schema: TTSchema; type: 'body'; } -export type RequestValidatorConfig = +export type RequestValidatorConfig = | ParamValidatorConfig | QueryValidatorConfig | BodyValidatorConfig; -export type SchemaValidatorConfig = - | RequestValidatorConfig - | ResponseValidatorConfig; +export type SchemaValidatorConfig = RequestValidatorConfig | ResponseValidatorConfig; export type ValidatorType = NonNullable;