payload 3.41.0-canary.2 → 3.41.0-internal.8617025
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/database/queryValidation/validateQueryPaths.d.ts.map +1 -1
- package/dist/database/queryValidation/validateQueryPaths.js +0 -2
- package/dist/database/queryValidation/validateQueryPaths.js.map +1 -1
- package/dist/database/queryValidation/validateSearchParams.d.ts.map +1 -1
- package/dist/database/queryValidation/validateSearchParams.js +3 -5
- package/dist/database/queryValidation/validateSearchParams.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.js +1 -2
- package/dist/uploads/fetchAPI-multipart/processMultipart.js.map +1 -1
- package/dist/uploads/getExternalFile.d.ts.map +1 -1
- package/dist/uploads/getExternalFile.js +8 -1
- package/dist/uploads/getExternalFile.js.map +1 -1
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateQueryPaths.d.ts","sourceRoot":"","sources":["../../../src/database/queryValidation/validateQueryPaths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAY,cAAc,EAAE,KAAK,EAAc,MAAM,sBAAsB,CAAA;AACvF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAMhD,KAAK,IAAI,GAAG;IACV,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC3B,cAAc,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,GAAG,EAAE,cAAc,CAAA;IACnB,aAAa,CAAC,EAAE,cAAc,EAAE,CAAA;IAChC,KAAK,EAAE,KAAK,CAAA;CACb,GAAG,CACA;IACE,gBAAgB,EAAE,yBAAyB,CAAA;IAC3C,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;CACjC,GACD;IACE,gBAAgB,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;IACpC,YAAY,EAAE,qBAAqB,CAAA;CACpC,CACJ,CAAA;AAED,wBAAsB,kBAAkB,CAAC,EACvC,gBAAgB,EAChB,MAAW,EACX,YAAY,EACZ,cAAc,EACd,QAGC,EACD,eAAe,EACf,GAAG,EACH,aAAa,EACb,KAAK,GACN,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"validateQueryPaths.d.ts","sourceRoot":"","sources":["../../../src/database/queryValidation/validateQueryPaths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAY,cAAc,EAAE,KAAK,EAAc,MAAM,sBAAsB,CAAA;AACvF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAMhD,KAAK,IAAI,GAAG;IACV,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC3B,cAAc,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,GAAG,EAAE,cAAc,CAAA;IACnB,aAAa,CAAC,EAAE,cAAc,EAAE,CAAA;IAChC,KAAK,EAAE,KAAK,CAAA;CACb,GAAG,CACA;IACE,gBAAgB,EAAE,yBAAyB,CAAA;IAC3C,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;CACjC,GACD;IACE,gBAAgB,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;IACpC,YAAY,EAAE,qBAAqB,CAAA;CACpC,CACJ,CAAA;AAED,wBAAsB,kBAAkB,CAAC,EACvC,gBAAgB,EAChB,MAAW,EACX,YAAY,EACZ,cAAc,EACd,QAGC,EACD,eAAe,EACf,GAAG,EACH,aAAa,EACb,KAAK,GACN,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAoEtB"}
|
|
@@ -20,7 +20,6 @@ export async function validateQueryPaths({ collectionConfig, errors = [], global
|
|
|
20
20
|
errors,
|
|
21
21
|
overrideAccess,
|
|
22
22
|
policies,
|
|
23
|
-
polymorphicJoin,
|
|
24
23
|
req,
|
|
25
24
|
versionFields,
|
|
26
25
|
where: item
|
|
@@ -31,7 +30,6 @@ export async function validateQueryPaths({ collectionConfig, errors = [], global
|
|
|
31
30
|
globalConfig,
|
|
32
31
|
overrideAccess,
|
|
33
32
|
policies,
|
|
34
|
-
polymorphicJoin,
|
|
35
33
|
req,
|
|
36
34
|
versionFields,
|
|
37
35
|
where: item
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/database/queryValidation/validateQueryPaths.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { SanitizedCollectionConfig } from '../../collections/config/types.js'\nimport type { FlattenedField } from '../../fields/config/types.js'\nimport type { SanitizedGlobalConfig } from '../../globals/config/types.js'\nimport type { Operator, PayloadRequest, Where, WhereField } from '../../types/index.js'\nimport type { EntityPolicies } from './types.js'\n\nimport { QueryError } from '../../errors/QueryError.js'\nimport { validOperatorSet } from '../../types/constants.js'\nimport { validateSearchParam } from './validateSearchParams.js'\n\ntype Args = {\n errors?: { path: string }[]\n overrideAccess: boolean\n policies?: EntityPolicies\n polymorphicJoin?: boolean\n req: PayloadRequest\n versionFields?: FlattenedField[]\n where: Where\n} & (\n | {\n collectionConfig: SanitizedCollectionConfig\n globalConfig?: never | undefined\n }\n | {\n collectionConfig?: never | undefined\n globalConfig: SanitizedGlobalConfig\n }\n)\n\nexport async function validateQueryPaths({\n collectionConfig,\n errors = [],\n globalConfig,\n overrideAccess,\n policies = {\n collections: {},\n globals: {},\n },\n polymorphicJoin,\n req,\n versionFields,\n where,\n}: Args): Promise<void> {\n const fields = versionFields || (globalConfig || collectionConfig).flattenedFields\n\n if (typeof where === 'object') {\n // We need to determine if the whereKey is an AND, OR, or a schema path\n const promises = []\n for (const path in where) {\n const constraint = where[path]\n\n if ((path === 'and' || path === 'or') && Array.isArray(constraint)) {\n for (const item of constraint) {\n if (collectionConfig) {\n promises.push(\n validateQueryPaths({\n collectionConfig,\n errors,\n overrideAccess,\n policies,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/database/queryValidation/validateQueryPaths.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { SanitizedCollectionConfig } from '../../collections/config/types.js'\nimport type { FlattenedField } from '../../fields/config/types.js'\nimport type { SanitizedGlobalConfig } from '../../globals/config/types.js'\nimport type { Operator, PayloadRequest, Where, WhereField } from '../../types/index.js'\nimport type { EntityPolicies } from './types.js'\n\nimport { QueryError } from '../../errors/QueryError.js'\nimport { validOperatorSet } from '../../types/constants.js'\nimport { validateSearchParam } from './validateSearchParams.js'\n\ntype Args = {\n errors?: { path: string }[]\n overrideAccess: boolean\n policies?: EntityPolicies\n polymorphicJoin?: boolean\n req: PayloadRequest\n versionFields?: FlattenedField[]\n where: Where\n} & (\n | {\n collectionConfig: SanitizedCollectionConfig\n globalConfig?: never | undefined\n }\n | {\n collectionConfig?: never | undefined\n globalConfig: SanitizedGlobalConfig\n }\n)\n\nexport async function validateQueryPaths({\n collectionConfig,\n errors = [],\n globalConfig,\n overrideAccess,\n policies = {\n collections: {},\n globals: {},\n },\n polymorphicJoin,\n req,\n versionFields,\n where,\n}: Args): Promise<void> {\n const fields = versionFields || (globalConfig || collectionConfig).flattenedFields\n\n if (typeof where === 'object') {\n // We need to determine if the whereKey is an AND, OR, or a schema path\n const promises = []\n for (const path in where) {\n const constraint = where[path]\n\n if ((path === 'and' || path === 'or') && Array.isArray(constraint)) {\n for (const item of constraint) {\n if (collectionConfig) {\n promises.push(\n validateQueryPaths({\n collectionConfig,\n errors,\n overrideAccess,\n policies,\n req,\n versionFields,\n where: item,\n }),\n )\n } else {\n promises.push(\n validateQueryPaths({\n errors,\n globalConfig,\n overrideAccess,\n policies,\n req,\n versionFields,\n where: item,\n }),\n )\n }\n }\n } else if (!Array.isArray(constraint)) {\n for (const operator in constraint) {\n const val = constraint[operator]\n if (validOperatorSet.has(operator as Operator)) {\n promises.push(\n validateSearchParam({\n collectionConfig,\n constraint: where as WhereField,\n errors,\n fields,\n globalConfig,\n operator,\n overrideAccess,\n path,\n policies,\n polymorphicJoin,\n req,\n val,\n versionFields,\n }),\n )\n }\n }\n }\n }\n\n await Promise.all(promises)\n if (errors.length > 0) {\n throw new QueryError(errors)\n }\n }\n}\n"],"names":["QueryError","validOperatorSet","validateSearchParam","validateQueryPaths","collectionConfig","errors","globalConfig","overrideAccess","policies","collections","globals","polymorphicJoin","req","versionFields","where","fields","flattenedFields","promises","path","constraint","Array","isArray","item","push","operator","val","has","Promise","all","length"],"mappings":"AAAA,oBAAoB;AAOpB,SAASA,UAAU,QAAQ,6BAA4B;AACvD,SAASC,gBAAgB,QAAQ,2BAA0B;AAC3D,SAASC,mBAAmB,QAAQ,4BAA2B;AAqB/D,OAAO,eAAeC,mBAAmB,EACvCC,gBAAgB,EAChBC,SAAS,EAAE,EACXC,YAAY,EACZC,cAAc,EACdC,WAAW;IACTC,aAAa,CAAC;IACdC,SAAS,CAAC;AACZ,CAAC,EACDC,eAAe,EACfC,GAAG,EACHC,aAAa,EACbC,KAAK,EACA;IACL,MAAMC,SAASF,iBAAiB,AAACP,CAAAA,gBAAgBF,gBAAe,EAAGY,eAAe;IAElF,IAAI,OAAOF,UAAU,UAAU;QAC7B,uEAAuE;QACvE,MAAMG,WAAW,EAAE;QACnB,IAAK,MAAMC,QAAQJ,MAAO;YACxB,MAAMK,aAAaL,KAAK,CAACI,KAAK;YAE9B,IAAI,AAACA,CAAAA,SAAS,SAASA,SAAS,IAAG,KAAME,MAAMC,OAAO,CAACF,aAAa;gBAClE,KAAK,MAAMG,QAAQH,WAAY;oBAC7B,IAAIf,kBAAkB;wBACpBa,SAASM,IAAI,CACXpB,mBAAmB;4BACjBC;4BACAC;4BACAE;4BACAC;4BACAI;4BACAC;4BACAC,OAAOQ;wBACT;oBAEJ,OAAO;wBACLL,SAASM,IAAI,CACXpB,mBAAmB;4BACjBE;4BACAC;4BACAC;4BACAC;4BACAI;4BACAC;4BACAC,OAAOQ;wBACT;oBAEJ;gBACF;YACF,OAAO,IAAI,CAACF,MAAMC,OAAO,CAACF,aAAa;gBACrC,IAAK,MAAMK,YAAYL,WAAY;oBACjC,MAAMM,MAAMN,UAAU,CAACK,SAAS;oBAChC,IAAIvB,iBAAiByB,GAAG,CAACF,WAAuB;wBAC9CP,SAASM,IAAI,CACXrB,oBAAoB;4BAClBE;4BACAe,YAAYL;4BACZT;4BACAU;4BACAT;4BACAkB;4BACAjB;4BACAW;4BACAV;4BACAG;4BACAC;4BACAa;4BACAZ;wBACF;oBAEJ;gBACF;YACF;QACF;QAEA,MAAMc,QAAQC,GAAG,CAACX;QAClB,IAAIZ,OAAOwB,MAAM,GAAG,GAAG;YACrB,MAAM,IAAI7B,WAAWK;QACvB;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateSearchParams.d.ts","sourceRoot":"","sources":["../../../src/database/queryValidation/validateSearchParams.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,YAAY,CAAA;AAS7D,KAAK,IAAI,GAAG;IACV,gBAAgB,CAAC,EAAE,yBAAyB,CAAA;IAC5C,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC1B,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,OAAO,CAAA;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,cAAc,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,GAAG,EAAE,cAAc,CAAA;IACnB,GAAG,EAAE,OAAO,CAAA;IACZ,aAAa,CAAC,EAAE,cAAc,EAAE,CAAA;CACjC,CAAA;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,gBAAgB,EAChB,UAAU,EACV,MAAM,EACN,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,IAAI,EAAE,YAAY,EAClB,QAAQ,EACR,eAAe,EACf,GAAG,EACH,GAAG,EACH,aAAa,GACd,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"validateSearchParams.d.ts","sourceRoot":"","sources":["../../../src/database/queryValidation/validateSearchParams.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAClF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,YAAY,CAAA;AAS7D,KAAK,IAAI,GAAG;IACV,gBAAgB,CAAC,EAAE,yBAAyB,CAAA;IAC5C,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC1B,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,OAAO,CAAA;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,cAAc,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,GAAG,EAAE,cAAc,CAAA;IACnB,GAAG,EAAE,OAAO,CAAA;IACZ,aAAa,CAAC,EAAE,cAAc,EAAE,CAAA;CACjC,CAAA;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,gBAAgB,EAChB,UAAU,EACV,MAAM,EACN,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,IAAI,EAAE,YAAY,EAClB,QAAQ,EACR,eAAe,EACf,GAAG,EACH,GAAG,EACH,aAAa,GACd,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA0KtB"}
|
|
@@ -50,11 +50,9 @@ import { validateQueryPaths } from './validateQueryPaths.js';
|
|
|
50
50
|
}
|
|
51
51
|
promises.push(...paths.map(async ({ collectionSlug, field, invalid, path }, i)=>{
|
|
52
52
|
if (invalid) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
}
|
|
53
|
+
errors.push({
|
|
54
|
+
path
|
|
55
|
+
});
|
|
58
56
|
return;
|
|
59
57
|
}
|
|
60
58
|
if ('virtual' in field && field.virtual) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/database/queryValidation/validateSearchParams.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { SanitizedCollectionConfig } from '../../collections/config/types.js'\nimport type { FlattenedField } from '../../fields/config/types.js'\nimport type { SanitizedGlobalConfig } from '../../globals/config/types.js'\nimport type { PayloadRequest, WhereField } from '../../types/index.js'\nimport type { EntityPolicies, PathToQuery } from './types.js'\n\nimport { fieldAffectsData, fieldIsVirtual } from '../../fields/config/types.js'\nimport { getEntityPolicies } from '../../utilities/getEntityPolicies.js'\nimport { getFieldByPath } from '../../utilities/getFieldByPath.js'\nimport isolateObjectProperty from '../../utilities/isolateObjectProperty.js'\nimport { getLocalizedPaths } from '../getLocalizedPaths.js'\nimport { validateQueryPaths } from './validateQueryPaths.js'\n\ntype Args = {\n collectionConfig?: SanitizedCollectionConfig\n constraint: WhereField\n errors: { path: string }[]\n fields: FlattenedField[]\n globalConfig?: SanitizedGlobalConfig\n operator: string\n overrideAccess: boolean\n parentIsLocalized?: boolean\n path: string\n policies: EntityPolicies\n polymorphicJoin?: boolean\n req: PayloadRequest\n val: unknown\n versionFields?: FlattenedField[]\n}\n\n/**\n * Validate the Payload key / value / operator\n */\nexport async function validateSearchParam({\n collectionConfig,\n constraint,\n errors,\n fields,\n globalConfig,\n operator,\n overrideAccess,\n parentIsLocalized,\n path: incomingPath,\n policies,\n polymorphicJoin,\n req,\n val,\n versionFields,\n}: Args): Promise<void> {\n // Replace GraphQL nested field double underscore formatting\n let sanitizedPath\n if (incomingPath === '_id') {\n sanitizedPath = 'id'\n } else {\n sanitizedPath = incomingPath.replace(/__/g, '.')\n }\n let paths: PathToQuery[] = []\n const { slug } = collectionConfig || globalConfig\n\n const blockPolicies = {}\n\n if (globalConfig && !policies.globals[slug]) {\n policies.globals[slug] = await getEntityPolicies({\n type: 'global',\n blockPolicies,\n entity: globalConfig,\n operations: ['read'],\n req,\n })\n }\n\n if (sanitizedPath !== 'id') {\n paths = getLocalizedPaths({\n collectionSlug: collectionConfig?.slug,\n fields,\n globalSlug: globalConfig?.slug,\n incomingPath: sanitizedPath,\n locale: req.locale,\n overrideAccess,\n parentIsLocalized,\n payload: req.payload,\n })\n }\n const promises = []\n\n // Sanitize relation.otherRelation.id to relation.otherRelation\n if (paths.at(-1)?.path === 'id') {\n const previousField = paths.at(-2)?.field\n if (\n previousField &&\n (previousField.type === 'relationship' || previousField.type === 'upload') &&\n typeof previousField.relationTo === 'string'\n ) {\n paths.pop()\n }\n }\n\n promises.push(\n ...paths.map(async ({ collectionSlug, field, invalid, path }, i) => {\n if (invalid) {\n if (!polymorphicJoin) {\n errors.push({ path })\n }\n\n return\n }\n\n if ('virtual' in field && field.virtual) {\n if (field.virtual === true) {\n errors.push({ path })\n } else {\n constraint[`${field.virtual}`] = constraint[path]\n delete constraint[path]\n }\n }\n\n if (polymorphicJoin && path === 'relationTo') {\n return\n }\n\n if (!overrideAccess && fieldAffectsData(field)) {\n if (collectionSlug) {\n if (!policies.collections[collectionSlug]) {\n policies.collections[collectionSlug] = await getEntityPolicies({\n type: 'collection',\n blockPolicies,\n entity: req.payload.collections[collectionSlug].config,\n operations: ['read'],\n req: isolateObjectProperty(req, 'transactionID'),\n })\n }\n\n if (\n ['hash', 'salt'].includes(incomingPath) &&\n collectionConfig.auth &&\n !collectionConfig.auth?.disableLocalStrategy\n ) {\n errors.push({ path: incomingPath })\n }\n }\n let fieldPath = path\n // remove locale from end of path\n if (path.endsWith(`.${req.locale}`)) {\n fieldPath = path.slice(0, -(req.locale.length + 1))\n }\n // remove \".value\" from ends of polymorphic relationship paths\n if (\n (field.type === 'relationship' || field.type === 'upload') &&\n Array.isArray(field.relationTo)\n ) {\n fieldPath = fieldPath.replace('.value', '')\n }\n\n const entityType: 'collections' | 'globals' = globalConfig ? 'globals' : 'collections'\n const entitySlug = collectionSlug || globalConfig.slug\n const segments = fieldPath.split('.')\n\n let fieldAccess\n\n if (versionFields) {\n fieldAccess = policies[entityType][entitySlug]\n\n if (segments[0] === 'parent' || segments[0] === 'version') {\n segments.shift()\n }\n } else {\n fieldAccess = policies[entityType][entitySlug].fields\n }\n\n segments.forEach((segment) => {\n if (fieldAccess[segment]) {\n if ('fields' in fieldAccess[segment]) {\n fieldAccess = fieldAccess[segment].fields\n } else if (\n 'blocks' in fieldAccess[segment] ||\n 'blockReferences' in fieldAccess[segment]\n ) {\n fieldAccess = fieldAccess[segment]\n } else {\n fieldAccess = fieldAccess[segment]\n }\n }\n })\n\n if (!fieldAccess?.read?.permission) {\n errors.push({ path: fieldPath })\n }\n }\n\n if (i > 1) {\n // Remove top collection and reverse array\n // to work backwards from top\n const pathsToQuery = paths.slice(1).reverse()\n\n pathsToQuery.forEach(\n ({ collectionSlug: pathCollectionSlug, path: subPath }, pathToQueryIndex) => {\n // On the \"deepest\" collection,\n // validate query of the relationship\n if (pathToQueryIndex === 0) {\n promises.push(\n validateQueryPaths({\n collectionConfig: req.payload.collections[pathCollectionSlug].config,\n errors,\n globalConfig: undefined,\n overrideAccess,\n policies,\n req,\n where: {\n [subPath]: {\n [operator]: val,\n },\n },\n }),\n )\n }\n },\n )\n }\n }),\n )\n await Promise.all(promises)\n}\n"],"names":["fieldAffectsData","getEntityPolicies","isolateObjectProperty","getLocalizedPaths","validateQueryPaths","validateSearchParam","collectionConfig","constraint","errors","fields","globalConfig","operator","overrideAccess","parentIsLocalized","path","incomingPath","policies","polymorphicJoin","req","val","versionFields","sanitizedPath","replace","paths","slug","blockPolicies","globals","type","entity","operations","collectionSlug","globalSlug","locale","payload","promises","at","previousField","field","relationTo","pop","push","map","invalid","i","virtual","collections","config","includes","auth","disableLocalStrategy","fieldPath","endsWith","slice","length","Array","isArray","entityType","entitySlug","segments","split","fieldAccess","shift","forEach","segment","read","permission","pathsToQuery","reverse","pathCollectionSlug","subPath","pathToQueryIndex","undefined","where","Promise","all"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/database/queryValidation/validateSearchParams.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { SanitizedCollectionConfig } from '../../collections/config/types.js'\nimport type { FlattenedField } from '../../fields/config/types.js'\nimport type { SanitizedGlobalConfig } from '../../globals/config/types.js'\nimport type { PayloadRequest, WhereField } from '../../types/index.js'\nimport type { EntityPolicies, PathToQuery } from './types.js'\n\nimport { fieldAffectsData, fieldIsVirtual } from '../../fields/config/types.js'\nimport { getEntityPolicies } from '../../utilities/getEntityPolicies.js'\nimport { getFieldByPath } from '../../utilities/getFieldByPath.js'\nimport isolateObjectProperty from '../../utilities/isolateObjectProperty.js'\nimport { getLocalizedPaths } from '../getLocalizedPaths.js'\nimport { validateQueryPaths } from './validateQueryPaths.js'\n\ntype Args = {\n collectionConfig?: SanitizedCollectionConfig\n constraint: WhereField\n errors: { path: string }[]\n fields: FlattenedField[]\n globalConfig?: SanitizedGlobalConfig\n operator: string\n overrideAccess: boolean\n parentIsLocalized?: boolean\n path: string\n policies: EntityPolicies\n polymorphicJoin?: boolean\n req: PayloadRequest\n val: unknown\n versionFields?: FlattenedField[]\n}\n\n/**\n * Validate the Payload key / value / operator\n */\nexport async function validateSearchParam({\n collectionConfig,\n constraint,\n errors,\n fields,\n globalConfig,\n operator,\n overrideAccess,\n parentIsLocalized,\n path: incomingPath,\n policies,\n polymorphicJoin,\n req,\n val,\n versionFields,\n}: Args): Promise<void> {\n // Replace GraphQL nested field double underscore formatting\n let sanitizedPath\n if (incomingPath === '_id') {\n sanitizedPath = 'id'\n } else {\n sanitizedPath = incomingPath.replace(/__/g, '.')\n }\n let paths: PathToQuery[] = []\n const { slug } = collectionConfig || globalConfig\n\n const blockPolicies = {}\n\n if (globalConfig && !policies.globals[slug]) {\n policies.globals[slug] = await getEntityPolicies({\n type: 'global',\n blockPolicies,\n entity: globalConfig,\n operations: ['read'],\n req,\n })\n }\n\n if (sanitizedPath !== 'id') {\n paths = getLocalizedPaths({\n collectionSlug: collectionConfig?.slug,\n fields,\n globalSlug: globalConfig?.slug,\n incomingPath: sanitizedPath,\n locale: req.locale,\n overrideAccess,\n parentIsLocalized,\n payload: req.payload,\n })\n }\n const promises = []\n\n // Sanitize relation.otherRelation.id to relation.otherRelation\n if (paths.at(-1)?.path === 'id') {\n const previousField = paths.at(-2)?.field\n if (\n previousField &&\n (previousField.type === 'relationship' || previousField.type === 'upload') &&\n typeof previousField.relationTo === 'string'\n ) {\n paths.pop()\n }\n }\n\n promises.push(\n ...paths.map(async ({ collectionSlug, field, invalid, path }, i) => {\n if (invalid) {\n errors.push({ path })\n return\n }\n\n if ('virtual' in field && field.virtual) {\n if (field.virtual === true) {\n errors.push({ path })\n } else {\n constraint[`${field.virtual}`] = constraint[path]\n delete constraint[path]\n }\n }\n\n if (polymorphicJoin && path === 'relationTo') {\n return\n }\n\n if (!overrideAccess && fieldAffectsData(field)) {\n if (collectionSlug) {\n if (!policies.collections[collectionSlug]) {\n policies.collections[collectionSlug] = await getEntityPolicies({\n type: 'collection',\n blockPolicies,\n entity: req.payload.collections[collectionSlug].config,\n operations: ['read'],\n req: isolateObjectProperty(req, 'transactionID'),\n })\n }\n\n if (\n ['hash', 'salt'].includes(incomingPath) &&\n collectionConfig.auth &&\n !collectionConfig.auth?.disableLocalStrategy\n ) {\n errors.push({ path: incomingPath })\n }\n }\n let fieldPath = path\n // remove locale from end of path\n if (path.endsWith(`.${req.locale}`)) {\n fieldPath = path.slice(0, -(req.locale.length + 1))\n }\n // remove \".value\" from ends of polymorphic relationship paths\n if (\n (field.type === 'relationship' || field.type === 'upload') &&\n Array.isArray(field.relationTo)\n ) {\n fieldPath = fieldPath.replace('.value', '')\n }\n\n const entityType: 'collections' | 'globals' = globalConfig ? 'globals' : 'collections'\n const entitySlug = collectionSlug || globalConfig.slug\n const segments = fieldPath.split('.')\n\n let fieldAccess\n\n if (versionFields) {\n fieldAccess = policies[entityType][entitySlug]\n\n if (segments[0] === 'parent' || segments[0] === 'version') {\n segments.shift()\n }\n } else {\n fieldAccess = policies[entityType][entitySlug].fields\n }\n\n segments.forEach((segment) => {\n if (fieldAccess[segment]) {\n if ('fields' in fieldAccess[segment]) {\n fieldAccess = fieldAccess[segment].fields\n } else if (\n 'blocks' in fieldAccess[segment] ||\n 'blockReferences' in fieldAccess[segment]\n ) {\n fieldAccess = fieldAccess[segment]\n } else {\n fieldAccess = fieldAccess[segment]\n }\n }\n })\n\n if (!fieldAccess?.read?.permission) {\n errors.push({ path: fieldPath })\n }\n }\n\n if (i > 1) {\n // Remove top collection and reverse array\n // to work backwards from top\n const pathsToQuery = paths.slice(1).reverse()\n\n pathsToQuery.forEach(\n ({ collectionSlug: pathCollectionSlug, path: subPath }, pathToQueryIndex) => {\n // On the \"deepest\" collection,\n // validate query of the relationship\n if (pathToQueryIndex === 0) {\n promises.push(\n validateQueryPaths({\n collectionConfig: req.payload.collections[pathCollectionSlug].config,\n errors,\n globalConfig: undefined,\n overrideAccess,\n policies,\n req,\n where: {\n [subPath]: {\n [operator]: val,\n },\n },\n }),\n )\n }\n },\n )\n }\n }),\n )\n await Promise.all(promises)\n}\n"],"names":["fieldAffectsData","getEntityPolicies","isolateObjectProperty","getLocalizedPaths","validateQueryPaths","validateSearchParam","collectionConfig","constraint","errors","fields","globalConfig","operator","overrideAccess","parentIsLocalized","path","incomingPath","policies","polymorphicJoin","req","val","versionFields","sanitizedPath","replace","paths","slug","blockPolicies","globals","type","entity","operations","collectionSlug","globalSlug","locale","payload","promises","at","previousField","field","relationTo","pop","push","map","invalid","i","virtual","collections","config","includes","auth","disableLocalStrategy","fieldPath","endsWith","slice","length","Array","isArray","entityType","entitySlug","segments","split","fieldAccess","shift","forEach","segment","read","permission","pathsToQuery","reverse","pathCollectionSlug","subPath","pathToQueryIndex","undefined","where","Promise","all"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processMultipart.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAW5D,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE;IAC7B,OAAO,EAAE,yBAAyB,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAA;AACzC,eAAO,MAAM,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"processMultipart.d.ts","sourceRoot":"","sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA;AAW5D,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE;IAC7B,OAAO,EAAE,yBAAyB,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAA;AACzC,eAAO,MAAM,gBAAgB,EAAE,gBAmM9B,CAAA"}
|
|
@@ -47,7 +47,6 @@ export const processMultipart = async ({ options, request })=>{
|
|
|
47
47
|
// Parse file name(cutting huge names, decoding, etc..).
|
|
48
48
|
const { encoding, filename: name, mimeType: mime } = info;
|
|
49
49
|
const filename = parseFileName(options, name);
|
|
50
|
-
const inferredMimeType = filename && filename.endsWith('.glb') && 'model/gltf-binary' || filename && filename.endsWith('.gltf') && 'model/gltf+json' || mime;
|
|
51
50
|
// Define methods and handlers for upload process.
|
|
52
51
|
const { cleanup, complete, dataHandler, getFilePath, getFileSize, getHash, getWritePromise } = options.useTempFiles ? tempFileHandler(options, field, filename) // Upload into temporary file.
|
|
53
52
|
: memHandler(options, field, filename) // Upload into RAM.
|
|
@@ -99,7 +98,7 @@ export const processMultipart = async ({ options, request })=>{
|
|
|
99
98
|
buffer: complete(),
|
|
100
99
|
encoding,
|
|
101
100
|
hash: getHash(),
|
|
102
|
-
mimetype:
|
|
101
|
+
mimetype: mime,
|
|
103
102
|
size,
|
|
104
103
|
tempFilePath: getFilePath(),
|
|
105
104
|
truncated: Boolean('truncated' in file && file.truncated) || false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { Readable } from 'stream'\n\nimport Busboy from 'busboy'\nimport { status as httpStatus } from 'http-status'\n\nimport type { FetchAPIFileUploadOptions } from '../../config/types.js'\nimport type { FetchAPIFileUploadResponse } from './index.js'\n\nimport { APIError } from '../../errors/APIError.js'\nimport { fileFactory } from './fileFactory.js'\nimport { memHandler, tempFileHandler } from './handlers.js'\nimport { processNested } from './processNested.js'\nimport { createUploadTimer } from './uploadTimer.js'\nimport { buildFields, debugLog, isFunc, parseFileName } from './utilities.js'\n\nconst waitFlushProperty = Symbol('wait flush property symbol')\n\ntype ProcessMultipart = (args: {\n options: FetchAPIFileUploadOptions\n request: Request\n}) => Promise<FetchAPIFileUploadResponse>\nexport const processMultipart: ProcessMultipart = async ({ options, request }) => {\n let parsingRequest = true\n\n let shouldAbortProccessing = false\n let fileCount = 0\n let filesCompleted = 0\n let allFilesHaveResolved: (value?: unknown) => void\n let failedResolvingFiles: (err: Error) => void\n\n const allFilesComplete = new Promise((res, rej) => {\n allFilesHaveResolved = res\n failedResolvingFiles = rej\n })\n\n const result: FetchAPIFileUploadResponse = {\n fields: undefined,\n files: undefined,\n }\n\n const headersObject = {}\n request.headers.forEach((value, name) => {\n headersObject[name] = value\n })\n\n const reader = request.body.getReader()\n\n const busboy = Busboy({ ...options, headers: headersObject })\n\n function abortAndDestroyFile(file: Readable, err: APIError) {\n file.destroy()\n shouldAbortProccessing = true\n failedResolvingFiles(err)\n }\n\n // Build multipart req.body fields\n busboy.on('field', (field, val) => {\n result.fields = buildFields(result.fields, field, val)\n })\n\n // Build req.files fields\n busboy.on('file', (field, file, info) => {\n fileCount += 1\n // Parse file name(cutting huge names, decoding, etc..).\n const { encoding, filename: name, mimeType: mime } = info\n const filename = parseFileName(options, name)\n\n const inferredMimeType =\n (filename && filename.endsWith('.glb') && 'model/gltf-binary') ||\n (filename && filename.endsWith('.gltf') && 'model/gltf+json') ||\n mime\n\n // Define methods and handlers for upload process.\n const { cleanup, complete, dataHandler, getFilePath, getFileSize, getHash, getWritePromise } =\n options.useTempFiles\n ? tempFileHandler(options, field, filename) // Upload into temporary file.\n : memHandler(options, field, filename) // Upload into RAM.\n\n const writePromise = options.useTempFiles\n ? getWritePromise().catch((err) => {\n busboy.end()\n cleanup()\n })\n : getWritePromise()\n\n const uploadTimer = createUploadTimer(options.uploadTimeout, () => {\n return abortAndDestroyFile(\n file,\n new APIError(`Upload timeout for ${field}->${filename}, bytes:${getFileSize()}`),\n )\n })\n\n file.on('limit', () => {\n debugLog(options, `Size limit reached for ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.clear()\n\n if (isFunc(options.limitHandler)) {\n options.limitHandler({ request, size: getFileSize() })\n }\n\n // Return error and cleanup files if abortOnLimit set.\n if (options.abortOnLimit) {\n debugLog(options, `Upload file size limit reached ${field}->${filename}.`)\n cleanup()\n abortAndDestroyFile(\n file,\n new APIError(options.responseOnLimit, httpStatus.REQUEST_ENTITY_TOO_LARGE, {\n size: getFileSize(),\n }),\n )\n }\n })\n\n file.on('data', (data) => {\n uploadTimer.set()\n dataHandler(data)\n })\n\n file.on('end', () => {\n const size = getFileSize()\n debugLog(options, `Upload finished ${field}->${filename}, bytes:${size}`)\n uploadTimer.clear()\n\n if (!name && size === 0) {\n fileCount -= 1\n if (options.useTempFiles) {\n cleanup()\n debugLog(options, `Removing the empty file ${field}->${filename}`)\n }\n return debugLog(options, `Don't add file instance if original name and size are empty`)\n }\n\n filesCompleted += 1\n\n result.files = buildFields(\n result.files,\n field,\n fileFactory(\n {\n name: filename,\n buffer: complete(),\n encoding,\n hash: getHash(),\n mimetype: inferredMimeType,\n size,\n tempFilePath: getFilePath(),\n truncated: Boolean('truncated' in file && file.truncated) || false,\n },\n options,\n ),\n )\n\n if (!request[waitFlushProperty]) {\n request[waitFlushProperty] = []\n }\n request[waitFlushProperty].push(writePromise)\n\n if (filesCompleted === fileCount) {\n allFilesHaveResolved()\n }\n })\n\n file.on('error', (err) => {\n uploadTimer.clear()\n debugLog(options, `File Error: ${err.message}`)\n cleanup()\n failedResolvingFiles(err)\n })\n\n // Start upload process.\n debugLog(options, `New upload started ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.set()\n })\n\n busboy.on('finish', async () => {\n debugLog(options, `Busboy finished parsing request.`)\n if (options.parseNested) {\n result.fields = processNested(result.fields)\n result.files = processNested(result.files)\n }\n\n if (request[waitFlushProperty]) {\n try {\n await Promise.all(request[waitFlushProperty]).then(() => {\n delete request[waitFlushProperty]\n })\n } catch (err) {\n debugLog(options, `Error waiting for file write promises: ${err}`)\n }\n }\n\n return result\n })\n\n busboy.on(\n 'error',\n (err = new APIError('Busboy error parsing multipart request', httpStatus.BAD_REQUEST)) => {\n debugLog(options, `Busboy error`)\n throw err\n },\n )\n\n while (parsingRequest) {\n const { done, value } = await reader.read()\n\n if (done) {\n parsingRequest = false\n }\n\n if (value && !shouldAbortProccessing) {\n busboy.write(value)\n }\n }\n\n if (fileCount !== 0) {\n await allFilesComplete.catch((e) => {\n throw e\n })\n }\n\n return result\n}\n"],"names":["Busboy","status","httpStatus","APIError","fileFactory","memHandler","tempFileHandler","processNested","createUploadTimer","buildFields","debugLog","isFunc","parseFileName","waitFlushProperty","Symbol","processMultipart","options","request","parsingRequest","shouldAbortProccessing","fileCount","filesCompleted","allFilesHaveResolved","failedResolvingFiles","allFilesComplete","Promise","res","rej","result","fields","undefined","files","headersObject","headers","forEach","value","name","reader","body","getReader","busboy","abortAndDestroyFile","file","err","destroy","on","field","val","info","encoding","filename","mimeType","mime","inferredMimeType","endsWith","cleanup","complete","dataHandler","getFilePath","getFileSize","getHash","getWritePromise","useTempFiles","writePromise","catch","end","uploadTimer","uploadTimeout","clear","limitHandler","size","abortOnLimit","responseOnLimit","REQUEST_ENTITY_TOO_LARGE","data","set","buffer","hash","mimetype","tempFilePath","truncated","Boolean","push","message","parseNested","all","then","BAD_REQUEST","done","read","write","e"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/uploads/fetchAPI-multipart/processMultipart.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { Readable } from 'stream'\n\nimport Busboy from 'busboy'\nimport { status as httpStatus } from 'http-status'\n\nimport type { FetchAPIFileUploadOptions } from '../../config/types.js'\nimport type { FetchAPIFileUploadResponse } from './index.js'\n\nimport { APIError } from '../../errors/APIError.js'\nimport { fileFactory } from './fileFactory.js'\nimport { memHandler, tempFileHandler } from './handlers.js'\nimport { processNested } from './processNested.js'\nimport { createUploadTimer } from './uploadTimer.js'\nimport { buildFields, debugLog, isFunc, parseFileName } from './utilities.js'\n\nconst waitFlushProperty = Symbol('wait flush property symbol')\n\ntype ProcessMultipart = (args: {\n options: FetchAPIFileUploadOptions\n request: Request\n}) => Promise<FetchAPIFileUploadResponse>\nexport const processMultipart: ProcessMultipart = async ({ options, request }) => {\n let parsingRequest = true\n\n let shouldAbortProccessing = false\n let fileCount = 0\n let filesCompleted = 0\n let allFilesHaveResolved: (value?: unknown) => void\n let failedResolvingFiles: (err: Error) => void\n\n const allFilesComplete = new Promise((res, rej) => {\n allFilesHaveResolved = res\n failedResolvingFiles = rej\n })\n\n const result: FetchAPIFileUploadResponse = {\n fields: undefined,\n files: undefined,\n }\n\n const headersObject = {}\n request.headers.forEach((value, name) => {\n headersObject[name] = value\n })\n\n const reader = request.body.getReader()\n\n const busboy = Busboy({ ...options, headers: headersObject })\n\n function abortAndDestroyFile(file: Readable, err: APIError) {\n file.destroy()\n shouldAbortProccessing = true\n failedResolvingFiles(err)\n }\n\n // Build multipart req.body fields\n busboy.on('field', (field, val) => {\n result.fields = buildFields(result.fields, field, val)\n })\n\n // Build req.files fields\n busboy.on('file', (field, file, info) => {\n fileCount += 1\n // Parse file name(cutting huge names, decoding, etc..).\n const { encoding, filename: name, mimeType: mime } = info\n const filename = parseFileName(options, name)\n\n // Define methods and handlers for upload process.\n const { cleanup, complete, dataHandler, getFilePath, getFileSize, getHash, getWritePromise } =\n options.useTempFiles\n ? tempFileHandler(options, field, filename) // Upload into temporary file.\n : memHandler(options, field, filename) // Upload into RAM.\n\n const writePromise = options.useTempFiles\n ? getWritePromise().catch((err) => {\n busboy.end()\n cleanup()\n })\n : getWritePromise()\n\n const uploadTimer = createUploadTimer(options.uploadTimeout, () => {\n return abortAndDestroyFile(\n file,\n new APIError(`Upload timeout for ${field}->${filename}, bytes:${getFileSize()}`),\n )\n })\n\n file.on('limit', () => {\n debugLog(options, `Size limit reached for ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.clear()\n\n if (isFunc(options.limitHandler)) {\n options.limitHandler({ request, size: getFileSize() })\n }\n\n // Return error and cleanup files if abortOnLimit set.\n if (options.abortOnLimit) {\n debugLog(options, `Upload file size limit reached ${field}->${filename}.`)\n cleanup()\n abortAndDestroyFile(\n file,\n new APIError(options.responseOnLimit, httpStatus.REQUEST_ENTITY_TOO_LARGE, {\n size: getFileSize(),\n }),\n )\n }\n })\n\n file.on('data', (data) => {\n uploadTimer.set()\n dataHandler(data)\n })\n\n file.on('end', () => {\n const size = getFileSize()\n debugLog(options, `Upload finished ${field}->${filename}, bytes:${size}`)\n uploadTimer.clear()\n\n if (!name && size === 0) {\n fileCount -= 1\n if (options.useTempFiles) {\n cleanup()\n debugLog(options, `Removing the empty file ${field}->${filename}`)\n }\n return debugLog(options, `Don't add file instance if original name and size are empty`)\n }\n\n filesCompleted += 1\n\n result.files = buildFields(\n result.files,\n field,\n fileFactory(\n {\n name: filename,\n buffer: complete(),\n encoding,\n hash: getHash(),\n mimetype: mime,\n size,\n tempFilePath: getFilePath(),\n truncated: Boolean('truncated' in file && file.truncated) || false,\n },\n options,\n ),\n )\n\n if (!request[waitFlushProperty]) {\n request[waitFlushProperty] = []\n }\n request[waitFlushProperty].push(writePromise)\n\n if (filesCompleted === fileCount) {\n allFilesHaveResolved()\n }\n })\n\n file.on('error', (err) => {\n uploadTimer.clear()\n debugLog(options, `File Error: ${err.message}`)\n cleanup()\n failedResolvingFiles(err)\n })\n\n // Start upload process.\n debugLog(options, `New upload started ${field}->${filename}, bytes:${getFileSize()}`)\n uploadTimer.set()\n })\n\n busboy.on('finish', async () => {\n debugLog(options, `Busboy finished parsing request.`)\n if (options.parseNested) {\n result.fields = processNested(result.fields)\n result.files = processNested(result.files)\n }\n\n if (request[waitFlushProperty]) {\n try {\n await Promise.all(request[waitFlushProperty]).then(() => {\n delete request[waitFlushProperty]\n })\n } catch (err) {\n debugLog(options, `Error waiting for file write promises: ${err}`)\n }\n }\n\n return result\n })\n\n busboy.on(\n 'error',\n (err = new APIError('Busboy error parsing multipart request', httpStatus.BAD_REQUEST)) => {\n debugLog(options, `Busboy error`)\n throw err\n },\n )\n\n while (parsingRequest) {\n const { done, value } = await reader.read()\n\n if (done) {\n parsingRequest = false\n }\n\n if (value && !shouldAbortProccessing) {\n busboy.write(value)\n }\n }\n\n if (fileCount !== 0) {\n await allFilesComplete.catch((e) => {\n throw e\n })\n }\n\n return result\n}\n"],"names":["Busboy","status","httpStatus","APIError","fileFactory","memHandler","tempFileHandler","processNested","createUploadTimer","buildFields","debugLog","isFunc","parseFileName","waitFlushProperty","Symbol","processMultipart","options","request","parsingRequest","shouldAbortProccessing","fileCount","filesCompleted","allFilesHaveResolved","failedResolvingFiles","allFilesComplete","Promise","res","rej","result","fields","undefined","files","headersObject","headers","forEach","value","name","reader","body","getReader","busboy","abortAndDestroyFile","file","err","destroy","on","field","val","info","encoding","filename","mimeType","mime","cleanup","complete","dataHandler","getFilePath","getFileSize","getHash","getWritePromise","useTempFiles","writePromise","catch","end","uploadTimer","uploadTimeout","clear","limitHandler","size","abortOnLimit","responseOnLimit","REQUEST_ENTITY_TOO_LARGE","data","set","buffer","hash","mimetype","tempFilePath","truncated","Boolean","push","message","parseNested","all","then","BAD_REQUEST","done","read","write","e"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getExternalFile.d.ts","sourceRoot":"","sources":["../../src/uploads/getExternalFile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getExternalFile.d.ts","sourceRoot":"","sources":["../../src/uploads/getExternalFile.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAI9D,KAAK,IAAI,GAAG;IACV,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;IACnB,YAAY,EAAE,YAAY,CAAA;CAC3B,CAAA;AACD,eAAO,MAAM,eAAe,gCAAuC,IAAI,KAAG,OAAO,CAAC,IAAI,CAyCrF,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import ssrfFilter from 'ssrf-req-filter';
|
|
2
2
|
import { APIError } from '../errors/index.js';
|
|
3
3
|
export const getExternalFile = async ({ data, req, uploadConfig })=>{
|
|
4
4
|
const { filename, url } = data;
|
|
@@ -8,6 +8,13 @@ export const getExternalFile = async ({ data, req, uploadConfig })=>{
|
|
|
8
8
|
const baseUrl = req.headers.get('origin') || `${req.protocol}://${req.headers.get('host')}`;
|
|
9
9
|
fileURL = `${baseUrl}${url}`;
|
|
10
10
|
}
|
|
11
|
+
try {
|
|
12
|
+
ssrfFilter({
|
|
13
|
+
url: fileURL
|
|
14
|
+
});
|
|
15
|
+
} catch (error) {
|
|
16
|
+
throw new APIError(`Failed to fetch file from filtered url, ${fileURL}`, 400);
|
|
17
|
+
}
|
|
11
18
|
const headers = uploadConfig.externalFileHeaderFilter ? uploadConfig.externalFileHeaderFilter(Object.fromEntries(new Headers(req.headers))) : {
|
|
12
19
|
cookie: req.headers?.get('cookie')
|
|
13
20
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/uploads/getExternalFile.ts"],"sourcesContent":["// @ts-strict-ignore\nimport type { PayloadRequest } from '../types/index.js'\nimport type { File, FileData, UploadConfig } from './types.js'\n\nimport { APIError } from '../errors/index.js'\n\ntype Args = {\n data: FileData\n req: PayloadRequest\n uploadConfig: UploadConfig\n}\nexport const getExternalFile = async ({ data, req, uploadConfig }: Args): Promise<File> => {\n const { filename, url } = data\n\n if (typeof url === 'string') {\n let fileURL = url\n if (!url.startsWith('http')) {\n const baseUrl = req.headers.get('origin') || `${req.protocol}://${req.headers.get('host')}`\n fileURL = `${baseUrl}${url}`\n }\n\n const headers = uploadConfig.externalFileHeaderFilter\n ? uploadConfig.externalFileHeaderFilter(Object.fromEntries(new Headers(req.headers)))\n : { cookie: req.headers?.get('cookie') }\n\n const res = await fetch(fileURL, {\n credentials: 'include',\n headers,\n method: 'GET',\n })\n\n if (!res.ok) {\n throw new APIError(`Failed to fetch file from ${fileURL}`, res.status)\n }\n\n const data = await res.arrayBuffer()\n\n return {\n name: filename,\n data: Buffer.from(data),\n mimetype: res.headers.get('content-type') || undefined,\n size: Number(res.headers.get('content-length')) || 0,\n }\n }\n\n throw new APIError('Invalid file url', 400)\n}\n"],"names":["APIError","getExternalFile","data","req","uploadConfig","filename","url","fileURL","startsWith","baseUrl","headers","get","protocol","externalFileHeaderFilter","Object","fromEntries","Headers","cookie","res","fetch","credentials","method","ok","status","arrayBuffer","name","Buffer","from","mimetype","undefined","size","Number"],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/getExternalFile.ts"],"sourcesContent":["import ssrfFilter from 'ssrf-req-filter'\n\n// @ts-strict-ignore\nimport type { PayloadRequest } from '../types/index.js'\nimport type { File, FileData, UploadConfig } from './types.js'\n\nimport { APIError } from '../errors/index.js'\n\ntype Args = {\n data: FileData\n req: PayloadRequest\n uploadConfig: UploadConfig\n}\nexport const getExternalFile = async ({ data, req, uploadConfig }: Args): Promise<File> => {\n const { filename, url } = data\n\n if (typeof url === 'string') {\n let fileURL = url\n if (!url.startsWith('http')) {\n const baseUrl = req.headers.get('origin') || `${req.protocol}://${req.headers.get('host')}`\n fileURL = `${baseUrl}${url}`\n }\n\n try {\n ssrfFilter({ url: fileURL })\n } catch (error) {\n throw new APIError(`Failed to fetch file from filtered url, ${fileURL}`, 400)\n }\n\n const headers = uploadConfig.externalFileHeaderFilter\n ? uploadConfig.externalFileHeaderFilter(Object.fromEntries(new Headers(req.headers)))\n : { cookie: req.headers?.get('cookie') }\n\n const res = await fetch(fileURL, {\n credentials: 'include',\n headers,\n method: 'GET',\n })\n\n if (!res.ok) {\n throw new APIError(`Failed to fetch file from ${fileURL}`, res.status)\n }\n\n const data = await res.arrayBuffer()\n\n return {\n name: filename,\n data: Buffer.from(data),\n mimetype: res.headers.get('content-type') || undefined,\n size: Number(res.headers.get('content-length')) || 0,\n }\n }\n\n throw new APIError('Invalid file url', 400)\n}\n"],"names":["ssrfFilter","APIError","getExternalFile","data","req","uploadConfig","filename","url","fileURL","startsWith","baseUrl","headers","get","protocol","error","externalFileHeaderFilter","Object","fromEntries","Headers","cookie","res","fetch","credentials","method","ok","status","arrayBuffer","name","Buffer","from","mimetype","undefined","size","Number"],"mappings":"AAAA,OAAOA,gBAAgB,kBAAiB;AAMxC,SAASC,QAAQ,QAAQ,qBAAoB;AAO7C,OAAO,MAAMC,kBAAkB,OAAO,EAAEC,IAAI,EAAEC,GAAG,EAAEC,YAAY,EAAQ;IACrE,MAAM,EAAEC,QAAQ,EAAEC,GAAG,EAAE,GAAGJ;IAE1B,IAAI,OAAOI,QAAQ,UAAU;QAC3B,IAAIC,UAAUD;QACd,IAAI,CAACA,IAAIE,UAAU,CAAC,SAAS;YAC3B,MAAMC,UAAUN,IAAIO,OAAO,CAACC,GAAG,CAAC,aAAa,GAAGR,IAAIS,QAAQ,CAAC,GAAG,EAAET,IAAIO,OAAO,CAACC,GAAG,CAAC,SAAS;YAC3FJ,UAAU,GAAGE,UAAUH,KAAK;QAC9B;QAEA,IAAI;YACFP,WAAW;gBAAEO,KAAKC;YAAQ;QAC5B,EAAE,OAAOM,OAAO;YACd,MAAM,IAAIb,SAAS,CAAC,wCAAwC,EAAEO,SAAS,EAAE;QAC3E;QAEA,MAAMG,UAAUN,aAAaU,wBAAwB,GACjDV,aAAaU,wBAAwB,CAACC,OAAOC,WAAW,CAAC,IAAIC,QAAQd,IAAIO,OAAO,MAChF;YAAEQ,QAAQf,IAAIO,OAAO,EAAEC,IAAI;QAAU;QAEzC,MAAMQ,MAAM,MAAMC,MAAMb,SAAS;YAC/Bc,aAAa;YACbX;YACAY,QAAQ;QACV;QAEA,IAAI,CAACH,IAAII,EAAE,EAAE;YACX,MAAM,IAAIvB,SAAS,CAAC,0BAA0B,EAAEO,SAAS,EAAEY,IAAIK,MAAM;QACvE;QAEA,MAAMtB,OAAO,MAAMiB,IAAIM,WAAW;QAElC,OAAO;YACLC,MAAMrB;YACNH,MAAMyB,OAAOC,IAAI,CAAC1B;YAClB2B,UAAUV,IAAIT,OAAO,CAACC,GAAG,CAAC,mBAAmBmB;YAC7CC,MAAMC,OAAOb,IAAIT,OAAO,CAACC,GAAG,CAAC,sBAAsB;QACrD;IACF;IAEA,MAAM,IAAIX,SAAS,oBAAoB;AACzC,EAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload",
|
|
3
|
-
"version": "3.41.0-
|
|
3
|
+
"version": "3.41.0-internal.8617025",
|
|
4
4
|
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"admin panel",
|
|
@@ -95,14 +95,15 @@
|
|
|
95
95
|
"qs-esm": "7.0.2",
|
|
96
96
|
"sanitize-filename": "1.6.3",
|
|
97
97
|
"scmp": "2.1.0",
|
|
98
|
+
"ssrf-req-filter": "1.1.1",
|
|
98
99
|
"ts-essentials": "10.0.3",
|
|
99
100
|
"tsx": "4.19.2",
|
|
100
101
|
"uuid": "10.0.0",
|
|
101
102
|
"ws": "^8.16.0",
|
|
102
|
-
"@payloadcms/translations": "3.41.0-
|
|
103
|
+
"@payloadcms/translations": "3.41.0-internal.8617025"
|
|
103
104
|
},
|
|
104
105
|
"devDependencies": {
|
|
105
|
-
"@hyrious/esbuild-plugin-commonjs": "0.2.
|
|
106
|
+
"@hyrious/esbuild-plugin-commonjs": "^0.2.4",
|
|
106
107
|
"@monaco-editor/react": "4.7.0",
|
|
107
108
|
"@types/json-schema": "7.0.15",
|
|
108
109
|
"@types/minimist": "1.2.2",
|
|
@@ -113,7 +114,7 @@
|
|
|
113
114
|
"concurrently": "9.1.2",
|
|
114
115
|
"copyfiles": "2.4.1",
|
|
115
116
|
"cross-env": "7.0.3",
|
|
116
|
-
"esbuild": "0.
|
|
117
|
+
"esbuild": "0.24.2",
|
|
117
118
|
"graphql-http": "^1.22.0",
|
|
118
119
|
"react-datepicker": "7.6.0",
|
|
119
120
|
"rimraf": "6.0.1",
|