@strapi/utils
Version:
Shared utilities for the Strapi packages
1 lines • 12.3 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../../src/validate/index.ts"],"sourcesContent":["import { CurriedFunction1 } from 'lodash';\nimport { isArray, isObject } from 'lodash/fp';\n\nimport { getNonWritableAttributes, constants } from '../content-types';\nimport { pipe as pipeAsync } from '../async';\nimport { throwInvalidKey } from './utils';\n\nimport * as visitors from './visitors';\nimport * as validators from './validators';\nimport traverseEntity from '../traverse-entity';\n\nimport { traverseQueryFilters, traverseQuerySort, traverseQueryPopulate } from '../traverse';\n\nimport { Model, Data } from '../types';\nimport { ValidationError } from '../errors';\n\nconst { ID_ATTRIBUTE, DOC_ID_ATTRIBUTE } = constants;\n\nexport interface Options {\n auth?: unknown;\n}\n\nexport interface Validator {\n (schema: Model): CurriedFunction1<Data, Promise<Data>>;\n}\nexport interface ValidateFunc {\n (data: unknown, schema: Model, options?: Options): Promise<void>;\n}\n\ninterface APIOptions {\n validators?: Validators;\n getModel: (model: string) => Model;\n}\n\nexport interface Validators {\n input?: Validator[];\n}\n\nconst createAPIValidators = (opts: APIOptions) => {\n const { getModel } = opts || {};\n\n const validateInput: ValidateFunc = async (data: unknown, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in validateInput');\n }\n\n if (isArray(data)) {\n await Promise.all(data.map((entry) => validateInput(entry, schema, { auth })));\n return;\n }\n\n const nonWritableAttributes = getNonWritableAttributes(schema);\n\n const transforms = [\n (data: unknown) => {\n if (isObject(data)) {\n if (ID_ATTRIBUTE in data) {\n throwInvalidKey({ key: ID_ATTRIBUTE });\n }\n\n if (DOC_ID_ATTRIBUTE in data) {\n throwInvalidKey({ key: DOC_ID_ATTRIBUTE });\n }\n }\n return data;\n },\n // non-writable attributes\n traverseEntity(visitors.throwRestrictedFields(nonWritableAttributes), { schema, getModel }),\n // unrecognized attributes\n traverseEntity(visitors.throwUnrecognizedFields, { schema, getModel }),\n ];\n\n if (auth) {\n // restricted relations\n transforms.push(\n traverseEntity(visitors.throwRestrictedRelations(auth), {\n schema,\n getModel,\n })\n );\n }\n\n // Apply validators from registry if exists\n opts?.validators?.input?.forEach((validator: Validator) => transforms.push(validator(schema)));\n\n try {\n await pipeAsync(...transforms)(data as Data);\n } catch (e) {\n if (e instanceof ValidationError) {\n e.details.source = 'body';\n }\n throw e;\n }\n };\n\n const validateQuery = async (\n query: Record<string, unknown>,\n schema: Model,\n { auth }: Options = {}\n ) => {\n if (!schema) {\n throw new Error('Missing schema in validateQuery');\n }\n const { filters, sort, fields, populate } = query;\n\n if (filters) {\n await validateFilters(filters, schema, { auth });\n }\n\n if (sort) {\n await validateSort(sort, schema, { auth });\n }\n\n if (fields) {\n await validateFields(fields, schema);\n }\n\n // a wildcard is always valid; its conversion will be handled by the entity service and can be optimized with sanitizer\n if (populate && populate !== '*') {\n await validatePopulate(populate, schema);\n }\n };\n\n const validateFilters: ValidateFunc = async (filters, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in validateFilters');\n }\n if (isArray(filters)) {\n await Promise.all(filters.map((filter) => validateFilters(filter, schema, { auth })));\n return;\n }\n\n const transforms = [validators.defaultValidateFilters({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryFilters(visitors.throwRestrictedRelations(auth), {\n schema,\n getModel,\n })\n );\n }\n\n try {\n await pipeAsync(...transforms)(filters);\n } catch (e) {\n if (e instanceof ValidationError) {\n e.details.source = 'query';\n e.details.param = 'filters';\n }\n throw e;\n }\n };\n\n const validateSort: ValidateFunc = async (sort, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in validateSort');\n }\n const transforms = [validators.defaultValidateSort({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQuerySort(visitors.throwRestrictedRelations(auth), {\n schema,\n getModel,\n })\n );\n }\n\n try {\n await pipeAsync(...transforms)(sort);\n } catch (e) {\n if (e instanceof ValidationError) {\n e.details.source = 'query';\n e.details.param = 'sort';\n }\n throw e;\n }\n };\n\n const validateFields: ValidateFunc = async (fields, schema: Model) => {\n if (!schema) {\n throw new Error('Missing schema in validateFields');\n }\n const transforms = [validators.defaultValidateFields({ schema, getModel })];\n\n try {\n await pipeAsync(...transforms)(fields);\n } catch (e) {\n if (e instanceof ValidationError) {\n e.details.source = 'query';\n e.details.param = 'fields';\n }\n throw e;\n }\n };\n\n const validatePopulate: ValidateFunc = async (populate, schema: Model, { auth } = {}) => {\n if (!schema) {\n throw new Error('Missing schema in sanitizePopulate');\n }\n const transforms = [validators.defaultValidatePopulate({ schema, getModel })];\n\n if (auth) {\n transforms.push(\n traverseQueryPopulate(visitors.throwRestrictedRelations(auth), {\n schema,\n getModel,\n })\n );\n }\n\n try {\n await pipeAsync(...transforms)(populate);\n } catch (e) {\n if (e instanceof ValidationError) {\n e.details.source = 'query';\n e.details.param = 'populate';\n }\n throw e;\n }\n };\n\n return {\n input: validateInput,\n query: validateQuery,\n filters: validateFilters,\n sort: validateSort,\n fields: validateFields,\n populate: validatePopulate,\n };\n};\n\nexport { createAPIValidators, validators, visitors };\n\nexport type APIValidators = ReturnType<typeof createAPIValidators>;\n"],"names":["ID_ATTRIBUTE","DOC_ID_ATTRIBUTE","constants","createAPIValidators","opts","getModel","validateInput","data","schema","auth","Error","isArray","Promise","all","map","entry","nonWritableAttributes","getNonWritableAttributes","transforms","isObject","throwInvalidKey","key","traverseEntity","visitors","push","validators","input","forEach","validator","pipeAsync","e","ValidationError","details","source","validateQuery","query","filters","sort","fields","populate","validateFilters","validateSort","validateFields","validatePopulate","filter","traverseQueryFilters","param","traverseQuerySort","traverseQueryPopulate"],"mappings":"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"}