payload 3.89.0-internal.95c9cba → 3.90.0
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/admin/forms/Field.d.ts +2 -0
- package/dist/admin/forms/Field.d.ts.map +1 -1
- package/dist/admin/forms/Field.js.map +1 -1
- package/dist/admin/forms/Form.d.ts +2 -0
- package/dist/admin/forms/Form.d.ts.map +1 -1
- package/dist/admin/forms/Form.js.map +1 -1
- package/dist/admin/functions/index.d.ts +3 -1
- package/dist/admin/functions/index.d.ts.map +1 -1
- package/dist/admin/functions/index.js.map +1 -1
- package/dist/admin/views/dashboard.d.ts +1 -1
- package/dist/admin/views/dashboard.d.ts.map +1 -1
- package/dist/admin/views/dashboard.js.map +1 -1
- package/dist/auth/applyUserReadAccess.d.ts +15 -0
- package/dist/auth/applyUserReadAccess.d.ts.map +1 -0
- package/dist/auth/applyUserReadAccess.js +41 -0
- package/dist/auth/applyUserReadAccess.js.map +1 -0
- package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.d.ts +4 -0
- package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.d.ts.map +1 -0
- package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.js +20 -0
- package/dist/auth/baseFields/apiKey/canCreateOrUpdateAPIKey.js.map +1 -0
- package/dist/auth/baseFields/apiKey/encryptAPIKey.d.ts +4 -0
- package/dist/auth/baseFields/apiKey/encryptAPIKey.d.ts.map +1 -0
- package/dist/auth/baseFields/apiKey/encryptAPIKey.js +16 -0
- package/dist/auth/baseFields/apiKey/encryptAPIKey.js.map +1 -0
- package/dist/auth/baseFields/apiKey/index.d.ts +6 -0
- package/dist/auth/baseFields/apiKey/index.d.ts.map +1 -0
- package/dist/auth/baseFields/apiKey/index.js +112 -0
- package/dist/auth/baseFields/apiKey/index.js.map +1 -0
- package/dist/auth/baseFields/apiKey/omitAPIKey.d.ts +4 -0
- package/dist/auth/baseFields/apiKey/omitAPIKey.d.ts.map +1 -0
- package/dist/auth/baseFields/apiKey/omitAPIKey.js +8 -0
- package/dist/auth/baseFields/apiKey/omitAPIKey.js.map +1 -0
- package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.d.ts +4 -0
- package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.d.ts.map +1 -0
- package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.js +5 -0
- package/dist/auth/baseFields/apiKey/omitAPIKeyIndex.js.map +1 -0
- package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.d.ts +4 -0
- package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.d.ts.map +1 -0
- package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.js +5 -0
- package/dist/auth/baseFields/apiKey/omitEncryptedAPIKey.js.map +1 -0
- package/dist/auth/baseFields/apiKey/setAPIKeyIndex.d.ts +4 -0
- package/dist/auth/baseFields/apiKey/setAPIKeyIndex.d.ts.map +1 -0
- package/dist/auth/baseFields/apiKey/setAPIKeyIndex.js +17 -0
- package/dist/auth/baseFields/apiKey/setAPIKeyIndex.js.map +1 -0
- package/dist/auth/baseFields/auth.d.ts +1 -0
- package/dist/auth/baseFields/auth.d.ts.map +1 -1
- package/dist/auth/baseFields/auth.js +9 -0
- package/dist/auth/baseFields/auth.js.map +1 -1
- package/dist/auth/defaultUnlockAccess.d.ts +3 -0
- package/dist/auth/defaultUnlockAccess.d.ts.map +1 -0
- package/dist/auth/defaultUnlockAccess.js +8 -0
- package/dist/auth/defaultUnlockAccess.js.map +1 -0
- package/dist/auth/endpoints/index.d.ts +1 -0
- package/dist/auth/endpoints/index.d.ts.map +1 -1
- package/dist/auth/endpoints/index.js +8 -0
- package/dist/auth/endpoints/index.js.map +1 -1
- package/dist/auth/endpoints/revealAPIKey.d.ts +7 -0
- package/dist/auth/endpoints/revealAPIKey.d.ts.map +1 -0
- package/dist/auth/endpoints/revealAPIKey.js +120 -0
- package/dist/auth/endpoints/revealAPIKey.js.map +1 -0
- package/dist/auth/executeAccess.d.ts +3 -1
- package/dist/auth/executeAccess.d.ts.map +1 -1
- package/dist/auth/executeAccess.js +2 -1
- package/dist/auth/executeAccess.js.map +1 -1
- package/dist/auth/getAuthFields.d.ts +1 -1
- package/dist/auth/getAuthFields.d.ts.map +1 -1
- package/dist/auth/getAuthFields.js +7 -4
- package/dist/auth/getAuthFields.js.map +1 -1
- package/dist/auth/getFieldsToSign.d.ts.map +1 -1
- package/dist/auth/getFieldsToSign.js +17 -10
- package/dist/auth/getFieldsToSign.js.map +1 -1
- package/dist/auth/getFieldsToSign.spec.js +114 -0
- package/dist/auth/getFieldsToSign.spec.js.map +1 -0
- package/dist/auth/jwt.d.ts.map +1 -1
- package/dist/auth/jwt.js +2 -0
- package/dist/auth/jwt.js.map +1 -1
- package/dist/auth/jwt.spec.js +24 -0
- package/dist/auth/jwt.spec.js.map +1 -0
- package/dist/auth/jwtAuth.d.ts +9 -0
- package/dist/auth/jwtAuth.d.ts.map +1 -0
- package/dist/auth/jwtAuth.js +8 -0
- package/dist/auth/jwtAuth.js.map +1 -0
- package/dist/auth/operations/auth.d.ts.map +1 -1
- package/dist/auth/operations/auth.js +2 -1
- package/dist/auth/operations/auth.js.map +1 -1
- package/dist/auth/operations/forgotPassword.d.ts.map +1 -1
- package/dist/auth/operations/forgotPassword.js +95 -7
- package/dist/auth/operations/forgotPassword.js.map +1 -1
- package/dist/auth/operations/local/auth.js +3 -1
- package/dist/auth/operations/local/auth.js.map +1 -1
- package/dist/auth/operations/login.d.ts.map +1 -1
- package/dist/auth/operations/login.js +48 -26
- package/dist/auth/operations/login.js.map +1 -1
- package/dist/auth/operations/refresh.d.ts.map +1 -1
- package/dist/auth/operations/refresh.js +32 -9
- package/dist/auth/operations/refresh.js.map +1 -1
- package/dist/auth/operations/registerFirstUser.d.ts.map +1 -1
- package/dist/auth/operations/registerFirstUser.js +3 -4
- package/dist/auth/operations/registerFirstUser.js.map +1 -1
- package/dist/auth/operations/resetPassword.d.ts.map +1 -1
- package/dist/auth/operations/resetPassword.js +31 -22
- package/dist/auth/operations/resetPassword.js.map +1 -1
- package/dist/auth/operations/unlock.d.ts.map +1 -1
- package/dist/auth/operations/unlock.js +1 -0
- package/dist/auth/operations/unlock.js.map +1 -1
- package/dist/auth/strategies/apiKey.d.ts.map +1 -1
- package/dist/auth/strategies/apiKey.js +15 -1
- package/dist/auth/strategies/apiKey.js.map +1 -1
- package/dist/auth/strategies/jwt.d.ts.map +1 -1
- package/dist/auth/strategies/jwt.js +61 -10
- package/dist/auth/strategies/jwt.js.map +1 -1
- package/dist/auth/strategies/jwt.spec.js +281 -0
- package/dist/auth/strategies/jwt.spec.js.map +1 -0
- package/dist/auth/strategies/local/authenticate.d.ts +5 -1
- package/dist/auth/strategies/local/authenticate.d.ts.map +1 -1
- package/dist/auth/strategies/local/authenticate.js +8 -3
- package/dist/auth/strategies/local/authenticate.js.map +1 -1
- package/dist/auth/strategies/local/authenticate.spec.js +37 -10
- package/dist/auth/strategies/local/authenticate.spec.js.map +1 -1
- package/dist/auth/strategies/local/generatePasswordSaltHash.d.ts +9 -1
- package/dist/auth/strategies/local/generatePasswordSaltHash.d.ts.map +1 -1
- package/dist/auth/strategies/local/generatePasswordSaltHash.js +61 -34
- package/dist/auth/strategies/local/generatePasswordSaltHash.js.map +1 -1
- package/dist/auth/types.d.ts +16 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/types.js.map +1 -1
- package/dist/collections/config/client.d.ts +1 -0
- package/dist/collections/config/client.d.ts.map +1 -1
- package/dist/collections/config/client.js +3 -0
- package/dist/collections/config/client.js.map +1 -1
- package/dist/collections/config/defaults.d.ts.map +1 -1
- package/dist/collections/config/defaults.js +4 -2
- package/dist/collections/config/defaults.js.map +1 -1
- package/dist/collections/config/sanitize.d.ts.map +1 -1
- package/dist/collections/config/sanitize.js +17 -6
- package/dist/collections/config/sanitize.js.map +1 -1
- package/dist/collections/endpoints/index.d.ts +1 -0
- package/dist/collections/endpoints/index.d.ts.map +1 -1
- package/dist/collections/endpoints/index.js +6 -5
- package/dist/collections/endpoints/index.js.map +1 -1
- package/dist/collections/operations/create.d.ts.map +1 -1
- package/dist/collections/operations/create.js +105 -8
- package/dist/collections/operations/create.js.map +1 -1
- package/dist/collections/operations/deleteByID.js +13 -13
- package/dist/collections/operations/deleteByID.js.map +1 -1
- package/dist/collections/operations/findDistinct.d.ts.map +1 -1
- package/dist/collections/operations/findDistinct.js +96 -18
- package/dist/collections/operations/findDistinct.js.map +1 -1
- package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
- package/dist/collections/operations/restoreVersion.js +47 -13
- package/dist/collections/operations/restoreVersion.js.map +1 -1
- package/dist/collections/operations/update.d.ts.map +1 -1
- package/dist/collections/operations/update.js +123 -23
- package/dist/collections/operations/update.js.map +1 -1
- package/dist/collections/operations/updateByID.d.ts.map +1 -1
- package/dist/collections/operations/updateByID.js +62 -2
- package/dist/collections/operations/updateByID.js.map +1 -1
- package/dist/collections/operations/utilities/update.d.ts.map +1 -1
- package/dist/collections/operations/utilities/update.js +71 -15
- package/dist/collections/operations/utilities/update.js.map +1 -1
- package/dist/config/orderable/index.d.ts.map +1 -1
- package/dist/config/orderable/index.js +67 -14
- package/dist/config/orderable/index.js.map +1 -1
- package/dist/config/sanitize.d.ts.map +1 -1
- package/dist/config/sanitize.js +1 -1
- package/dist/config/sanitize.js.map +1 -1
- package/dist/config/types.d.ts +13 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/database/getLocalizedPaths.d.ts +2 -1
- package/dist/database/getLocalizedPaths.d.ts.map +1 -1
- package/dist/database/getLocalizedPaths.js +12 -3
- package/dist/database/getLocalizedPaths.js.map +1 -1
- package/dist/database/isNestedRelationshipQuery.d.ts +9 -0
- package/dist/database/isNestedRelationshipQuery.d.ts.map +1 -0
- package/dist/database/isNestedRelationshipQuery.js +14 -0
- package/dist/database/isNestedRelationshipQuery.js.map +1 -0
- package/dist/database/prefixWherePaths.d.ts +6 -0
- package/dist/database/prefixWherePaths.d.ts.map +1 -0
- package/dist/database/prefixWherePaths.js +19 -0
- package/dist/database/prefixWherePaths.js.map +1 -0
- package/dist/database/prefixWherePaths.spec.js +46 -0
- package/dist/database/prefixWherePaths.spec.js.map +1 -0
- package/dist/database/queryValidation/validateQueryPaths.d.ts +2 -1
- package/dist/database/queryValidation/validateQueryPaths.d.ts.map +1 -1
- package/dist/database/queryValidation/validateQueryPaths.js +4 -1
- package/dist/database/queryValidation/validateQueryPaths.js.map +1 -1
- package/dist/database/queryValidation/validateSearchParams.d.ts +2 -1
- package/dist/database/queryValidation/validateSearchParams.d.ts.map +1 -1
- package/dist/database/queryValidation/validateSearchParams.js +82 -4
- package/dist/database/queryValidation/validateSearchParams.js.map +1 -1
- package/dist/database/types.d.ts +5 -0
- package/dist/database/types.d.ts.map +1 -1
- package/dist/database/types.js.map +1 -1
- package/dist/email/normalizeSendEmailOptions.js.map +1 -1
- package/dist/email/types.d.ts +4 -1
- package/dist/email/types.d.ts.map +1 -1
- package/dist/email/types.js.map +1 -1
- package/dist/exports/internal.d.ts +7 -0
- package/dist/exports/internal.d.ts.map +1 -1
- package/dist/exports/internal.js +7 -1
- package/dist/exports/internal.js.map +1 -1
- package/dist/exports/shared.d.ts +3 -0
- package/dist/exports/shared.d.ts.map +1 -1
- package/dist/exports/shared.js +3 -0
- package/dist/exports/shared.js.map +1 -1
- package/dist/fields/config/types.d.ts +7 -5
- package/dist/fields/config/types.d.ts.map +1 -1
- package/dist/fields/config/types.js.map +1 -1
- package/dist/fields/hooks/beforeChange/index.d.ts +7 -1
- package/dist/fields/hooks/beforeChange/index.d.ts.map +1 -1
- package/dist/fields/hooks/beforeChange/index.js +4 -2
- package/dist/fields/hooks/beforeChange/index.js.map +1 -1
- package/dist/fields/hooks/beforeChange/index.spec.js +206 -0
- package/dist/fields/hooks/beforeChange/index.spec.js.map +1 -0
- package/dist/fields/hooks/beforeChange/promise.d.ts +2 -1
- package/dist/fields/hooks/beforeChange/promise.d.ts.map +1 -1
- package/dist/fields/hooks/beforeChange/promise.js +51 -9
- package/dist/fields/hooks/beforeChange/promise.js.map +1 -1
- package/dist/fields/hooks/beforeChange/traverseFields.d.ts +2 -1
- package/dist/fields/hooks/beforeChange/traverseFields.d.ts.map +1 -1
- package/dist/fields/hooks/beforeChange/traverseFields.js +3 -2
- package/dist/fields/hooks/beforeChange/traverseFields.js.map +1 -1
- package/dist/fields/hooks/beforeDuplicate/promise.d.ts.map +1 -1
- package/dist/fields/hooks/beforeDuplicate/promise.js +4 -0
- package/dist/fields/hooks/beforeDuplicate/promise.js.map +1 -1
- package/dist/fields/hooks/beforeValidate/getFallbackValue.d.ts +2 -1
- package/dist/fields/hooks/beforeValidate/getFallbackValue.d.ts.map +1 -1
- package/dist/fields/hooks/beforeValidate/getFallbackValue.js +2 -2
- package/dist/fields/hooks/beforeValidate/getFallbackValue.js.map +1 -1
- package/dist/fields/hooks/beforeValidate/index.d.ts +6 -1
- package/dist/fields/hooks/beforeValidate/index.d.ts.map +1 -1
- package/dist/fields/hooks/beforeValidate/index.js +3 -1
- package/dist/fields/hooks/beforeValidate/index.js.map +1 -1
- package/dist/fields/hooks/beforeValidate/index.spec.js +90 -0
- package/dist/fields/hooks/beforeValidate/index.spec.js.map +1 -0
- package/dist/fields/hooks/beforeValidate/promise.d.ts +6 -1
- package/dist/fields/hooks/beforeValidate/promise.d.ts.map +1 -1
- package/dist/fields/hooks/beforeValidate/promise.js +23 -8
- package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
- package/dist/fields/hooks/beforeValidate/traverseFields.d.ts +6 -1
- package/dist/fields/hooks/beforeValidate/traverseFields.d.ts.map +1 -1
- package/dist/fields/hooks/beforeValidate/traverseFields.js +3 -1
- package/dist/fields/hooks/beforeValidate/traverseFields.js.map +1 -1
- package/dist/fields/validations.d.ts.map +1 -1
- package/dist/fields/validations.js +3 -1
- package/dist/fields/validations.js.map +1 -1
- package/dist/globals/operations/restoreVersion.d.ts.map +1 -1
- package/dist/globals/operations/restoreVersion.js +45 -11
- package/dist/globals/operations/restoreVersion.js.map +1 -1
- package/dist/globals/operations/update.d.ts.map +1 -1
- package/dist/globals/operations/update.js +95 -16
- package/dist/globals/operations/update.js.map +1 -1
- package/dist/index.bundled.d.ts +146 -48
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/preferences/config.d.ts.map +1 -1
- package/dist/preferences/config.js +2 -1
- package/dist/preferences/config.js.map +1 -1
- package/dist/query-presets/access.d.ts.map +1 -1
- package/dist/query-presets/access.js +2 -1
- package/dist/query-presets/access.js.map +1 -1
- package/dist/queues/config/collection.d.ts.map +1 -1
- package/dist/queues/config/collection.js +6 -0
- package/dist/queues/config/collection.js.map +1 -1
- package/dist/queues/config/types/index.d.ts +4 -1
- package/dist/queues/config/types/index.d.ts.map +1 -1
- package/dist/queues/config/types/index.js.map +1 -1
- package/dist/queues/endpoints/handleSchedules.d.ts.map +1 -1
- package/dist/queues/endpoints/handleSchedules.js +2 -1
- package/dist/queues/endpoints/handleSchedules.js.map +1 -1
- package/dist/queues/endpoints/run.d.ts.map +1 -1
- package/dist/queues/endpoints/run.js +2 -1
- package/dist/queues/endpoints/run.js.map +1 -1
- package/dist/uploads/assertClientUploadAccess.d.ts +7 -0
- package/dist/uploads/assertClientUploadAccess.d.ts.map +1 -0
- package/dist/uploads/assertClientUploadAccess.js +27 -0
- package/dist/uploads/assertClientUploadAccess.js.map +1 -0
- package/dist/uploads/assertClientUploadAllowed.d.ts +11 -0
- package/dist/uploads/assertClientUploadAllowed.d.ts.map +1 -0
- package/dist/uploads/assertClientUploadAllowed.js +46 -0
- package/dist/uploads/assertClientUploadAllowed.js.map +1 -0
- package/dist/uploads/assertClientUploadAllowed.spec.js +91 -0
- package/dist/uploads/assertClientUploadAllowed.spec.js.map +1 -0
- package/dist/uploads/checkFileRestrictions.d.ts +4 -1
- package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
- package/dist/uploads/checkFileRestrictions.js +66 -26
- package/dist/uploads/checkFileRestrictions.js.map +1 -1
- package/dist/uploads/clientUploadReceipt.d.ts +23 -0
- package/dist/uploads/clientUploadReceipt.d.ts.map +1 -0
- package/dist/uploads/clientUploadReceipt.js +55 -0
- package/dist/uploads/clientUploadReceipt.js.map +1 -0
- package/dist/uploads/deleteAssociatedFiles.d.ts.map +1 -1
- package/dist/uploads/deleteAssociatedFiles.js +33 -8
- package/dist/uploads/deleteAssociatedFiles.js.map +1 -1
- package/dist/uploads/deleteAssociatedFiles.spec.js +124 -0
- package/dist/uploads/deleteAssociatedFiles.spec.js.map +1 -0
- package/dist/uploads/detectSvgFromXml.d.ts +1 -3
- package/dist/uploads/detectSvgFromXml.d.ts.map +1 -1
- package/dist/uploads/detectSvgFromXml.js +3 -40
- package/dist/uploads/detectSvgFromXml.js.map +1 -1
- package/dist/uploads/endpoints/getFile.d.ts.map +1 -1
- package/dist/uploads/endpoints/getFile.js +5 -3
- package/dist/uploads/endpoints/getFile.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/handlers.d.ts +2 -2
- package/dist/uploads/fetchAPI-multipart/handlers.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/handlers.js +18 -5
- package/dist/uploads/fetchAPI-multipart/handlers.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/index.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/index.js +24 -2
- package/dist/uploads/fetchAPI-multipart/index.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts +0 -6
- package/dist/uploads/fetchAPI-multipart/processMultipart.d.ts.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.js +146 -126
- package/dist/uploads/fetchAPI-multipart/processMultipart.js.map +1 -1
- package/dist/uploads/fetchAPI-multipart/processMultipart.spec.js +663 -0
- package/dist/uploads/fetchAPI-multipart/processMultipart.spec.js.map +1 -0
- package/dist/uploads/generateFileData.d.ts +3 -1
- package/dist/uploads/generateFileData.d.ts.map +1 -1
- package/dist/uploads/generateFileData.js +29 -16
- package/dist/uploads/generateFileData.js.map +1 -1
- package/dist/uploads/getBaseFields.d.ts.map +1 -1
- package/dist/uploads/getBaseFields.js +3 -1
- package/dist/uploads/getBaseFields.js.map +1 -1
- package/dist/uploads/getExternalFile.d.ts +1 -1
- package/dist/uploads/getExternalFile.d.ts.map +1 -1
- package/dist/uploads/getExternalFile.js +60 -15
- package/dist/uploads/getExternalFile.js.map +1 -1
- package/dist/uploads/getFileFromClientUpload.d.ts +2 -2
- package/dist/uploads/getFileFromClientUpload.d.ts.map +1 -1
- package/dist/uploads/getFileFromClientUpload.js +4 -4
- package/dist/uploads/getFileFromClientUpload.js.map +1 -1
- package/dist/uploads/getFileFromClientUpload.spec.js +62 -0
- package/dist/uploads/getFileFromClientUpload.spec.js.map +1 -1
- package/dist/uploads/getFileTypeFallback.d.ts.map +1 -1
- package/dist/uploads/getFileTypeFallback.js +3 -1
- package/dist/uploads/getFileTypeFallback.js.map +1 -1
- package/dist/uploads/getFileTypeIdentity.d.ts +19 -0
- package/dist/uploads/getFileTypeIdentity.d.ts.map +1 -0
- package/dist/uploads/getFileTypeIdentity.js +34 -0
- package/dist/uploads/getFileTypeIdentity.js.map +1 -0
- package/dist/uploads/getFileTypeIdentity.spec.js +43 -0
- package/dist/uploads/getFileTypeIdentity.spec.js.map +1 -0
- package/dist/uploads/isProcessableImage.d.ts +2 -0
- package/dist/uploads/isProcessableImage.d.ts.map +1 -0
- package/dist/uploads/isProcessableImage.js +7 -0
- package/dist/uploads/isProcessableImage.js.map +1 -0
- package/dist/uploads/safeFetch.d.ts.map +1 -1
- package/dist/uploads/safeFetch.js +3 -2
- package/dist/uploads/safeFetch.js.map +1 -1
- package/dist/uploads/sanitizeUploadData.d.ts +26 -0
- package/dist/uploads/sanitizeUploadData.d.ts.map +1 -0
- package/dist/uploads/sanitizeUploadData.js +159 -0
- package/dist/uploads/sanitizeUploadData.js.map +1 -0
- package/dist/uploads/sanitizeUploadData.spec.js +255 -0
- package/dist/uploads/sanitizeUploadData.spec.js.map +1 -0
- package/dist/uploads/types.d.ts +11 -3
- package/dist/uploads/types.d.ts.map +1 -1
- package/dist/uploads/types.js.map +1 -1
- package/dist/uploads/unlinkClientUploadTempFile.d.ts +20 -0
- package/dist/uploads/unlinkClientUploadTempFile.d.ts.map +1 -0
- package/dist/uploads/unlinkClientUploadTempFile.js +30 -0
- package/dist/uploads/unlinkClientUploadTempFile.js.map +1 -0
- package/dist/uploads/unlinkTempFiles.d.ts.map +1 -1
- package/dist/uploads/unlinkTempFiles.js +7 -9
- package/dist/uploads/unlinkTempFiles.js.map +1 -1
- package/dist/uploads/unlinkTempFiles.spec.js +61 -1
- package/dist/uploads/unlinkTempFiles.spec.js.map +1 -1
- package/dist/uploads/uploadContentSecurityPolicy.d.ts +2 -0
- package/dist/uploads/uploadContentSecurityPolicy.d.ts.map +1 -0
- package/dist/uploads/uploadContentSecurityPolicy.js +3 -0
- package/dist/uploads/uploadContentSecurityPolicy.js.map +1 -0
- package/dist/uploads/validateISOBaseMediaFile.d.ts +4 -0
- package/dist/uploads/validateISOBaseMediaFile.d.ts.map +1 -0
- package/dist/uploads/validateISOBaseMediaFile.js +91 -0
- package/dist/uploads/validateISOBaseMediaFile.js.map +1 -0
- package/dist/uploads/validateISOBaseMediaFile.spec.js +130 -0
- package/dist/uploads/validateISOBaseMediaFile.spec.js.map +1 -0
- package/dist/uploads/validateSvg.d.ts +10 -4
- package/dist/uploads/validateSvg.d.ts.map +1 -1
- package/dist/uploads/validateSvg.js +280 -40
- package/dist/uploads/validateSvg.js.map +1 -1
- package/dist/uploads/validateSvg.spec.js +123 -0
- package/dist/uploads/validateSvg.spec.js.map +1 -0
- package/dist/uploads/validateUploadFilename.d.ts +3 -0
- package/dist/uploads/validateUploadFilename.d.ts.map +1 -0
- package/dist/uploads/validateUploadFilename.js +13 -0
- package/dist/uploads/validateUploadFilename.js.map +1 -0
- package/dist/uploads/validateUploadFilename.spec.js +24 -0
- package/dist/uploads/validateUploadFilename.spec.js.map +1 -0
- package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.js +28 -1
- package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.spec.js +158 -0
- package/dist/utilities/addDataAndFileToRequest.spec.js.map +1 -1
- package/dist/utilities/createPayloadRequest.d.ts.map +1 -1
- package/dist/utilities/createPayloadRequest.js +2 -1
- package/dist/utilities/createPayloadRequest.js.map +1 -1
- package/dist/utilities/deepCopyObject.d.ts.map +1 -1
- package/dist/utilities/deepCopyObject.js +110 -19
- package/dist/utilities/deepCopyObject.js.map +1 -1
- package/dist/utilities/deepCopyObject.spec.js +216 -0
- package/dist/utilities/deepCopyObject.spec.js.map +1 -0
- package/dist/utilities/fieldPath.d.ts +13 -0
- package/dist/utilities/fieldPath.d.ts.map +1 -0
- package/dist/utilities/fieldPath.js +51 -0
- package/dist/utilities/fieldPath.js.map +1 -0
- package/dist/utilities/fieldPath.spec.js +155 -0
- package/dist/utilities/fieldPath.spec.js.map +1 -0
- package/dist/utilities/getEntityPermissions/getEntityPermissions.d.ts.map +1 -1
- package/dist/utilities/getEntityPermissions/getEntityPermissions.js +2 -0
- package/dist/utilities/getEntityPermissions/getEntityPermissions.js.map +1 -1
- package/dist/utilities/getObjectDotNotation.d.ts.map +1 -1
- package/dist/utilities/getObjectDotNotation.js +7 -1
- package/dist/utilities/getObjectDotNotation.js.map +1 -1
- package/dist/utilities/getObjectDotNotation.spec.js +33 -0
- package/dist/utilities/getObjectDotNotation.spec.js.map +1 -0
- package/dist/utilities/getSafeRedirect.spec.js +14 -0
- package/dist/utilities/getSafeRedirect.spec.js.map +1 -1
- package/dist/utilities/getTopLevelFieldNames.d.ts +2 -0
- package/dist/utilities/getTopLevelFieldNames.d.ts.map +1 -0
- package/dist/utilities/getTopLevelFieldNames.js +3 -0
- package/dist/utilities/getTopLevelFieldNames.js.map +1 -0
- package/dist/utilities/getTopLevelFieldNames.spec.js +18 -0
- package/dist/utilities/getTopLevelFieldNames.spec.js.map +1 -0
- package/dist/utilities/handleEndpoints.js +1 -1
- package/dist/utilities/handleEndpoints.js.map +1 -1
- package/dist/utilities/parseParams/index.d.ts.map +1 -1
- package/dist/utilities/parseParams/index.js +3 -1
- package/dist/utilities/parseParams/index.js.map +1 -1
- package/dist/utilities/parseParams/index.spec.js +8 -0
- package/dist/utilities/parseParams/index.spec.js.map +1 -1
- package/dist/utilities/traverseFields.d.ts.map +1 -1
- package/dist/utilities/traverseFields.js +5 -14
- package/dist/utilities/traverseFields.js.map +1 -1
- package/dist/utilities/unflatten.d.ts.map +1 -1
- package/dist/utilities/unflatten.js +21 -9
- package/dist/utilities/unflatten.js.map +1 -1
- package/dist/utilities/unflatten.spec.js +38 -0
- package/dist/utilities/unflatten.spec.js.map +1 -0
- package/dist/utilities/wrapInternalEndpoints.d.ts.map +1 -1
- package/dist/utilities/wrapInternalEndpoints.js +10 -3
- package/dist/utilities/wrapInternalEndpoints.js.map +1 -1
- package/dist/utilities/wrapInternalEndpoints.spec.js +124 -0
- package/dist/utilities/wrapInternalEndpoints.spec.js.map +1 -0
- package/dist/versions/allLocalesPublicationStatus.d.ts +38 -0
- package/dist/versions/allLocalesPublicationStatus.d.ts.map +1 -0
- package/dist/versions/allLocalesPublicationStatus.js +57 -0
- package/dist/versions/allLocalesPublicationStatus.js.map +1 -0
- package/dist/versions/getLatestGlobalVersion.d.ts.map +1 -1
- package/dist/versions/getLatestGlobalVersion.js +10 -2
- package/dist/versions/getLatestGlobalVersion.js.map +1 -1
- package/dist/versions/getRestoredStatusesToAuthorize.d.ts +9 -0
- package/dist/versions/getRestoredStatusesToAuthorize.d.ts.map +1 -0
- package/dist/versions/getRestoredStatusesToAuthorize.js +22 -0
- package/dist/versions/getRestoredStatusesToAuthorize.js.map +1 -0
- package/dist/versions/getRestoredStatusesToAuthorize.spec.js +50 -0
- package/dist/versions/getRestoredStatusesToAuthorize.spec.js.map +1 -0
- package/dist/versions/schedule/job.d.ts +2 -2
- package/dist/versions/schedule/job.d.ts.map +1 -1
- package/dist/versions/schedule/job.js +11 -7
- package/dist/versions/schedule/job.js.map +1 -1
- package/dist/versions/schedule/types.d.ts +5 -1
- package/dist/versions/schedule/types.d.ts.map +1 -1
- package/dist/versions/schedule/types.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getSanitizedUploadFilename, isXmlMimeType } from './getFileTypeIdentity.js';
|
|
3
|
+
describe('getSanitizedUploadFilename', ()=>{
|
|
4
|
+
it('should use the output extension while preserving the sanitized source basename', ()=>{
|
|
5
|
+
expect(getSanitizedUploadFilename('incoming/image.jpg', 'png')).toBe('image.png');
|
|
6
|
+
});
|
|
7
|
+
});
|
|
8
|
+
describe('isXmlMimeType', ()=>{
|
|
9
|
+
it.each([
|
|
10
|
+
[
|
|
11
|
+
'application/xml',
|
|
12
|
+
true
|
|
13
|
+
],
|
|
14
|
+
[
|
|
15
|
+
'text/xml',
|
|
16
|
+
true
|
|
17
|
+
],
|
|
18
|
+
[
|
|
19
|
+
'application/atom+xml',
|
|
20
|
+
true
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
'image/svg+xml',
|
|
24
|
+
true
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
'APPLICATION/XML',
|
|
28
|
+
true
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
' Application/Atom+Xml; Charset=UTF-8 ',
|
|
32
|
+
true
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
'text/plain',
|
|
36
|
+
false
|
|
37
|
+
]
|
|
38
|
+
])('should classify %s as %s', (mimeType, expected)=>{
|
|
39
|
+
expect(isXmlMimeType(mimeType)).toBe(expected);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=getFileTypeIdentity.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/getFileTypeIdentity.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { getSanitizedUploadFilename, isXmlMimeType } from './getFileTypeIdentity.js'\n\ndescribe('getSanitizedUploadFilename', () => {\n it('should use the output extension while preserving the sanitized source basename', () => {\n expect(getSanitizedUploadFilename('incoming/image.jpg', 'png')).toBe('image.png')\n })\n})\n\ndescribe('isXmlMimeType', () => {\n it.each([\n ['application/xml', true],\n ['text/xml', true],\n ['application/atom+xml', true],\n ['image/svg+xml', true],\n ['APPLICATION/XML', true],\n [' Application/Atom+Xml; Charset=UTF-8 ', true],\n ['text/plain', false],\n ])('should classify %s as %s', (mimeType, expected) => {\n expect(isXmlMimeType(mimeType)).toBe(expected)\n })\n})\n"],"names":["describe","expect","it","getSanitizedUploadFilename","isXmlMimeType","toBe","each","mimeType","expected"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,0BAA0B,EAAEC,aAAa,QAAQ,2BAA0B;AAEpFJ,SAAS,8BAA8B;IACrCE,GAAG,kFAAkF;QACnFD,OAAOE,2BAA2B,sBAAsB,QAAQE,IAAI,CAAC;IACvE;AACF;AAEAL,SAAS,iBAAiB;IACxBE,GAAGI,IAAI,CAAC;QACN;YAAC;YAAmB;SAAK;QACzB;YAAC;YAAY;SAAK;QAClB;YAAC;YAAwB;SAAK;QAC9B;YAAC;YAAiB;SAAK;QACvB;YAAC;YAAmB;SAAK;QACzB;YAAC;YAAyC;SAAK;QAC/C;YAAC;YAAc;SAAM;KACtB,EAAE,4BAA4B,CAACC,UAAUC;QACxCP,OAAOG,cAAcG,WAAWF,IAAI,CAACG;IACvC;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isProcessableImage.d.ts","sourceRoot":"","sources":["../../src/uploads/isProcessableImage.ts"],"names":[],"mappings":"AAGA,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/isProcessableImage.ts"],"sourcesContent":["import { canResizeImage } from './canResizeImage.js'\nimport { isImage } from './isImage.js'\n\nexport function isProcessableImage(mimeType: string): boolean {\n return isImage(mimeType) || canResizeImage(mimeType)\n}\n"],"names":["canResizeImage","isImage","isProcessableImage","mimeType"],"mappings":"AAAA,SAASA,cAAc,QAAQ,sBAAqB;AACpD,SAASC,OAAO,QAAQ,eAAc;AAEtC,OAAO,SAASC,mBAAmBC,QAAgB;IACjD,OAAOF,QAAQE,aAAaH,eAAeG;AAC7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safeFetch.d.ts","sourceRoot":"","sources":["../../src/uploads/safeFetch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAE5B,OAAO,EAAS,KAAK,IAAI,WAAW,EAAE,MAAM,QAAQ,CAAA;AAEpD;;GAEG;AACH,eAAO,MAAM,yBAAyB;;CAErC,CAAA;
|
|
1
|
+
{"version":3,"file":"safeFetch.d.ts","sourceRoot":"","sources":["../../src/uploads/safeFetch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAA;AAE5B,OAAO,EAAS,KAAK,IAAI,WAAW,EAAE,MAAM,QAAQ,CAAA;AAEpD;;GAEG;AACH,eAAO,MAAM,yBAAyB;;CAErC,CAAA;AAuDD;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,4FAAoD,OAAO,CAAC,QAAQ,CA4CzF,CAAA"}
|
|
@@ -6,6 +6,7 @@ import { Agent, fetch as undiciFetch } from 'undici';
|
|
|
6
6
|
*/ export const _internal_safeFetchGlobal = {
|
|
7
7
|
lookup
|
|
8
8
|
};
|
|
9
|
+
const buildBlockedFetchError = (hostname)=>new Error(`Blocked unsafe attempt to ${hostname}. This host resolves to a private or internal address. ` + `If this is a trusted destination, allowlist it via the upload collection's "skipSafeFetch" option ` + `(https://payloadcms.com/docs/upload/overview#skip-safe-fetch).`);
|
|
9
10
|
const isSafeIp = (ip)=>{
|
|
10
11
|
try {
|
|
11
12
|
if (!ip) {
|
|
@@ -39,7 +40,7 @@ const ssrfFilterInterceptor = (hostname, options, callback)=>{
|
|
|
39
40
|
];
|
|
40
41
|
}
|
|
41
42
|
if (ips.some((ip)=>!isSafeIp(ip))) {
|
|
42
|
-
callback(
|
|
43
|
+
callback(buildBlockedFetchError(hostname), address, family);
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
callback(null, address, family);
|
|
@@ -68,7 +69,7 @@ const safeDispatcher = new Agent({
|
|
|
68
69
|
}
|
|
69
70
|
if (ipaddr.isValid(hostname)) {
|
|
70
71
|
if (!isSafeIp(hostname)) {
|
|
71
|
-
throw
|
|
72
|
+
throw buildBlockedFetchError(hostname);
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
return await undiciFetch(url, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/uploads/safeFetch.ts"],"sourcesContent":["import type { LookupFunction } from 'net'\n\nimport { lookup } from 'dns'\nimport ipaddr from 'ipaddr.js'\nimport { Agent, fetch as undiciFetch } from 'undici'\n\n/**\n * @internal this is used to mock the IP `lookup` function in integration tests\n */\nexport const _internal_safeFetchGlobal = {\n lookup,\n}\n\nconst isSafeIp = (ip: string) => {\n try {\n if (!ip) {\n return false\n }\n\n if (!ipaddr.isValid(ip)) {\n return false\n }\n\n const parsedIpAddress = ipaddr.parse(ip)\n const range = parsedIpAddress.range()\n if (range !== 'unicast') {\n return false // Private IP Range\n }\n } catch (ignore) {\n return false\n }\n return true\n}\n\nconst ssrfFilterInterceptor: LookupFunction = (hostname, options, callback) => {\n _internal_safeFetchGlobal.lookup(hostname, options, (err, address, family) => {\n if (err) {\n callback(err, address, family)\n } else {\n let ips = [] as string[]\n if (Array.isArray(address)) {\n ips = address.map((a) => a.address)\n } else {\n ips = [address]\n }\n\n if (ips.some((ip) => !isSafeIp(ip))) {\n callback(
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/safeFetch.ts"],"sourcesContent":["import type { LookupFunction } from 'net'\n\nimport { lookup } from 'dns'\nimport ipaddr from 'ipaddr.js'\nimport { Agent, fetch as undiciFetch } from 'undici'\n\n/**\n * @internal this is used to mock the IP `lookup` function in integration tests\n */\nexport const _internal_safeFetchGlobal = {\n lookup,\n}\n\nconst buildBlockedFetchError = (hostname: string): Error =>\n new Error(\n `Blocked unsafe attempt to ${hostname}. This host resolves to a private or internal address. ` +\n `If this is a trusted destination, allowlist it via the upload collection's \"skipSafeFetch\" option ` +\n `(https://payloadcms.com/docs/upload/overview#skip-safe-fetch).`,\n )\n\nconst isSafeIp = (ip: string) => {\n try {\n if (!ip) {\n return false\n }\n\n if (!ipaddr.isValid(ip)) {\n return false\n }\n\n const parsedIpAddress = ipaddr.parse(ip)\n const range = parsedIpAddress.range()\n if (range !== 'unicast') {\n return false // Private IP Range\n }\n } catch (ignore) {\n return false\n }\n return true\n}\n\nconst ssrfFilterInterceptor: LookupFunction = (hostname, options, callback) => {\n _internal_safeFetchGlobal.lookup(hostname, options, (err, address, family) => {\n if (err) {\n callback(err, address, family)\n } else {\n let ips = [] as string[]\n if (Array.isArray(address)) {\n ips = address.map((a) => a.address)\n } else {\n ips = [address]\n }\n\n if (ips.some((ip) => !isSafeIp(ip))) {\n callback(buildBlockedFetchError(hostname), address, family)\n return\n }\n\n callback(null, address, family)\n }\n })\n}\n\nconst safeDispatcher = new Agent({\n connect: { lookup: ssrfFilterInterceptor },\n})\n/**\n * A \"safe\" version of undici's fetch that prevents SSRF attacks.\n *\n * - Utilizes a custom dispatcher that filters out requests to unsafe IP addresses.\n * - Validates domain names by resolving them to IP addresses and checking if they're safe.\n * - Undici was used because it supported interceptors as well as \"credentials: include\". Native fetch\n */\nexport const safeFetch = async (...args: Parameters<typeof undiciFetch>): Promise<Response> => {\n const [unverifiedUrl, options] = args\n\n try {\n const url = new URL(unverifiedUrl)\n\n let hostname = url.hostname\n\n // Strip brackets from IPv6 addresses (e.g., \"[::1]\" => \"::1\")\n if (hostname.startsWith('[') && hostname.endsWith(']')) {\n hostname = hostname.slice(1, -1)\n }\n\n if (ipaddr.isValid(hostname)) {\n if (!isSafeIp(hostname)) {\n throw buildBlockedFetchError(hostname)\n }\n }\n return (await undiciFetch(url, {\n ...options,\n dispatcher: safeDispatcher,\n redirect: 'manual', // Prevent automatic redirects\n })) as unknown as Response\n } catch (error) {\n if (error instanceof Error) {\n if (error.cause instanceof Error && error.cause.message.includes('unsafe')) {\n // Errors thrown from within interceptors always have 'fetch error' as the message\n // The desired message we want to bubble up is in the cause\n throw new Error(error.cause.message)\n } else {\n let stringifiedUrl: string | undefined = undefined\n if (typeof unverifiedUrl === 'string') {\n stringifiedUrl = unverifiedUrl\n } else if (unverifiedUrl instanceof URL) {\n stringifiedUrl = unverifiedUrl.toString()\n } else if (unverifiedUrl instanceof Request) {\n stringifiedUrl = unverifiedUrl.url\n }\n\n throw new Error(`Failed to fetch from ${stringifiedUrl}, ${error.message}`)\n }\n }\n throw error\n }\n}\n"],"names":["lookup","ipaddr","Agent","fetch","undiciFetch","_internal_safeFetchGlobal","buildBlockedFetchError","hostname","Error","isSafeIp","ip","isValid","parsedIpAddress","parse","range","ignore","ssrfFilterInterceptor","options","callback","err","address","family","ips","Array","isArray","map","a","some","safeDispatcher","connect","safeFetch","args","unverifiedUrl","url","URL","startsWith","endsWith","slice","dispatcher","redirect","error","cause","message","includes","stringifiedUrl","undefined","toString","Request"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FlattenedField } from '../fields/config/types.js';
|
|
2
|
+
type Operation = 'create' | 'update';
|
|
3
|
+
export type ExternalUploadSource = {
|
|
4
|
+
filename: string;
|
|
5
|
+
url: string;
|
|
6
|
+
};
|
|
7
|
+
type UploadDataOptions = {
|
|
8
|
+
locale?: string;
|
|
9
|
+
localizedProperties?: Set<string>;
|
|
10
|
+
};
|
|
11
|
+
export declare const getExternalUploadSource: (data: unknown) => ExternalUploadSource | undefined;
|
|
12
|
+
export declare const getUploadDestination: ({ data, file, }: {
|
|
13
|
+
data: unknown;
|
|
14
|
+
file: {
|
|
15
|
+
clientUploadContext?: unknown;
|
|
16
|
+
} | null | undefined;
|
|
17
|
+
}) => {
|
|
18
|
+
objectKey?: string;
|
|
19
|
+
prefix?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const getLocalizedUploadProperties: (fields: FlattenedField[]) => Set<string>;
|
|
22
|
+
export declare const sanitizeUploadData: <T>(data: T, operation: Operation) => T;
|
|
23
|
+
export declare const mergeUploadDataWithDocument: <T>(data: T, document: unknown, options?: UploadDataOptions) => T;
|
|
24
|
+
export declare const restoreUploadDataFromDocument: <T>(data: T, document: unknown, options?: UploadDataOptions) => T;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=sanitizeUploadData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizeUploadData.d.ts","sourceRoot":"","sources":["../../src/uploads/sanitizeUploadData.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAI/D,KAAK,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEpC,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAClC,CAAA;AAQD,eAAO,MAAM,uBAAuB,SAAU,OAAO,KAAG,oBAAoB,GAAG,SAS9E,CAAA;AAKD,eAAO,MAAM,oBAAoB,oBAG9B;IACD,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE;QAAE,mBAAmB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAA;CAC3D,KAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAoBxC,CAAA;AAcD,eAAO,MAAM,4BAA4B,WAAY,cAAc,EAAE,KAAG,GAAG,CAAC,MAAM,CAUjF,CAAA;AAqBD,eAAO,MAAM,kBAAkB,GAAI,CAAC,QAAQ,CAAC,aAAa,SAAS,KAAG,CA4BrE,CAAA;AAQD,eAAO,MAAM,2BAA2B,GAAI,CAAC,QACrC,CAAC,YACG,OAAO,YACR,iBAAiB,KACzB,CA8BF,CAAA;AAiBD,eAAO,MAAM,6BAA6B,GAAI,CAAC,QACvC,CAAC,YACG,OAAO,YACR,iBAAiB,KACzB,CAeF,CAAA"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { APIError } from '../errors/APIError.js';
|
|
3
|
+
const hasOwnProperty = (value, key)=>Object.prototype.hasOwnProperty.call(value, key);
|
|
4
|
+
const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
5
|
+
export const getExternalUploadSource = (data)=>{
|
|
6
|
+
if (!isRecord(data) || typeof data.filename !== 'string' || typeof data.url !== 'string') {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
filename: data.filename,
|
|
11
|
+
url: data.url
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
// Resolves the server-owned upload destination for a document write. For client uploads the prefix
|
|
15
|
+
// and key segment come from the verified upload context; for server uploads the prefix falls back
|
|
16
|
+
// to the submitted document data and there is no key segment.
|
|
17
|
+
export const getUploadDestination = ({ data, file })=>{
|
|
18
|
+
if (!file) {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
const submittedPrefix = isRecord(data) && typeof data.prefix === 'string' ? data.prefix : undefined;
|
|
22
|
+
const { clientUploadContext } = file;
|
|
23
|
+
if (!isRecord(clientUploadContext)) {
|
|
24
|
+
return {
|
|
25
|
+
prefix: submittedPrefix
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
objectKey: typeof clientUploadContext._objectKey === 'string' ? clientUploadContext._objectKey : undefined,
|
|
30
|
+
prefix: typeof clientUploadContext.prefix === 'string' ? clientUploadContext.prefix : undefined
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const getDocumentProperty = (document, property, { locale, localizedProperties })=>{
|
|
34
|
+
const value = document[property];
|
|
35
|
+
return locale && localizedProperties?.has(property) && isRecord(value) ? value[locale] : value;
|
|
36
|
+
};
|
|
37
|
+
// Accepts flattened fields so localized identity fields declared inside presentational
|
|
38
|
+
// containers (row/collapsible/unnamed tabs) are still detected — those live at the document
|
|
39
|
+
// root data level but are nested in the config tree, so walking `fields` alone would miss them.
|
|
40
|
+
export const getLocalizedUploadProperties = (fields)=>{
|
|
41
|
+
const localizedProperties = new Set();
|
|
42
|
+
for (const field of fields){
|
|
43
|
+
if ('name' in field && field.localized) {
|
|
44
|
+
localizedProperties.add(field.name);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return localizedProperties;
|
|
48
|
+
};
|
|
49
|
+
// The submitted filename is stripped by sanitizeUploadData regardless, so this only exists to
|
|
50
|
+
// reject path-traversal attempts loudly (400) instead of silently dropping them. Non-string
|
|
51
|
+
// values are ignored here because they are removed by the caller anyway.
|
|
52
|
+
const validateFilename = (filename)=>{
|
|
53
|
+
if (typeof filename !== 'string') {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const pathSegments = filename.replace(/\\/g, '/').split('/');
|
|
57
|
+
if (path.posix.isAbsolute(filename) || path.win32.isAbsolute(filename) || pathSegments.includes('..')) {
|
|
58
|
+
throw new APIError('Invalid filename.', 400);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
export const sanitizeUploadData = (data, operation)=>{
|
|
62
|
+
if (!isRecord(data)) {
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
validateFilename(data.filename);
|
|
66
|
+
if (isRecord(data.sizes)) {
|
|
67
|
+
for (const sizeData of Object.values(data.sizes)){
|
|
68
|
+
if (isRecord(sizeData)) {
|
|
69
|
+
validateFilename(sizeData.filename);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const sanitizedData = {
|
|
74
|
+
...data
|
|
75
|
+
};
|
|
76
|
+
delete sanitizedData.filename;
|
|
77
|
+
delete sanitizedData.sizes;
|
|
78
|
+
delete sanitizedData.url;
|
|
79
|
+
// Server-owned; never accepted from the caller.
|
|
80
|
+
delete sanitizedData._objectKey;
|
|
81
|
+
// On update, `prefix` is restored from the stored document (file identity); kept on create.
|
|
82
|
+
if (operation === 'update') {
|
|
83
|
+
delete sanitizedData.prefix;
|
|
84
|
+
}
|
|
85
|
+
return sanitizedData;
|
|
86
|
+
};
|
|
87
|
+
// Restores only the identity fields that select/serve a stored object (`filename`, `prefix`,
|
|
88
|
+
// `url`, `sizes`). Other generated-but-derived fields (`thumbnailURL`, `filesize`, `height`,
|
|
89
|
+
// `width`, `mimeType`, `focalX`/`focalY`) are intentionally left as submitted: `focalX`/`focalY`
|
|
90
|
+
// are user-editable crop input, and the rest are regenerated by generateFileData when a file is
|
|
91
|
+
// written. Compare with restoreUploadDataFromDocument (version restore), which re-binds the full
|
|
92
|
+
// tuple below.
|
|
93
|
+
export const mergeUploadDataWithDocument = (data, document, options = {})=>{
|
|
94
|
+
if (!isRecord(data) || !isRecord(document)) {
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
const mergedData = {
|
|
98
|
+
...data
|
|
99
|
+
};
|
|
100
|
+
for (const property of [
|
|
101
|
+
'_objectKey',
|
|
102
|
+
'filename',
|
|
103
|
+
'prefix',
|
|
104
|
+
'url'
|
|
105
|
+
]){
|
|
106
|
+
if (!hasOwnProperty(data, property) && hasOwnProperty(document, property)) {
|
|
107
|
+
mergedData[property] = getDocumentProperty(document, property, options);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const documentSizes = getDocumentProperty(document, 'sizes', options);
|
|
111
|
+
if (!hasOwnProperty(data, 'sizes') && hasOwnProperty(document, 'sizes')) {
|
|
112
|
+
mergedData.sizes = documentSizes;
|
|
113
|
+
} else if (isRecord(data.sizes) && isRecord(documentSizes)) {
|
|
114
|
+
const mergedSizes = {
|
|
115
|
+
...documentSizes
|
|
116
|
+
};
|
|
117
|
+
for (const [sizeName, sizeData] of Object.entries(data.sizes)){
|
|
118
|
+
const documentSize = documentSizes[sizeName];
|
|
119
|
+
mergedSizes[sizeName] = isRecord(sizeData) && isRecord(documentSize) ? {
|
|
120
|
+
...documentSize,
|
|
121
|
+
...sizeData
|
|
122
|
+
} : sizeData;
|
|
123
|
+
}
|
|
124
|
+
mergedData.sizes = mergedSizes;
|
|
125
|
+
}
|
|
126
|
+
return mergedData;
|
|
127
|
+
};
|
|
128
|
+
const uploadDerivedProperties = [
|
|
129
|
+
'_objectKey',
|
|
130
|
+
'filename',
|
|
131
|
+
'filesize',
|
|
132
|
+
'focalX',
|
|
133
|
+
'focalY',
|
|
134
|
+
'height',
|
|
135
|
+
'mimeType',
|
|
136
|
+
'prefix',
|
|
137
|
+
'sizes',
|
|
138
|
+
'thumbnailURL',
|
|
139
|
+
'url',
|
|
140
|
+
'width'
|
|
141
|
+
];
|
|
142
|
+
export const restoreUploadDataFromDocument = (data, document, options = {})=>{
|
|
143
|
+
if (!isRecord(data) || !isRecord(document)) {
|
|
144
|
+
return data;
|
|
145
|
+
}
|
|
146
|
+
const restoredData = {
|
|
147
|
+
...data
|
|
148
|
+
};
|
|
149
|
+
for (const property of uploadDerivedProperties){
|
|
150
|
+
if (hasOwnProperty(document, property)) {
|
|
151
|
+
restoredData[property] = getDocumentProperty(document, property, options);
|
|
152
|
+
} else {
|
|
153
|
+
delete restoredData[property];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return restoredData;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=sanitizeUploadData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/sanitizeUploadData.ts"],"sourcesContent":["import path from 'path'\n\nimport type { FlattenedField } from '../fields/config/types.js'\n\nimport { APIError } from '../errors/APIError.js'\n\ntype Operation = 'create' | 'update'\n\nexport type ExternalUploadSource = {\n filename: string\n url: string\n}\n\ntype UploadDataOptions = {\n locale?: string\n localizedProperties?: Set<string>\n}\n\nconst hasOwnProperty = (value: Record<string, unknown>, key: string): boolean =>\n Object.prototype.hasOwnProperty.call(value, key)\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nexport const getExternalUploadSource = (data: unknown): ExternalUploadSource | undefined => {\n if (!isRecord(data) || typeof data.filename !== 'string' || typeof data.url !== 'string') {\n return undefined\n }\n\n return {\n filename: data.filename,\n url: data.url,\n }\n}\n\n// Resolves the server-owned upload destination for a document write. For client uploads the prefix\n// and key segment come from the verified upload context; for server uploads the prefix falls back\n// to the submitted document data and there is no key segment.\nexport const getUploadDestination = ({\n data,\n file,\n}: {\n data: unknown\n file: { clientUploadContext?: unknown } | null | undefined\n}): { objectKey?: string; prefix?: string } => {\n if (!file) {\n return {}\n }\n\n const submittedPrefix =\n isRecord(data) && typeof data.prefix === 'string' ? data.prefix : undefined\n const { clientUploadContext } = file\n\n if (!isRecord(clientUploadContext)) {\n return { prefix: submittedPrefix }\n }\n\n return {\n objectKey:\n typeof clientUploadContext._objectKey === 'string'\n ? clientUploadContext._objectKey\n : undefined,\n prefix: typeof clientUploadContext.prefix === 'string' ? clientUploadContext.prefix : undefined,\n }\n}\n\nconst getDocumentProperty = (\n document: Record<string, unknown>,\n property: string,\n { locale, localizedProperties }: UploadDataOptions,\n): unknown => {\n const value = document[property]\n return locale && localizedProperties?.has(property) && isRecord(value) ? value[locale] : value\n}\n\n// Accepts flattened fields so localized identity fields declared inside presentational\n// containers (row/collapsible/unnamed tabs) are still detected — those live at the document\n// root data level but are nested in the config tree, so walking `fields` alone would miss them.\nexport const getLocalizedUploadProperties = (fields: FlattenedField[]): Set<string> => {\n const localizedProperties = new Set<string>()\n\n for (const field of fields) {\n if ('name' in field && (field as { localized?: boolean }).localized) {\n localizedProperties.add(field.name)\n }\n }\n\n return localizedProperties\n}\n\n// The submitted filename is stripped by sanitizeUploadData regardless, so this only exists to\n// reject path-traversal attempts loudly (400) instead of silently dropping them. Non-string\n// values are ignored here because they are removed by the caller anyway.\nconst validateFilename = (filename: unknown): void => {\n if (typeof filename !== 'string') {\n return\n }\n\n const pathSegments = filename.replace(/\\\\/g, '/').split('/')\n\n if (\n path.posix.isAbsolute(filename) ||\n path.win32.isAbsolute(filename) ||\n pathSegments.includes('..')\n ) {\n throw new APIError('Invalid filename.', 400)\n }\n}\n\nexport const sanitizeUploadData = <T>(data: T, operation: Operation): T => {\n if (!isRecord(data)) {\n return data\n }\n\n validateFilename(data.filename)\n\n if (isRecord(data.sizes)) {\n for (const sizeData of Object.values(data.sizes)) {\n if (isRecord(sizeData)) {\n validateFilename(sizeData.filename)\n }\n }\n }\n\n const sanitizedData: Record<string, unknown> = { ...data }\n delete sanitizedData.filename\n delete sanitizedData.sizes\n delete sanitizedData.url\n // Server-owned; never accepted from the caller.\n delete sanitizedData._objectKey\n\n // On update, `prefix` is restored from the stored document (file identity); kept on create.\n if (operation === 'update') {\n delete sanitizedData.prefix\n }\n\n return sanitizedData as T\n}\n\n// Restores only the identity fields that select/serve a stored object (`filename`, `prefix`,\n// `url`, `sizes`). Other generated-but-derived fields (`thumbnailURL`, `filesize`, `height`,\n// `width`, `mimeType`, `focalX`/`focalY`) are intentionally left as submitted: `focalX`/`focalY`\n// are user-editable crop input, and the rest are regenerated by generateFileData when a file is\n// written. Compare with restoreUploadDataFromDocument (version restore), which re-binds the full\n// tuple below.\nexport const mergeUploadDataWithDocument = <T>(\n data: T,\n document: unknown,\n options: UploadDataOptions = {},\n): T => {\n if (!isRecord(data) || !isRecord(document)) {\n return data\n }\n\n const mergedData: Record<string, unknown> = { ...data }\n\n for (const property of ['_objectKey', 'filename', 'prefix', 'url']) {\n if (!hasOwnProperty(data, property) && hasOwnProperty(document, property)) {\n mergedData[property] = getDocumentProperty(document, property, options)\n }\n }\n\n const documentSizes = getDocumentProperty(document, 'sizes', options)\n if (!hasOwnProperty(data, 'sizes') && hasOwnProperty(document, 'sizes')) {\n mergedData.sizes = documentSizes\n } else if (isRecord(data.sizes) && isRecord(documentSizes)) {\n const mergedSizes: Record<string, unknown> = { ...documentSizes }\n\n for (const [sizeName, sizeData] of Object.entries(data.sizes)) {\n const documentSize = documentSizes[sizeName]\n\n mergedSizes[sizeName] =\n isRecord(sizeData) && isRecord(documentSize) ? { ...documentSize, ...sizeData } : sizeData\n }\n\n mergedData.sizes = mergedSizes\n }\n\n return mergedData as T\n}\n\nconst uploadDerivedProperties = [\n '_objectKey',\n 'filename',\n 'filesize',\n 'focalX',\n 'focalY',\n 'height',\n 'mimeType',\n 'prefix',\n 'sizes',\n 'thumbnailURL',\n 'url',\n 'width',\n] as const\n\nexport const restoreUploadDataFromDocument = <T>(\n data: T,\n document: unknown,\n options: UploadDataOptions = {},\n): T => {\n if (!isRecord(data) || !isRecord(document)) {\n return data\n }\n\n const restoredData: Record<string, unknown> = { ...data }\n for (const property of uploadDerivedProperties) {\n if (hasOwnProperty(document, property)) {\n restoredData[property] = getDocumentProperty(document, property, options)\n } else {\n delete restoredData[property]\n }\n }\n\n return restoredData as T\n}\n"],"names":["path","APIError","hasOwnProperty","value","key","Object","prototype","call","isRecord","Array","isArray","getExternalUploadSource","data","filename","url","undefined","getUploadDestination","file","submittedPrefix","prefix","clientUploadContext","objectKey","_objectKey","getDocumentProperty","document","property","locale","localizedProperties","has","getLocalizedUploadProperties","fields","Set","field","localized","add","name","validateFilename","pathSegments","replace","split","posix","isAbsolute","win32","includes","sanitizeUploadData","operation","sizes","sizeData","values","sanitizedData","mergeUploadDataWithDocument","options","mergedData","documentSizes","mergedSizes","sizeName","entries","documentSize","uploadDerivedProperties","restoreUploadDataFromDocument","restoredData"],"mappings":"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"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getExternalUploadSource, getLocalizedUploadProperties, getUploadDestination, mergeUploadDataWithDocument, restoreUploadDataFromDocument, sanitizeUploadData } from './sanitizeUploadData.js';
|
|
3
|
+
import { flattenAllFields } from '../utilities/flattenAllFields.js';
|
|
4
|
+
describe('sanitizeUploadData', ()=>{
|
|
5
|
+
it('should preserve only the temporary external upload source', ()=>{
|
|
6
|
+
expect(getExternalUploadSource({
|
|
7
|
+
alt: 'Alternative text',
|
|
8
|
+
filename: 'remote.png',
|
|
9
|
+
sizes: {
|
|
10
|
+
thumbnail: {
|
|
11
|
+
filename: 'submitted-thumbnail.png'
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
url: 'https://example.com/remote.png'
|
|
15
|
+
})).toEqual({
|
|
16
|
+
filename: 'remote.png',
|
|
17
|
+
url: 'https://example.com/remote.png'
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
it('should remove submitted generated file data on update', ()=>{
|
|
21
|
+
expect(sanitizeUploadData({
|
|
22
|
+
alt: 'Updated alternative text',
|
|
23
|
+
filename: 'submitted.png',
|
|
24
|
+
prefix: 'articles',
|
|
25
|
+
sizes: {
|
|
26
|
+
thumbnail: {
|
|
27
|
+
filename: 'submitted-thumbnail.png',
|
|
28
|
+
height: 100,
|
|
29
|
+
width: 100
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
url: '/api/media/file/submitted.png'
|
|
33
|
+
}, 'update')).toEqual({
|
|
34
|
+
alt: 'Updated alternative text'
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
it('should preserve a submitted prefix on create', ()=>{
|
|
38
|
+
expect(sanitizeUploadData({
|
|
39
|
+
filename: 'submitted.png',
|
|
40
|
+
prefix: 'articles'
|
|
41
|
+
}, 'create')).toEqual({
|
|
42
|
+
prefix: 'articles'
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
it('should use a submitted prefix when writing a new file', ()=>{
|
|
46
|
+
expect(getUploadDestination({
|
|
47
|
+
data: {
|
|
48
|
+
prefix: 'articles'
|
|
49
|
+
},
|
|
50
|
+
file: {}
|
|
51
|
+
})).toEqual({
|
|
52
|
+
prefix: 'articles'
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
it('should use the destination bound to a client upload context', ()=>{
|
|
56
|
+
expect(getUploadDestination({
|
|
57
|
+
data: {
|
|
58
|
+
prefix: 'submitted'
|
|
59
|
+
},
|
|
60
|
+
file: {
|
|
61
|
+
clientUploadContext: {
|
|
62
|
+
_objectKey: 'abc123',
|
|
63
|
+
prefix: 'provider'
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
})).toEqual({
|
|
67
|
+
objectKey: 'abc123',
|
|
68
|
+
prefix: 'provider'
|
|
69
|
+
});
|
|
70
|
+
expect(getUploadDestination({
|
|
71
|
+
data: {
|
|
72
|
+
prefix: 'submitted'
|
|
73
|
+
},
|
|
74
|
+
file: {
|
|
75
|
+
clientUploadContext: {
|
|
76
|
+
key: 'provider/file.png'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})).toEqual({});
|
|
80
|
+
});
|
|
81
|
+
it('should not preserve a submitted prefix without a new file', ()=>{
|
|
82
|
+
expect(getUploadDestination({
|
|
83
|
+
data: {
|
|
84
|
+
prefix: 'articles'
|
|
85
|
+
},
|
|
86
|
+
file: undefined
|
|
87
|
+
})).toEqual({});
|
|
88
|
+
});
|
|
89
|
+
it.each([
|
|
90
|
+
{
|
|
91
|
+
filename: '../submitted.png'
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
filename: '/submitted.png'
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
filename: 'C:\\submitted.png'
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
filename: '\\\\server\\submitted.png'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
filename: 'images/../submitted.png'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
sizes: {
|
|
107
|
+
thumbnail: {
|
|
108
|
+
filename: '..\\submitted-thumbnail.png'
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
])('should reject an invalid submitted filename', (data)=>{
|
|
113
|
+
expect(()=>sanitizeUploadData(data, 'update')).toThrow('Invalid filename.');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('mergeUploadDataWithDocument', ()=>{
|
|
117
|
+
it('should add stored generated file data to an update', ()=>{
|
|
118
|
+
expect(mergeUploadDataWithDocument({
|
|
119
|
+
alt: 'Updated alternative text'
|
|
120
|
+
}, {
|
|
121
|
+
filename: 'stored.png',
|
|
122
|
+
prefix: 'articles',
|
|
123
|
+
sizes: {
|
|
124
|
+
thumbnail: {
|
|
125
|
+
filename: 'stored-thumbnail.png',
|
|
126
|
+
height: 100,
|
|
127
|
+
width: 100
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
url: '/api/media/file/stored.png'
|
|
131
|
+
})).toEqual({
|
|
132
|
+
alt: 'Updated alternative text',
|
|
133
|
+
filename: 'stored.png',
|
|
134
|
+
prefix: 'articles',
|
|
135
|
+
sizes: {
|
|
136
|
+
thumbnail: {
|
|
137
|
+
filename: 'stored-thumbnail.png',
|
|
138
|
+
height: 100,
|
|
139
|
+
width: 100
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
url: '/api/media/file/stored.png'
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
it('should preserve generated file data supplied by a trusted hook', ()=>{
|
|
146
|
+
expect(mergeUploadDataWithDocument({
|
|
147
|
+
filename: 'hook.png',
|
|
148
|
+
prefix: 'hook-prefix',
|
|
149
|
+
sizes: {
|
|
150
|
+
thumbnail: {
|
|
151
|
+
filename: 'hook-thumbnail.png'
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
url: '/api/media/file/hook.png'
|
|
155
|
+
}, {
|
|
156
|
+
filename: 'stored.png',
|
|
157
|
+
prefix: 'stored-prefix',
|
|
158
|
+
sizes: {
|
|
159
|
+
thumbnail: {
|
|
160
|
+
filename: 'stored-thumbnail.png',
|
|
161
|
+
height: 100,
|
|
162
|
+
width: 100
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
url: '/api/media/file/stored.png'
|
|
166
|
+
})).toEqual({
|
|
167
|
+
filename: 'hook.png',
|
|
168
|
+
prefix: 'hook-prefix',
|
|
169
|
+
sizes: {
|
|
170
|
+
thumbnail: {
|
|
171
|
+
filename: 'hook-thumbnail.png',
|
|
172
|
+
height: 100,
|
|
173
|
+
width: 100
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
url: '/api/media/file/hook.png'
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
it('should merge the selected value for localized generated file data', ()=>{
|
|
180
|
+
expect(mergeUploadDataWithDocument({
|
|
181
|
+
alt: 'Updated alternative text'
|
|
182
|
+
}, {
|
|
183
|
+
prefix: {
|
|
184
|
+
en: 'current-prefix',
|
|
185
|
+
es: 'prefijo-actual'
|
|
186
|
+
}
|
|
187
|
+
}, {
|
|
188
|
+
locale: 'en',
|
|
189
|
+
localizedProperties: new Set([
|
|
190
|
+
'prefix'
|
|
191
|
+
])
|
|
192
|
+
})).toEqual({
|
|
193
|
+
alt: 'Updated alternative text',
|
|
194
|
+
prefix: 'current-prefix'
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe('getLocalizedUploadProperties', ()=>{
|
|
199
|
+
it('should identify localized flattened fields', ()=>{
|
|
200
|
+
expect(getLocalizedUploadProperties(flattenAllFields({
|
|
201
|
+
fields: [
|
|
202
|
+
{
|
|
203
|
+
fields: [
|
|
204
|
+
{
|
|
205
|
+
localized: true,
|
|
206
|
+
name: 'prefix',
|
|
207
|
+
type: 'text'
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'url',
|
|
211
|
+
type: 'text'
|
|
212
|
+
}
|
|
213
|
+
],
|
|
214
|
+
type: 'row'
|
|
215
|
+
}
|
|
216
|
+
]
|
|
217
|
+
}))).toEqual(new Set([
|
|
218
|
+
'prefix'
|
|
219
|
+
]));
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
describe('restoreUploadDataFromDocument', ()=>{
|
|
223
|
+
it('should replace the complete generated file tuple and preserve missing values', ()=>{
|
|
224
|
+
expect(restoreUploadDataFromDocument({
|
|
225
|
+
filename: 'version.png',
|
|
226
|
+
focalX: 10,
|
|
227
|
+
thumbnailURL: '/version-thumbnail.png'
|
|
228
|
+
}, {
|
|
229
|
+
filename: 'current.png',
|
|
230
|
+
thumbnailURL: null
|
|
231
|
+
})).toEqual({
|
|
232
|
+
filename: 'current.png',
|
|
233
|
+
thumbnailURL: null
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
it('should restore the selected value for localized generated file data', ()=>{
|
|
237
|
+
expect(restoreUploadDataFromDocument({
|
|
238
|
+
prefix: 'version-prefix'
|
|
239
|
+
}, {
|
|
240
|
+
prefix: {
|
|
241
|
+
en: 'current-prefix',
|
|
242
|
+
es: 'prefijo-actual'
|
|
243
|
+
}
|
|
244
|
+
}, {
|
|
245
|
+
locale: 'en',
|
|
246
|
+
localizedProperties: new Set([
|
|
247
|
+
'prefix'
|
|
248
|
+
])
|
|
249
|
+
})).toEqual({
|
|
250
|
+
prefix: 'current-prefix'
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
//# sourceMappingURL=sanitizeUploadData.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/sanitizeUploadData.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport {\n getExternalUploadSource,\n getLocalizedUploadProperties,\n getUploadDestination,\n mergeUploadDataWithDocument,\n restoreUploadDataFromDocument,\n sanitizeUploadData,\n} from './sanitizeUploadData.js'\nimport { flattenAllFields } from '../utilities/flattenAllFields.js'\n\ndescribe('sanitizeUploadData', () => {\n it('should preserve only the temporary external upload source', () => {\n expect(\n getExternalUploadSource({\n alt: 'Alternative text',\n filename: 'remote.png',\n sizes: { thumbnail: { filename: 'submitted-thumbnail.png' } },\n url: 'https://example.com/remote.png',\n }),\n ).toEqual({\n filename: 'remote.png',\n url: 'https://example.com/remote.png',\n })\n })\n\n it('should remove submitted generated file data on update', () => {\n expect(\n sanitizeUploadData(\n {\n alt: 'Updated alternative text',\n filename: 'submitted.png',\n prefix: 'articles',\n sizes: {\n thumbnail: {\n filename: 'submitted-thumbnail.png',\n height: 100,\n width: 100,\n },\n },\n url: '/api/media/file/submitted.png',\n },\n 'update',\n ),\n ).toEqual({\n alt: 'Updated alternative text',\n })\n })\n\n it('should preserve a submitted prefix on create', () => {\n expect(\n sanitizeUploadData(\n {\n filename: 'submitted.png',\n prefix: 'articles',\n },\n 'create',\n ),\n ).toEqual({\n prefix: 'articles',\n })\n })\n\n it('should use a submitted prefix when writing a new file', () => {\n expect(getUploadDestination({ data: { prefix: 'articles' }, file: {} })).toEqual({\n prefix: 'articles',\n })\n })\n\n it('should use the destination bound to a client upload context', () => {\n expect(\n getUploadDestination({\n data: { prefix: 'submitted' },\n file: { clientUploadContext: { _objectKey: 'abc123', prefix: 'provider' } },\n }),\n ).toEqual({ objectKey: 'abc123', prefix: 'provider' })\n expect(\n getUploadDestination({\n data: { prefix: 'submitted' },\n file: { clientUploadContext: { key: 'provider/file.png' } },\n }),\n ).toEqual({})\n })\n\n it('should not preserve a submitted prefix without a new file', () => {\n expect(getUploadDestination({ data: { prefix: 'articles' }, file: undefined })).toEqual({})\n })\n\n it.each([\n { filename: '../submitted.png' },\n { filename: '/submitted.png' },\n { filename: 'C:\\\\submitted.png' },\n { filename: '\\\\\\\\server\\\\submitted.png' },\n { filename: 'images/../submitted.png' },\n { sizes: { thumbnail: { filename: '..\\\\submitted-thumbnail.png' } } },\n ])('should reject an invalid submitted filename', (data) => {\n expect(() => sanitizeUploadData(data, 'update')).toThrow('Invalid filename.')\n })\n})\n\ndescribe('mergeUploadDataWithDocument', () => {\n it('should add stored generated file data to an update', () => {\n expect(\n mergeUploadDataWithDocument(\n { alt: 'Updated alternative text' },\n {\n filename: 'stored.png',\n prefix: 'articles',\n sizes: {\n thumbnail: {\n filename: 'stored-thumbnail.png',\n height: 100,\n width: 100,\n },\n },\n url: '/api/media/file/stored.png',\n },\n ),\n ).toEqual({\n alt: 'Updated alternative text',\n filename: 'stored.png',\n prefix: 'articles',\n sizes: {\n thumbnail: {\n filename: 'stored-thumbnail.png',\n height: 100,\n width: 100,\n },\n },\n url: '/api/media/file/stored.png',\n })\n })\n\n it('should preserve generated file data supplied by a trusted hook', () => {\n expect(\n mergeUploadDataWithDocument(\n {\n filename: 'hook.png',\n prefix: 'hook-prefix',\n sizes: { thumbnail: { filename: 'hook-thumbnail.png' } },\n url: '/api/media/file/hook.png',\n },\n {\n filename: 'stored.png',\n prefix: 'stored-prefix',\n sizes: {\n thumbnail: { filename: 'stored-thumbnail.png', height: 100, width: 100 },\n },\n url: '/api/media/file/stored.png',\n },\n ),\n ).toEqual({\n filename: 'hook.png',\n prefix: 'hook-prefix',\n sizes: {\n thumbnail: { filename: 'hook-thumbnail.png', height: 100, width: 100 },\n },\n url: '/api/media/file/hook.png',\n })\n })\n\n it('should merge the selected value for localized generated file data', () => {\n expect(\n mergeUploadDataWithDocument(\n { alt: 'Updated alternative text' },\n { prefix: { en: 'current-prefix', es: 'prefijo-actual' } },\n { locale: 'en', localizedProperties: new Set(['prefix']) },\n ),\n ).toEqual({ alt: 'Updated alternative text', prefix: 'current-prefix' })\n })\n})\n\ndescribe('getLocalizedUploadProperties', () => {\n it('should identify localized flattened fields', () => {\n expect(\n getLocalizedUploadProperties(\n flattenAllFields({\n fields: [\n {\n fields: [\n { localized: true, name: 'prefix', type: 'text' },\n { name: 'url', type: 'text' },\n ],\n type: 'row',\n },\n ],\n }),\n ),\n ).toEqual(new Set(['prefix']))\n })\n})\n\ndescribe('restoreUploadDataFromDocument', () => {\n it('should replace the complete generated file tuple and preserve missing values', () => {\n expect(\n restoreUploadDataFromDocument(\n { filename: 'version.png', focalX: 10, thumbnailURL: '/version-thumbnail.png' },\n { filename: 'current.png', thumbnailURL: null },\n ),\n ).toEqual({ filename: 'current.png', thumbnailURL: null })\n })\n\n it('should restore the selected value for localized generated file data', () => {\n expect(\n restoreUploadDataFromDocument(\n { prefix: 'version-prefix' },\n { prefix: { en: 'current-prefix', es: 'prefijo-actual' } },\n { locale: 'en', localizedProperties: new Set(['prefix']) },\n ),\n ).toEqual({ prefix: 'current-prefix' })\n })\n})\n"],"names":["describe","expect","it","getExternalUploadSource","getLocalizedUploadProperties","getUploadDestination","mergeUploadDataWithDocument","restoreUploadDataFromDocument","sanitizeUploadData","flattenAllFields","alt","filename","sizes","thumbnail","url","toEqual","prefix","height","width","data","file","clientUploadContext","_objectKey","objectKey","key","undefined","each","toThrow","en","es","locale","localizedProperties","Set","fields","localized","name","type","focalX","thumbnailURL"],"mappings":"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"}
|