From 6b58fd8b1c56c5564dd36aa429b025c59a7f6fb0 Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 24 Aug 2023 15:16:56 +0200 Subject: [PATCH] Update visitors --- packages/core/utils/src/sanitize/sanitizers.ts | 7 +++++++ .../visitors/remove-disallowed-fields.ts | 10 ++++++---- .../visitors/remove-restricted-fields.ts | 10 ++++++---- packages/core/utils/src/validate/validators.ts | 16 +++++++++++++++- .../validate/visitors/throw-disallowed-fields.ts | 10 ++++++---- .../validate/visitors/throw-restricted-fields.ts | 2 +- .../visitors/throw-restricted-relations.ts | 13 ++----------- 7 files changed, 43 insertions(+), 25 deletions(-) diff --git a/packages/core/utils/src/sanitize/sanitizers.ts b/packages/core/utils/src/sanitize/sanitizers.ts index 2493bd6709..9b68c8fff6 100644 --- a/packages/core/utils/src/sanitize/sanitizers.ts +++ b/packages/core/utils/src/sanitize/sanitizers.ts @@ -113,6 +113,12 @@ const defaultSanitizeSort = curry((schema: Model, sort: unknown) => { // Remove keys for empty non-scalar values traverseQuerySort( ({ key, attribute, value }, { remove }) => { + // ID is not an attribute per se, so we need to make + // an extra check to ensure we're not removing it + if (key === 'id') { + return; + } + if (!isScalarAttribute(attribute) && isEmpty(value)) { remove(key); } @@ -135,6 +141,7 @@ const defaultSanitizeFields = curry((schema: Model, fields: unknown) => { if (key === 'id') { return; } + if (isNil(attribute) || !isScalarAttribute(attribute)) { remove(key); } diff --git a/packages/core/utils/src/sanitize/visitors/remove-disallowed-fields.ts b/packages/core/utils/src/sanitize/visitors/remove-disallowed-fields.ts index 3f6f865349..e0925f51f9 100644 --- a/packages/core/utils/src/sanitize/visitors/remove-disallowed-fields.ts +++ b/packages/core/utils/src/sanitize/visitors/remove-disallowed-fields.ts @@ -1,4 +1,4 @@ -import { isArray, isNil, toPath } from 'lodash/fp'; +import { isArray, isNil, isString, toPath } from 'lodash/fp'; import type { Visitor } from '../../traverse/factory'; export default (allowedFields: string[] | null = null): Visitor => @@ -8,9 +8,11 @@ export default (allowedFields: string[] | null = null): Visitor => return; } - // Ignore invalid formats - if (!isArray(allowedFields)) { - return; + // Throw on invalid formats + if (!(isArray(allowedFields) && allowedFields.every(isString))) { + throw new TypeError( + `Expected array of strings for allowedFields but got "${typeof allowedFields}"` + ); } if (isNil(path)) { diff --git a/packages/core/utils/src/sanitize/visitors/remove-restricted-fields.ts b/packages/core/utils/src/sanitize/visitors/remove-restricted-fields.ts index 280adc8a6a..4bfe770996 100644 --- a/packages/core/utils/src/sanitize/visitors/remove-restricted-fields.ts +++ b/packages/core/utils/src/sanitize/visitors/remove-restricted-fields.ts @@ -1,4 +1,4 @@ -import { isArray } from 'lodash/fp'; +import { isArray, isString } from 'lodash/fp'; import type { Visitor } from '../../traverse/factory'; export default (restrictedFields: string[] | null = null): Visitor => @@ -9,9 +9,11 @@ export default (restrictedFields: string[] | null = null): Visitor => return; } - // Ignore invalid formats - if (!isArray(restrictedFields)) { - return; + // Throw on invalid formats + if (!(isArray(restrictedFields) && restrictedFields.every(isString))) { + throw new TypeError( + `Expected array of strings for restrictedFields but got "${typeof restrictedFields}"` + ); } // Remove if an exact match was found diff --git a/packages/core/utils/src/validate/validators.ts b/packages/core/utils/src/validate/validators.ts index 30e989f644..74d6da5778 100644 --- a/packages/core/utils/src/validate/validators.ts +++ b/packages/core/utils/src/validate/validators.ts @@ -29,9 +29,15 @@ const defaultValidateFilters = curry((schema: Model, filters: unknown) => { // keys that are not attributes or valid operators traverseQueryFilters( ({ key, attribute }) => { + // ID is not an attribute per se, so we need to make + // an extra check to ensure we're not removing it + if (key === 'id') { + return; + } + const isAttribute = !!attribute; - if (!isAttribute && !isOperator(key) && key !== 'id') { + if (!isAttribute && !isOperator(key)) { throwInvalidParam({ key }); } }, @@ -61,6 +67,7 @@ const defaultValidateSort = curry((schema: Model, sort: unknown) => { if (!schema) { throw new Error('Missing schema in defaultValidateSort'); } + return pipeAsync( // non attribute keys traverseQuerySort( @@ -88,6 +95,12 @@ const defaultValidateSort = curry((schema: Model, sort: unknown) => { // keys for empty non-scalar values traverseQuerySort( ({ key, attribute, value }) => { + // ID is not an attribute per se, so we need to make + // an extra check to ensure we're not removing it + if (key === 'id') { + return; + } + if (!isScalarAttribute(attribute) && isEmpty(value)) { throwInvalidParam({ key }); } @@ -108,6 +121,7 @@ const defaultValidateFields = curry((schema: Model, fields: unknown) => { if (key === 'id') { return; } + if (isNil(attribute) || !isScalarAttribute(attribute)) { throwInvalidParam({ key }); } diff --git a/packages/core/utils/src/validate/visitors/throw-disallowed-fields.ts b/packages/core/utils/src/validate/visitors/throw-disallowed-fields.ts index 04f2cfec3b..bc67a7cac2 100644 --- a/packages/core/utils/src/validate/visitors/throw-disallowed-fields.ts +++ b/packages/core/utils/src/validate/visitors/throw-disallowed-fields.ts @@ -1,4 +1,4 @@ -import { isArray, isNil, toPath } from 'lodash/fp'; +import { isArray, isNil, isString, toPath } from 'lodash/fp'; import type { Visitor } from '../../traverse/factory'; import { throwInvalidParam } from '../utils'; @@ -9,9 +9,11 @@ export default (allowedFields: string[] | null = null): Visitor => return; } - // Ignore invalid formats - if (!isArray(allowedFields)) { - return; + // Throw on invalid formats + if (!(isArray(allowedFields) && allowedFields.every(isString))) { + throw new TypeError( + `Expected array of strings for allowedFields but got "${typeof allowedFields}"` + ); } if (isNil(path)) { diff --git a/packages/core/utils/src/validate/visitors/throw-restricted-fields.ts b/packages/core/utils/src/validate/visitors/throw-restricted-fields.ts index 5258ebbd25..790a3ebf47 100644 --- a/packages/core/utils/src/validate/visitors/throw-restricted-fields.ts +++ b/packages/core/utils/src/validate/visitors/throw-restricted-fields.ts @@ -1,4 +1,4 @@ -import { isArray } from 'lodash/fp'; +import { isArray, isString } from 'lodash/fp'; import type { Visitor } from '../../traverse/factory'; import { throwInvalidParam } from '../utils'; diff --git a/packages/core/utils/src/validate/visitors/throw-restricted-relations.ts b/packages/core/utils/src/validate/visitors/throw-restricted-relations.ts index 73d2bc8219..819bc56c6f 100644 --- a/packages/core/utils/src/validate/visitors/throw-restricted-relations.ts +++ b/packages/core/utils/src/validate/visitors/throw-restricted-relations.ts @@ -20,23 +20,14 @@ export default (auth: unknown): Visitor => } const handleMorphRelation = async () => { - const newMorphValue: Record[] = []; - for (const element of (data as Record)[key]) { const scopes = ACTIONS_TO_VERIFY.map((action) => `${element.__type}.${action}`); const isAllowed = await hasAccessToSomeScopes(scopes, auth); - if (isAllowed) { - newMorphValue.push(element); + if (!isAllowed) { + throwInvalidParam({ key }); } } - - // If the new value is empty - if (newMorphValue.length === 0) { - throwInvalidParam({ key }); - } else { - set(key, newMorphValue); - } }; const handleRegularRelation = async () => {