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
package/dist/auth/jwt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/jwt.ts"],"sourcesContent":["import { SignJWT } from 'jose'\n\nexport const jwtSign = async ({\n fieldsToSign,\n secret,\n tokenExpiration,\n}: {\n fieldsToSign: Record<string, unknown>\n secret: string\n tokenExpiration: number\n}) => {\n const secretKey = new TextEncoder().encode(secret)\n const issuedAt = Math.floor(Date.now() / 1000)\n const exp = issuedAt + tokenExpiration\n const token = await new SignJWT(fieldsToSign)\n .setProtectedHeader({ alg: 'HS256', typ: 'JWT' })\n .setIssuedAt(issuedAt)\n .setExpirationTime(exp)\n .sign(secretKey)\n return { exp, token }\n}\n"],"names":["SignJWT","jwtSign","fieldsToSign","secret","tokenExpiration","secretKey","TextEncoder","encode","issuedAt","Math","floor","Date","now","exp","token","setProtectedHeader","alg","typ","setIssuedAt","setExpirationTime","sign"],"mappings":"AAAA,SAASA,OAAO,QAAQ,OAAM;AAE9B,OAAO,MAAMC,UAAU,OAAO,EAC5BC,YAAY,EACZC,MAAM,EACNC,eAAe,EAKhB;IACC,MAAMC,YAAY,IAAIC,cAAcC,MAAM,CAACJ;IAC3C,MAAMK,WAAWC,KAAKC,KAAK,CAACC,KAAKC,GAAG,KAAK;IACzC,MAAMC,MAAML,WAAWJ;IACvB,MAAMU,QAAQ,MAAM,
|
|
1
|
+
{"version":3,"sources":["../../src/auth/jwt.ts"],"sourcesContent":["import { SignJWT } from 'jose'\n\nimport { JWT_AUTH_VERSION } from './jwtAuth.js'\n\nexport const jwtSign = async ({\n fieldsToSign,\n secret,\n tokenExpiration,\n}: {\n fieldsToSign: Record<string, unknown>\n secret: string\n tokenExpiration: number\n}) => {\n const secretKey = new TextEncoder().encode(secret)\n const issuedAt = Math.floor(Date.now() / 1000)\n const exp = issuedAt + tokenExpiration\n const token = await new SignJWT(fieldsToSign)\n .setProtectedHeader({ alg: 'HS256', authVersion: JWT_AUTH_VERSION, typ: 'JWT' })\n .setIssuedAt(issuedAt)\n .setExpirationTime(exp)\n .sign(secretKey)\n return { exp, token }\n}\n"],"names":["SignJWT","JWT_AUTH_VERSION","jwtSign","fieldsToSign","secret","tokenExpiration","secretKey","TextEncoder","encode","issuedAt","Math","floor","Date","now","exp","token","setProtectedHeader","alg","authVersion","typ","setIssuedAt","setExpirationTime","sign"],"mappings":"AAAA,SAASA,OAAO,QAAQ,OAAM;AAE9B,SAASC,gBAAgB,QAAQ,eAAc;AAE/C,OAAO,MAAMC,UAAU,OAAO,EAC5BC,YAAY,EACZC,MAAM,EACNC,eAAe,EAKhB;IACC,MAAMC,YAAY,IAAIC,cAAcC,MAAM,CAACJ;IAC3C,MAAMK,WAAWC,KAAKC,KAAK,CAACC,KAAKC,GAAG,KAAK;IACzC,MAAMC,MAAML,WAAWJ;IACvB,MAAMU,QAAQ,MAAM,IAAIf,QAAQG,cAC7Ba,kBAAkB,CAAC;QAAEC,KAAK;QAASC,aAAajB;QAAkBkB,KAAK;IAAM,GAC7EC,WAAW,CAACX,UACZY,iBAAiB,CAACP,KAClBQ,IAAI,CAAChB;IACR,OAAO;QAAEQ;QAAKC;IAAM;AACtB,EAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { decodeJwt, decodeProtectedHeader } from 'jose';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { jwtSign } from './jwt.js';
|
|
4
|
+
import { JWT_AUTH_VERSION } from './jwtAuth.js';
|
|
5
|
+
describe('jwtSign', ()=>{
|
|
6
|
+
it('should add the JWT format version to the signed protected header without changing the payload', async ()=>{
|
|
7
|
+
const { token } = await jwtSign({
|
|
8
|
+
fieldsToSign: {
|
|
9
|
+
collection: 'users',
|
|
10
|
+
id: 'user-id'
|
|
11
|
+
},
|
|
12
|
+
secret: '01234567890123456789012345678901',
|
|
13
|
+
tokenExpiration: 3600
|
|
14
|
+
});
|
|
15
|
+
expect(decodeProtectedHeader(token)).toMatchObject({
|
|
16
|
+
alg: 'HS256',
|
|
17
|
+
authVersion: JWT_AUTH_VERSION,
|
|
18
|
+
typ: 'JWT'
|
|
19
|
+
});
|
|
20
|
+
expect(decodeJwt(token)).not.toHaveProperty('authVersion');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=jwt.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/jwt.spec.ts"],"sourcesContent":["import { decodeJwt, decodeProtectedHeader } from 'jose'\nimport { describe, expect, it } from 'vitest'\n\nimport { jwtSign } from './jwt.js'\nimport { JWT_AUTH_VERSION } from './jwtAuth.js'\n\ndescribe('jwtSign', () => {\n it('should add the JWT format version to the signed protected header without changing the payload', async () => {\n const { token } = await jwtSign({\n fieldsToSign: {\n collection: 'users',\n id: 'user-id',\n },\n secret: '01234567890123456789012345678901',\n tokenExpiration: 3600,\n })\n\n expect(decodeProtectedHeader(token)).toMatchObject({\n alg: 'HS256',\n authVersion: JWT_AUTH_VERSION,\n typ: 'JWT',\n })\n expect(decodeJwt(token)).not.toHaveProperty('authVersion')\n })\n})\n"],"names":["decodeJwt","decodeProtectedHeader","describe","expect","it","jwtSign","JWT_AUTH_VERSION","token","fieldsToSign","collection","id","secret","tokenExpiration","toMatchObject","alg","authVersion","typ","not","toHaveProperty"],"mappings":"AAAA,SAASA,SAAS,EAAEC,qBAAqB,QAAQ,OAAM;AACvD,SAASC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,OAAO,QAAQ,WAAU;AAClC,SAASC,gBAAgB,QAAQ,eAAc;AAE/CJ,SAAS,WAAW;IAClBE,GAAG,iGAAiG;QAClG,MAAM,EAAEG,KAAK,EAAE,GAAG,MAAMF,QAAQ;YAC9BG,cAAc;gBACZC,YAAY;gBACZC,IAAI;YACN;YACAC,QAAQ;YACRC,iBAAiB;QACnB;QAEAT,OAAOF,sBAAsBM,QAAQM,aAAa,CAAC;YACjDC,KAAK;YACLC,aAAaT;YACbU,KAAK;QACP;QACAb,OAAOH,UAAUO,QAAQU,GAAG,CAACC,cAAc,CAAC;IAC9C;AACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version of Payload's JWT authentication format, stored in the signed protected header.
|
|
3
|
+
*
|
|
4
|
+
* The signer, verifier, and external validators must agree on this value. A mismatch
|
|
5
|
+
* rejects every token in the system, so they should import it rather than repeat the literal.
|
|
6
|
+
*/
|
|
7
|
+
export declare const JWT_AUTH_VERSION = 1;
|
|
8
|
+
export type JWTAuthVersion = typeof JWT_AUTH_VERSION;
|
|
9
|
+
//# sourceMappingURL=jwtAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwtAuth.d.ts","sourceRoot":"","sources":["../../src/auth/jwtAuth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAA;AAEjC,MAAM,MAAM,cAAc,GAAG,OAAO,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version of Payload's JWT authentication format, stored in the signed protected header.
|
|
3
|
+
*
|
|
4
|
+
* The signer, verifier, and external validators must agree on this value. A mismatch
|
|
5
|
+
* rejects every token in the system, so they should import it rather than repeat the literal.
|
|
6
|
+
*/ export const JWT_AUTH_VERSION = 1;
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=jwtAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/jwtAuth.ts"],"sourcesContent":["/**\n * Version of Payload's JWT authentication format, stored in the signed protected header.\n *\n * The signer, verifier, and external validators must agree on this value. A mismatch\n * rejects every token in the system, so they should import it rather than repeat the literal.\n */\nexport const JWT_AUTH_VERSION = 1\n\nexport type JWTAuthVersion = typeof JWT_AUTH_VERSION\n"],"names":["JWT_AUTH_VERSION"],"mappings":"AAAA;;;;;CAKC,GACD,OAAO,MAAMA,mBAAmB,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAM1D,MAAM,MAAM,QAAQ,GAAG;IACrB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IAC3B,GAAG,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,oBAAoB,CAAA;IACjC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,IAAI,EAAE,IAAI,GAAG,SAAS,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,IAAI,SAAgB,QAAQ,CAAC,QAAQ,CAAC,KAAG,OAAO,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAM1D,MAAM,MAAM,QAAQ,GAAG;IACrB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IAC3B,GAAG,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,oBAAoB,CAAA;IACjC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,IAAI,EAAE,IAAI,GAAG,SAAS,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,IAAI,SAAgB,QAAQ,CAAC,QAAQ,CAAC,KAAG,OAAO,CAAC,UAAU,CA6BvE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/operations/auth.ts"],"sourcesContent":["import type { SanitizedPermissions, TypedUser } from '../../index.js'\nimport type { PayloadRequest } from '../../types/index.js'\n\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { executeAuthStrategies } from '../executeAuthStrategies.js'\nimport { getAccessResults } from '../getAccessResults.js'\n\nexport type AuthArgs = {\n /**\n * Specify if it's possible for auth strategies to set headers within this operation.\n */\n canSetHeaders?: boolean\n headers: Request['headers']\n req?: Omit<PayloadRequest, 'user'>\n}\n\nexport type AuthResult = {\n permissions: SanitizedPermissions\n responseHeaders?: Headers\n user: null | TypedUser\n}\n\nexport const auth = async (args: Required<AuthArgs>): Promise<AuthResult> => {\n const { canSetHeaders, headers } = args\n const req = args.req as PayloadRequest\n const { payload } = req\n\n try {\n const { responseHeaders, user } = await executeAuthStrategies({\n canSetHeaders,\n headers,\n payload,\n })\n\n req.user = user\n req.responseHeaders = responseHeaders\n\n const permissions = await getAccessResults({\n req,\n })\n\n return {\n permissions,\n responseHeaders,\n user,\n }\n } catch (error: unknown) {\n await killTransaction(req)\n throw error\n }\n}\n"],"names":["killTransaction","executeAuthStrategies","getAccessResults","auth","args","canSetHeaders","headers","req","payload","responseHeaders","user","permissions","error"],"mappings":"AAGA,SAASA,eAAe,QAAQ,qCAAoC;AACpE,SAASC,qBAAqB,QAAQ,8BAA6B;AACnE,SAASC,gBAAgB,QAAQ,yBAAwB;AAiBzD,OAAO,MAAMC,OAAO,OAAOC;IACzB,MAAM,EAAEC,aAAa,EAAEC,OAAO,EAAE,GAAGF;IACnC,MAAMG,MAAMH,KAAKG,GAAG;IACpB,MAAM,EAAEC,OAAO,EAAE,GAAGD;IAEpB,IAAI;QACF,MAAM,EAAEE,eAAe,EAAEC,IAAI,EAAE,GAAG,MAAMT,sBAAsB;YAC5DI;YACAC;YACAE;QACF;
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/operations/auth.ts"],"sourcesContent":["import type { SanitizedPermissions, TypedUser } from '../../index.js'\nimport type { PayloadRequest } from '../../types/index.js'\n\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { executeAuthStrategies } from '../executeAuthStrategies.js'\nimport { getAccessResults } from '../getAccessResults.js'\n\nexport type AuthArgs = {\n /**\n * Specify if it's possible for auth strategies to set headers within this operation.\n */\n canSetHeaders?: boolean\n headers: Request['headers']\n req?: Omit<PayloadRequest, 'user'>\n}\n\nexport type AuthResult = {\n permissions: SanitizedPermissions\n responseHeaders?: Headers\n user: null | TypedUser\n}\n\nexport const auth = async (args: Required<AuthArgs>): Promise<AuthResult> => {\n const { canSetHeaders, headers } = args\n const req = args.req as PayloadRequest\n const { payload } = req\n\n try {\n const { responseHeaders, user } = await executeAuthStrategies({\n canSetHeaders,\n headers,\n payload,\n req,\n })\n\n req.user = user\n req.responseHeaders = responseHeaders\n\n const permissions = await getAccessResults({\n req,\n })\n\n return {\n permissions,\n responseHeaders,\n user,\n }\n } catch (error: unknown) {\n await killTransaction(req)\n throw error\n }\n}\n"],"names":["killTransaction","executeAuthStrategies","getAccessResults","auth","args","canSetHeaders","headers","req","payload","responseHeaders","user","permissions","error"],"mappings":"AAGA,SAASA,eAAe,QAAQ,qCAAoC;AACpE,SAASC,qBAAqB,QAAQ,8BAA6B;AACnE,SAASC,gBAAgB,QAAQ,yBAAwB;AAiBzD,OAAO,MAAMC,OAAO,OAAOC;IACzB,MAAM,EAAEC,aAAa,EAAEC,OAAO,EAAE,GAAGF;IACnC,MAAMG,MAAMH,KAAKG,GAAG;IACpB,MAAM,EAAEC,OAAO,EAAE,GAAGD;IAEpB,IAAI;QACF,MAAM,EAAEE,eAAe,EAAEC,IAAI,EAAE,GAAG,MAAMT,sBAAsB;YAC5DI;YACAC;YACAE;YACAD;QACF;QAEAA,IAAIG,IAAI,GAAGA;QACXH,IAAIE,eAAe,GAAGA;QAEtB,MAAME,cAAc,MAAMT,iBAAiB;YACzCK;QACF;QAEA,OAAO;YACLI;YACAF;YACAC;QACF;IACF,EAAE,OAAOE,OAAgB;QACvB,MAAMZ,gBAAgBO;QACtB,MAAMK;IACR;AACF,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forgotPassword.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/forgotPassword.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,gCAAgC,EAChC,UAAU,EACX,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"forgotPassword.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/forgotPassword.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,gCAAgC,EAChC,UAAU,EACX,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,sBAAsB,CAAA;AAejE,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,kBAAkB,IAAI;IACxD,UAAU,EAAE,UAAU,CAAA;IACtB,IAAI,EAAE;QACJ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,GAAG,gCAAgC,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,CAAA;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,GAAG,EAAE,cAAc,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,CAAA;AAE3B,eAAO,MAAM,uBAAuB,GAAU,KAAK,SAAS,kBAAkB,gBAC9D,SAAS,CAAC,KAAK,CAAC,KAC7B,OAAO,CAAC,IAAI,GAAG,MAAM,CA6PvB,CAAA"}
|
|
@@ -9,6 +9,7 @@ import { commitTransaction } from '../../utilities/commitTransaction.js';
|
|
|
9
9
|
import { formatAdminURL } from '../../utilities/formatAdminURL.js';
|
|
10
10
|
import { getRequestOrigin } from '../../utilities/getRequestOrigin.js';
|
|
11
11
|
import { initTransaction } from '../../utilities/initTransaction.js';
|
|
12
|
+
import { isolateObjectProperty } from '../../utilities/isolateObjectProperty.js';
|
|
12
13
|
import { killTransaction } from '../../utilities/killTransaction.js';
|
|
13
14
|
import { getLoginOptions } from '../getLoginOptions.js';
|
|
14
15
|
export const forgotPasswordOperation = async (incomingArgs)=>{
|
|
@@ -18,6 +19,8 @@ export const forgotPasswordOperation = async (incomingArgs)=>{
|
|
|
18
19
|
const sanitizedEmail = canLoginWithEmail && (incomingArgs.data.email || '').toLowerCase().trim() || null;
|
|
19
20
|
const sanitizedUsername = 'username' in data && typeof data?.username === 'string' ? data.username.toLowerCase().trim() : null;
|
|
20
21
|
let args = incomingArgs;
|
|
22
|
+
let hasSentEmail = false;
|
|
23
|
+
let releaseRequestInterval = null;
|
|
21
24
|
if (incomingArgs.collection.config.auth.disableLocalStrategy) {
|
|
22
25
|
throw new Forbidden(incomingArgs.req.t);
|
|
23
26
|
}
|
|
@@ -36,6 +39,7 @@ export const forgotPasswordOperation = async (incomingArgs)=>{
|
|
|
36
39
|
overrideAccess
|
|
37
40
|
});
|
|
38
41
|
const { collection: { config: collectionConfig }, disableEmail, expiration, req: { payload: { config, email }, payload }, req } = args;
|
|
42
|
+
const minRequestInterval = collectionConfig.auth.forgotPassword?.minRequestInterval ?? 15000;
|
|
39
43
|
// /////////////////////////////////////
|
|
40
44
|
// Forget password
|
|
41
45
|
// /////////////////////////////////////
|
|
@@ -63,19 +67,92 @@ export const forgotPasswordOperation = async (incomingArgs)=>{
|
|
|
63
67
|
trash: false,
|
|
64
68
|
where: whereConstraint
|
|
65
69
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
const resetPasswordExpiration = new Date(now + (collectionConfig.auth?.forgotPassword?.expiration ?? expiration ?? 3600000)).toISOString();
|
|
72
|
+
let user;
|
|
73
|
+
if (!disableEmail && minRequestInterval > 0) {
|
|
74
|
+
const requestedAt = new Date(now).toISOString();
|
|
75
|
+
const reservationReq = isolateObjectProperty(req, 'transactionID');
|
|
76
|
+
reservationReq.transactionID = undefined;
|
|
77
|
+
user = await payload.db.updateOne({
|
|
78
|
+
collection: collectionConfig.slug,
|
|
79
|
+
data: {
|
|
80
|
+
resetPasswordRequestedAt: requestedAt
|
|
81
|
+
},
|
|
82
|
+
options: {
|
|
83
|
+
atomic: true
|
|
84
|
+
},
|
|
85
|
+
req: reservationReq,
|
|
86
|
+
where: {
|
|
87
|
+
and: [
|
|
88
|
+
whereConstraint,
|
|
89
|
+
{
|
|
90
|
+
or: [
|
|
91
|
+
{
|
|
92
|
+
resetPasswordRequestedAt: {
|
|
93
|
+
exists: false
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
resetPasswordRequestedAt: {
|
|
98
|
+
equals: null
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
resetPasswordRequestedAt: {
|
|
103
|
+
less_than_equal: new Date(now - minRequestInterval).toISOString()
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
if (user) {
|
|
112
|
+
const userID = user.id;
|
|
113
|
+
releaseRequestInterval = async ()=>{
|
|
114
|
+
await payload.db.updateOne({
|
|
115
|
+
collection: collectionConfig.slug,
|
|
116
|
+
data: {
|
|
117
|
+
resetPasswordRequestedAt: null
|
|
118
|
+
},
|
|
119
|
+
options: {
|
|
120
|
+
atomic: true
|
|
121
|
+
},
|
|
122
|
+
req: reservationReq,
|
|
123
|
+
where: {
|
|
124
|
+
and: [
|
|
125
|
+
{
|
|
126
|
+
id: {
|
|
127
|
+
equals: userID
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
resetPasswordRequestedAt: {
|
|
132
|
+
equals: requestedAt
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
user = await payload.db.findOne({
|
|
142
|
+
collection: collectionConfig.slug,
|
|
143
|
+
req,
|
|
144
|
+
where: whereConstraint
|
|
145
|
+
});
|
|
146
|
+
}
|
|
71
147
|
// We don't want to indicate specifically that an email was not found,
|
|
72
148
|
// as doing so could lead to the exposure of registered emails.
|
|
73
149
|
// Therefore, we prefer to fail silently.
|
|
74
150
|
if (!user) {
|
|
75
|
-
|
|
151
|
+
if (shouldCommit) {
|
|
152
|
+
await commitTransaction(args.req);
|
|
153
|
+
}
|
|
76
154
|
return null;
|
|
77
155
|
}
|
|
78
|
-
const resetPasswordExpiration = new Date(Date.now() + (collectionConfig.auth?.forgotPassword?.expiration ?? expiration ?? 3600000)).toISOString();
|
|
79
156
|
user = await payload.update({
|
|
80
157
|
id: user.id,
|
|
81
158
|
collection: collectionConfig.slug,
|
|
@@ -119,6 +196,7 @@ export const forgotPasswordOperation = async (incomingArgs)=>{
|
|
|
119
196
|
subject,
|
|
120
197
|
to: user.email
|
|
121
198
|
});
|
|
199
|
+
hasSentEmail = true;
|
|
122
200
|
}
|
|
123
201
|
// /////////////////////////////////////
|
|
124
202
|
// afterForgotPassword - Collection
|
|
@@ -148,6 +226,16 @@ export const forgotPasswordOperation = async (incomingArgs)=>{
|
|
|
148
226
|
return token;
|
|
149
227
|
} catch (error) {
|
|
150
228
|
await killTransaction(args.req);
|
|
229
|
+
if (!hasSentEmail && releaseRequestInterval) {
|
|
230
|
+
try {
|
|
231
|
+
await releaseRequestInterval();
|
|
232
|
+
} catch (err) {
|
|
233
|
+
args.req.payload.logger.error({
|
|
234
|
+
err,
|
|
235
|
+
msg: 'Failed to release forgot-password interval'
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
151
239
|
throw error;
|
|
152
240
|
}
|
|
153
241
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/operations/forgotPassword.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { status as httpStatus } from 'http-status'\n\nimport type {\n AuthOperationsFromCollectionSlug,\n Collection,\n} from '../../collections/config/types.js'\nimport type { AuthCollectionSlug } from '../../index.js'\nimport type { PayloadRequest, Where } from '../../types/index.js'\n\nimport { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js'\nimport { APIError } from '../../errors/index.js'\nimport { Forbidden } from '../../index.js'\nimport { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'\nimport { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { formatAdminURL } from '../../utilities/formatAdminURL.js'\nimport { getRequestOrigin } from '../../utilities/getRequestOrigin.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { getLoginOptions } from '../getLoginOptions.js'\n\nexport type Arguments<TSlug extends AuthCollectionSlug> = {\n collection: Collection\n data: {\n [key: string]: unknown\n } & AuthOperationsFromCollectionSlug<TSlug>['forgotPassword']\n disableEmail?: boolean\n expiration?: number\n overrideAccess?: boolean\n req: PayloadRequest\n}\n\nexport type Result = string\n\nexport const forgotPasswordOperation = async <TSlug extends AuthCollectionSlug>(\n incomingArgs: Arguments<TSlug>,\n): Promise<null | string> => {\n const loginWithUsername = incomingArgs.collection.config.auth.loginWithUsername\n const { data, overrideAccess } = incomingArgs\n\n const { canLoginWithEmail, canLoginWithUsername } = getLoginOptions(loginWithUsername)\n\n const sanitizedEmail =\n (canLoginWithEmail && (incomingArgs.data.email || '').toLowerCase().trim()) || null\n const sanitizedUsername =\n 'username' in data && typeof data?.username === 'string'\n ? data.username.toLowerCase().trim()\n : null\n\n let args = incomingArgs\n\n if (incomingArgs.collection.config.auth.disableLocalStrategy) {\n throw new Forbidden(incomingArgs.req.t)\n }\n if (!sanitizedEmail && !sanitizedUsername) {\n throw new APIError(\n `Missing ${loginWithUsername ? 'username' : 'email'}.`,\n httpStatus.BAD_REQUEST,\n )\n }\n\n try {\n const shouldCommit = await initTransaction(args.req)\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'forgotPassword',\n overrideAccess,\n })\n\n const {\n collection: { config: collectionConfig },\n disableEmail,\n expiration,\n req: {\n payload: { config, email },\n payload,\n },\n req,\n } = args\n\n // /////////////////////////////////////\n // Forget password\n // /////////////////////////////////////\n\n let token: string = crypto.randomBytes(20).toString('hex')\n type UserDoc = {\n email?: string\n id: number | string\n resetPasswordExpiration?: string\n resetPasswordToken?: string\n }\n\n if (!sanitizedEmail && !sanitizedUsername) {\n throw new APIError(\n `Missing ${loginWithUsername ? 'username' : 'email'}.`,\n httpStatus.BAD_REQUEST,\n )\n }\n\n let whereConstraint: Where = {}\n\n if (canLoginWithEmail && sanitizedEmail) {\n whereConstraint = {\n email: {\n equals: sanitizedEmail,\n },\n }\n } else if (canLoginWithUsername && sanitizedUsername) {\n whereConstraint = {\n username: {\n equals: sanitizedUsername,\n },\n }\n }\n\n // Exclude trashed users unless `trash: true`\n whereConstraint = appendNonTrashedFilter({\n enableTrash: collectionConfig.trash,\n trash: false,\n where: whereConstraint,\n })\n\n let user = await payload.db.findOne<UserDoc>({\n collection: collectionConfig.slug,\n req,\n where: whereConstraint,\n })\n\n // We don't want to indicate specifically that an email was not found,\n // as doing so could lead to the exposure of registered emails.\n // Therefore, we prefer to fail silently.\n if (!user) {\n await commitTransaction(args.req)\n return null\n }\n\n const resetPasswordExpiration = new Date(\n Date.now() + (collectionConfig.auth?.forgotPassword?.expiration ?? expiration ?? 3600000),\n ).toISOString()\n\n user = await payload.update({\n id: user.id,\n collection: collectionConfig.slug,\n data: {\n resetPasswordExpiration,\n resetPasswordToken: token,\n },\n req,\n })\n\n if (!disableEmail && user.email) {\n const serverURL = getRequestOrigin({ config, req })\n const forgotURL = formatAdminURL({\n adminRoute: config.routes.admin,\n path: `${config.admin.routes.reset}/${token}`,\n serverURL,\n })\n let html = `${req.t('authentication:youAreReceivingResetPassword')}\n <a href=\"${forgotURL}\">${forgotURL}</a>\n ${req.t('authentication:youDidNotRequestPassword')}`\n\n if (typeof collectionConfig.auth.forgotPassword?.generateEmailHTML === 'function') {\n html = await collectionConfig.auth.forgotPassword.generateEmailHTML({\n req,\n token,\n user,\n })\n }\n\n let subject = req.t('authentication:resetYourPassword')\n\n if (typeof collectionConfig.auth.forgotPassword?.generateEmailSubject === 'function') {\n subject = await collectionConfig.auth.forgotPassword.generateEmailSubject({\n req,\n token,\n user,\n })\n }\n\n await email.sendEmail({\n from: `\"${email.defaultFromName}\" <${email.defaultFromAddress}>`,\n html,\n subject,\n to: user.email,\n })\n }\n\n // /////////////////////////////////////\n // afterForgotPassword - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterForgotPassword?.length) {\n for (const hook of collectionConfig.hooks.afterForgotPassword) {\n await hook({ args, collection: args.collection?.config, context: req.context })\n }\n }\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n token = await buildAfterOperation({\n args,\n collection: args.collection?.config,\n operation: 'forgotPassword',\n overrideAccess,\n result: token,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n return token\n } catch (error: unknown) {\n await killTransaction(args.req)\n throw error\n }\n}\n"],"names":["crypto","status","httpStatus","buildAfterOperation","buildBeforeOperation","APIError","Forbidden","appendNonTrashedFilter","commitTransaction","formatAdminURL","getRequestOrigin","initTransaction","killTransaction","getLoginOptions","forgotPasswordOperation","incomingArgs","loginWithUsername","collection","config","auth","data","overrideAccess","canLoginWithEmail","canLoginWithUsername","sanitizedEmail","email","toLowerCase","trim","sanitizedUsername","username","args","disableLocalStrategy","req","t","BAD_REQUEST","shouldCommit","operation","collectionConfig","disableEmail","expiration","payload","token","randomBytes","toString","whereConstraint","equals","enableTrash","trash","where","user","db","findOne","slug","resetPasswordExpiration","Date","now","forgotPassword","toISOString","update","id","resetPasswordToken","serverURL","forgotURL","adminRoute","routes","admin","path","reset","html","generateEmailHTML","subject","generateEmailSubject","sendEmail","from","defaultFromName","defaultFromAddress","to","hooks","afterForgotPassword","length","hook","context","result","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/operations/forgotPassword.ts"],"sourcesContent":["import crypto from 'crypto'\nimport { status as httpStatus } from 'http-status'\n\nimport type {\n AuthOperationsFromCollectionSlug,\n Collection,\n} from '../../collections/config/types.js'\nimport type { AuthCollectionSlug } from '../../index.js'\nimport type { PayloadRequest, Where } from '../../types/index.js'\n\nimport { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js'\nimport { APIError } from '../../errors/index.js'\nimport { Forbidden } from '../../index.js'\nimport { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'\nimport { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { formatAdminURL } from '../../utilities/formatAdminURL.js'\nimport { getRequestOrigin } from '../../utilities/getRequestOrigin.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { isolateObjectProperty } from '../../utilities/isolateObjectProperty.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { getLoginOptions } from '../getLoginOptions.js'\n\nexport type Arguments<TSlug extends AuthCollectionSlug> = {\n collection: Collection\n data: {\n [key: string]: unknown\n } & AuthOperationsFromCollectionSlug<TSlug>['forgotPassword']\n disableEmail?: boolean\n expiration?: number\n overrideAccess?: boolean\n req: PayloadRequest\n}\n\nexport type Result = string\n\nexport const forgotPasswordOperation = async <TSlug extends AuthCollectionSlug>(\n incomingArgs: Arguments<TSlug>,\n): Promise<null | string> => {\n const loginWithUsername = incomingArgs.collection.config.auth.loginWithUsername\n const { data, overrideAccess } = incomingArgs\n\n const { canLoginWithEmail, canLoginWithUsername } = getLoginOptions(loginWithUsername)\n\n const sanitizedEmail =\n (canLoginWithEmail && (incomingArgs.data.email || '').toLowerCase().trim()) || null\n const sanitizedUsername =\n 'username' in data && typeof data?.username === 'string'\n ? data.username.toLowerCase().trim()\n : null\n let args = incomingArgs\n let hasSentEmail = false\n let releaseRequestInterval: (() => Promise<void>) | null = null\n\n if (incomingArgs.collection.config.auth.disableLocalStrategy) {\n throw new Forbidden(incomingArgs.req.t)\n }\n if (!sanitizedEmail && !sanitizedUsername) {\n throw new APIError(\n `Missing ${loginWithUsername ? 'username' : 'email'}.`,\n httpStatus.BAD_REQUEST,\n )\n }\n\n try {\n const shouldCommit = await initTransaction(args.req)\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'forgotPassword',\n overrideAccess,\n })\n\n const {\n collection: { config: collectionConfig },\n disableEmail,\n expiration,\n req: {\n payload: { config, email },\n payload,\n },\n req,\n } = args\n const minRequestInterval = collectionConfig.auth.forgotPassword?.minRequestInterval ?? 15000\n\n // /////////////////////////////////////\n // Forget password\n // /////////////////////////////////////\n\n let token: string = crypto.randomBytes(20).toString('hex')\n type UserDoc = {\n email?: string\n id: number | string\n resetPasswordExpiration?: string\n resetPasswordRequestedAt?: string\n resetPasswordToken?: string\n }\n\n if (!sanitizedEmail && !sanitizedUsername) {\n throw new APIError(\n `Missing ${loginWithUsername ? 'username' : 'email'}.`,\n httpStatus.BAD_REQUEST,\n )\n }\n\n let whereConstraint: Where = {}\n\n if (canLoginWithEmail && sanitizedEmail) {\n whereConstraint = {\n email: {\n equals: sanitizedEmail,\n },\n }\n } else if (canLoginWithUsername && sanitizedUsername) {\n whereConstraint = {\n username: {\n equals: sanitizedUsername,\n },\n }\n }\n\n // Exclude trashed users unless `trash: true`\n whereConstraint = appendNonTrashedFilter({\n enableTrash: collectionConfig.trash,\n trash: false,\n where: whereConstraint,\n })\n\n const now = Date.now()\n const resetPasswordExpiration = new Date(\n now + (collectionConfig.auth?.forgotPassword?.expiration ?? expiration ?? 3600000),\n ).toISOString()\n let user: null | UserDoc\n\n if (!disableEmail && minRequestInterval > 0) {\n const requestedAt = new Date(now).toISOString()\n const reservationReq = isolateObjectProperty(req, 'transactionID')\n reservationReq.transactionID = undefined\n\n user = (await payload.db.updateOne({\n collection: collectionConfig.slug,\n data: {\n resetPasswordRequestedAt: requestedAt,\n },\n options: { atomic: true },\n req: reservationReq,\n where: {\n and: [\n whereConstraint,\n {\n or: [\n { resetPasswordRequestedAt: { exists: false } },\n { resetPasswordRequestedAt: { equals: null } },\n {\n resetPasswordRequestedAt: {\n less_than_equal: new Date(now - minRequestInterval).toISOString(),\n },\n },\n ],\n },\n ],\n },\n })) as null | UserDoc\n\n if (user) {\n const userID = user.id\n releaseRequestInterval = async () => {\n await payload.db.updateOne({\n collection: collectionConfig.slug,\n data: { resetPasswordRequestedAt: null },\n options: { atomic: true },\n req: reservationReq,\n where: {\n and: [\n { id: { equals: userID } },\n { resetPasswordRequestedAt: { equals: requestedAt } },\n ],\n },\n })\n }\n }\n } else {\n user = await payload.db.findOne<UserDoc>({\n collection: collectionConfig.slug,\n req,\n where: whereConstraint,\n })\n }\n\n // We don't want to indicate specifically that an email was not found,\n // as doing so could lead to the exposure of registered emails.\n // Therefore, we prefer to fail silently.\n if (!user) {\n if (shouldCommit) {\n await commitTransaction(args.req)\n }\n return null\n }\n\n user = await payload.update({\n id: user.id,\n collection: collectionConfig.slug,\n data: {\n resetPasswordExpiration,\n resetPasswordToken: token,\n },\n req,\n })\n\n if (!disableEmail && user.email) {\n const serverURL = getRequestOrigin({ config, req })\n const forgotURL = formatAdminURL({\n adminRoute: config.routes.admin,\n path: `${config.admin.routes.reset}/${token}`,\n serverURL,\n })\n let html = `${req.t('authentication:youAreReceivingResetPassword')}\n <a href=\"${forgotURL}\">${forgotURL}</a>\n ${req.t('authentication:youDidNotRequestPassword')}`\n\n if (typeof collectionConfig.auth.forgotPassword?.generateEmailHTML === 'function') {\n html = await collectionConfig.auth.forgotPassword.generateEmailHTML({\n req,\n token,\n user,\n })\n }\n\n let subject = req.t('authentication:resetYourPassword')\n\n if (typeof collectionConfig.auth.forgotPassword?.generateEmailSubject === 'function') {\n subject = await collectionConfig.auth.forgotPassword.generateEmailSubject({\n req,\n token,\n user,\n })\n }\n\n await email.sendEmail({\n from: `\"${email.defaultFromName}\" <${email.defaultFromAddress}>`,\n html,\n subject,\n to: user.email,\n })\n hasSentEmail = true\n }\n\n // /////////////////////////////////////\n // afterForgotPassword - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterForgotPassword?.length) {\n for (const hook of collectionConfig.hooks.afterForgotPassword) {\n await hook({ args, collection: args.collection?.config, context: req.context })\n }\n }\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n token = await buildAfterOperation({\n args,\n collection: args.collection?.config,\n operation: 'forgotPassword',\n overrideAccess,\n result: token,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n return token\n } catch (error: unknown) {\n await killTransaction(args.req)\n\n if (!hasSentEmail && releaseRequestInterval) {\n try {\n await releaseRequestInterval()\n } catch (err) {\n args.req.payload.logger.error({ err, msg: 'Failed to release forgot-password interval' })\n }\n }\n\n throw error\n }\n}\n"],"names":["crypto","status","httpStatus","buildAfterOperation","buildBeforeOperation","APIError","Forbidden","appendNonTrashedFilter","commitTransaction","formatAdminURL","getRequestOrigin","initTransaction","isolateObjectProperty","killTransaction","getLoginOptions","forgotPasswordOperation","incomingArgs","loginWithUsername","collection","config","auth","data","overrideAccess","canLoginWithEmail","canLoginWithUsername","sanitizedEmail","email","toLowerCase","trim","sanitizedUsername","username","args","hasSentEmail","releaseRequestInterval","disableLocalStrategy","req","t","BAD_REQUEST","shouldCommit","operation","collectionConfig","disableEmail","expiration","payload","minRequestInterval","forgotPassword","token","randomBytes","toString","whereConstraint","equals","enableTrash","trash","where","now","Date","resetPasswordExpiration","toISOString","user","requestedAt","reservationReq","transactionID","undefined","db","updateOne","slug","resetPasswordRequestedAt","options","atomic","and","or","exists","less_than_equal","userID","id","findOne","update","resetPasswordToken","serverURL","forgotURL","adminRoute","routes","admin","path","reset","html","generateEmailHTML","subject","generateEmailSubject","sendEmail","from","defaultFromName","defaultFromAddress","to","hooks","afterForgotPassword","length","hook","context","result","error","err","logger","msg"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/auth/operations/local/auth.ts"],"sourcesContent":["import type { Payload } from '../../../index.js'\nimport type { AuthArgs, AuthResult } from '../auth.js'\n\nimport { createLocalReq } from '../../../utilities/createLocalReq.js'\nimport { auth as authOperation } from '../auth.js'\n\nexport const authLocal = async (payload: Payload, options: AuthArgs): Promise<AuthResult> => {\n const { headers, req } = options\n\n return await authOperation({\n canSetHeaders: Boolean(options.canSetHeaders),\n headers,\n req: await createLocalReq({ req }, payload),\n })\n}\n"],"names":["createLocalReq","auth","authOperation","authLocal","payload","options","headers","req","canSetHeaders","Boolean"],"mappings":"AAGA,SAASA,cAAc,QAAQ,uCAAsC;AACrE,SAASC,QAAQC,aAAa,QAAQ,aAAY;AAElD,OAAO,MAAMC,YAAY,OAAOC,SAAkBC;IAChD,MAAM,EAAEC,OAAO,EAAEC,GAAG,EAAE,GAAGF;IAEzB,OAAO,MAAMH,cAAc;QACzBM,eAAeC,QAAQJ,QAAQG,aAAa;QAC5CF;QACAC,KAAK,MAAMP,eAAe;YAAEO;
|
|
1
|
+
{"version":3,"sources":["../../../../src/auth/operations/local/auth.ts"],"sourcesContent":["import type { Payload } from '../../../index.js'\nimport type { AuthArgs, AuthResult } from '../auth.js'\n\nimport { createLocalReq } from '../../../utilities/createLocalReq.js'\nimport { auth as authOperation } from '../auth.js'\n\nexport const authLocal = async (payload: Payload, options: AuthArgs): Promise<AuthResult> => {\n const { headers, req } = options\n\n return await authOperation({\n canSetHeaders: Boolean(options.canSetHeaders),\n headers,\n req: await createLocalReq({ req: req ?? { headers } }, payload),\n })\n}\n"],"names":["createLocalReq","auth","authOperation","authLocal","payload","options","headers","req","canSetHeaders","Boolean"],"mappings":"AAGA,SAASA,cAAc,QAAQ,uCAAsC;AACrE,SAASC,QAAQC,aAAa,QAAQ,aAAY;AAElD,OAAO,MAAMC,YAAY,OAAOC,SAAkBC;IAChD,MAAM,EAAEC,OAAO,EAAEC,GAAG,EAAE,GAAGF;IAEzB,OAAO,MAAMH,cAAc;QACzBM,eAAeC,QAAQJ,QAAQG,aAAa;QAC5CF;QACAC,KAAK,MAAMP,eAAe;YAAEO,KAAKA,OAAO;gBAAED;YAAQ;QAAE,GAAGF;IACzD;AACF,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gCAAgC,EAChC,UAAU,EACV,sBAAsB,EACvB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAa,MAAM,gBAAgB,CAAA;AACnE,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/auth/operations/login.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gCAAgC,EAChC,UAAU,EACV,sBAAsB,EACvB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAa,MAAM,gBAAgB,CAAA;AACnE,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,sBAAsB,CAAA;AAyBjE,MAAM,MAAM,WAAW,CAAC,KAAK,SAAS,kBAAkB,IAAI;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,sBAAsB,CAAC,KAAK,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,kBAAkB,IAAI;IACxD,UAAU,EAAE,UAAU,CAAA;IACtB,IAAI,EAAE,gCAAgC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAA;IACtD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,GAAG,EAAE,cAAc,CAAA;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED,KAAK,wBAAwB,CAAC,KAAK,SAAS,kBAAkB,IAAI;IAChE,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,GAAG,EAAE,cAAc,CAAA;IACnB,IAAI,EAAE,sBAAsB,CAAC,KAAK,CAAC,CAAA;CACpC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,SAAS,kBAAkB,yCAIlE,wBAAwB,CAAC,KAAK,CAAC,SAQjC,CAAA;AAED,eAAO,MAAM,cAAc,GAAU,KAAK,SAAS,kBAAkB,gBACrD,SAAS,CAAC,KAAK,CAAC,KAC7B,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAuW5B,CAAA"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js';
|
|
2
2
|
import { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js';
|
|
3
3
|
import { AuthenticationError, LockedAuth, UnverifiedEmail, ValidationError } from '../../errors/index.js';
|
|
4
|
-
import { afterRead } from '../../fields/hooks/afterRead/index.js';
|
|
5
4
|
import { commitTransaction, Forbidden, initTransaction } from '../../index.js';
|
|
6
5
|
import { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js';
|
|
7
6
|
import { killTransaction } from '../../utilities/killTransaction.js';
|
|
8
7
|
import { sanitizeInternalFields } from '../../utilities/sanitizeInternalFields.js';
|
|
8
|
+
import { applyUserReadAccess } from '../applyUserReadAccess.js';
|
|
9
9
|
import { getFieldsToSign } from '../getFieldsToSign.js';
|
|
10
10
|
import { getLoginOptions } from '../getLoginOptions.js';
|
|
11
11
|
import { isUserLocked } from '../isUserLocked.js';
|
|
12
12
|
import { jwtSign } from '../jwt.js';
|
|
13
13
|
import { addSessionToUser, revokeSession } from '../sessions.js';
|
|
14
14
|
import { authenticateLocalStrategy } from '../strategies/local/authenticate.js';
|
|
15
|
+
import { generatePasswordSaltHash } from '../strategies/local/generatePasswordSaltHash.js';
|
|
15
16
|
import { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts.js';
|
|
16
17
|
import { resetLoginAttempts } from '../strategies/local/resetLoginAttempts.js';
|
|
17
18
|
/**
|
|
@@ -40,7 +41,7 @@ export const loginOperation = async (incomingArgs)=>{
|
|
|
40
41
|
operation: 'login',
|
|
41
42
|
overrideAccess: args.overrideAccess
|
|
42
43
|
});
|
|
43
|
-
const { collection: { config: collectionConfig }, data, depth, overrideAccess = false, req, req: {
|
|
44
|
+
const { collection: { config: collectionConfig }, data, depth, overrideAccess = false, req, req: { payload, payload: { secret } }, showHiddenFields } = args;
|
|
44
45
|
// /////////////////////////////////////
|
|
45
46
|
// Login
|
|
46
47
|
// /////////////////////////////////////
|
|
@@ -159,6 +160,8 @@ export const loginOperation = async (incomingArgs)=>{
|
|
|
159
160
|
});
|
|
160
161
|
user.collection = collectionConfig.slug;
|
|
161
162
|
user._strategy = 'local-jwt';
|
|
163
|
+
const authenticatedHash = user.hash;
|
|
164
|
+
const authenticatedSalt = user.salt;
|
|
162
165
|
const authResult = await authenticateLocalStrategy({
|
|
163
166
|
doc: user,
|
|
164
167
|
password
|
|
@@ -229,6 +232,45 @@ export const loginOperation = async (incomingArgs)=>{
|
|
|
229
232
|
if (sid) {
|
|
230
233
|
fieldsToSignArgs.sid = sid;
|
|
231
234
|
}
|
|
235
|
+
if (authResult.shouldUpdatePasswordHash && typeof authenticatedHash === 'string' && typeof authenticatedSalt === 'string') {
|
|
236
|
+
try {
|
|
237
|
+
const { hash, salt } = await generatePasswordSaltHash({
|
|
238
|
+
collection: collectionConfig,
|
|
239
|
+
isPasswordAuthenticated: true,
|
|
240
|
+
password,
|
|
241
|
+
req
|
|
242
|
+
});
|
|
243
|
+
await payload.db.updateOne({
|
|
244
|
+
collection: collectionConfig.slug,
|
|
245
|
+
data: {
|
|
246
|
+
hash,
|
|
247
|
+
salt
|
|
248
|
+
},
|
|
249
|
+
req,
|
|
250
|
+
select: {
|
|
251
|
+
id: true
|
|
252
|
+
},
|
|
253
|
+
where: {
|
|
254
|
+
id: {
|
|
255
|
+
equals: user.id
|
|
256
|
+
},
|
|
257
|
+
hash: {
|
|
258
|
+
equals: authenticatedHash
|
|
259
|
+
},
|
|
260
|
+
salt: {
|
|
261
|
+
equals: authenticatedSalt
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
} catch (err) {
|
|
266
|
+
// Rehashing is opportunistic and is retried on the next login, so a failure here
|
|
267
|
+
// must not reject an otherwise valid login or discard the session already created
|
|
268
|
+
payload.logger.error({
|
|
269
|
+
err,
|
|
270
|
+
msg: 'Failed to update the stored password hash'
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
232
274
|
const fieldsToSign = getFieldsToSign(fieldsToSignArgs);
|
|
233
275
|
if (maxLoginAttemptsEnabled) {
|
|
234
276
|
await resetLoginAttempts({
|
|
@@ -274,38 +316,18 @@ export const loginOperation = async (incomingArgs)=>{
|
|
|
274
316
|
// /////////////////////////////////////
|
|
275
317
|
// afterRead - Fields
|
|
276
318
|
// /////////////////////////////////////
|
|
277
|
-
|
|
319
|
+
const userWithReadAccess = await applyUserReadAccess({
|
|
278
320
|
collection: collectionConfig,
|
|
279
|
-
context: req.context,
|
|
280
321
|
depth: depth,
|
|
281
|
-
doc: user,
|
|
282
|
-
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
|
283
|
-
draft: undefined,
|
|
284
|
-
fallbackLocale: fallbackLocale,
|
|
285
|
-
global: null,
|
|
286
|
-
locale: locale,
|
|
287
322
|
overrideAccess,
|
|
288
323
|
req,
|
|
289
|
-
showHiddenFields: showHiddenFields
|
|
324
|
+
showHiddenFields: showHiddenFields,
|
|
325
|
+
user
|
|
290
326
|
});
|
|
291
|
-
// /////////////////////////////////////
|
|
292
|
-
// afterRead - Collection
|
|
293
|
-
// /////////////////////////////////////
|
|
294
|
-
if (collectionConfig.hooks?.afterRead?.length) {
|
|
295
|
-
for (const hook of collectionConfig.hooks.afterRead){
|
|
296
|
-
user = await hook({
|
|
297
|
-
collection: args.collection?.config,
|
|
298
|
-
context: req.context,
|
|
299
|
-
doc: user,
|
|
300
|
-
overrideAccess,
|
|
301
|
-
req
|
|
302
|
-
}) || user;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
327
|
let result = {
|
|
306
328
|
exp,
|
|
307
329
|
token,
|
|
308
|
-
user
|
|
330
|
+
user: userWithReadAccess
|
|
309
331
|
};
|
|
310
332
|
// /////////////////////////////////////
|
|
311
333
|
// afterOperation - Collection
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/operations/login.ts"],"sourcesContent":["import type {\n AuthOperationsFromCollectionSlug,\n Collection,\n DataFromCollectionSlug,\n} from '../../collections/config/types.js'\nimport type { AuthCollectionSlug, TypedUser } from '../../index.js'\nimport type { PayloadRequest, Where } from '../../types/index.js'\n\nimport { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js'\nimport {\n AuthenticationError,\n LockedAuth,\n UnverifiedEmail,\n ValidationError,\n} from '../../errors/index.js'\nimport { afterRead } from '../../fields/hooks/afterRead/index.js'\nimport { commitTransaction, Forbidden, initTransaction } from '../../index.js'\nimport { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { sanitizeInternalFields } from '../../utilities/sanitizeInternalFields.js'\nimport { getFieldsToSign } from '../getFieldsToSign.js'\nimport { getLoginOptions } from '../getLoginOptions.js'\nimport { isUserLocked } from '../isUserLocked.js'\nimport { jwtSign } from '../jwt.js'\nimport { addSessionToUser, revokeSession } from '../sessions.js'\nimport { authenticateLocalStrategy } from '../strategies/local/authenticate.js'\nimport { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts.js'\nimport { resetLoginAttempts } from '../strategies/local/resetLoginAttempts.js'\n\nexport type LoginResult<TSlug extends AuthCollectionSlug> = {\n exp?: number\n token?: string\n user?: DataFromCollectionSlug<TSlug>\n}\n\nexport type Arguments<TSlug extends AuthCollectionSlug> = {\n collection: Collection\n data: AuthOperationsFromCollectionSlug<TSlug>['login']\n depth?: number\n overrideAccess?: boolean\n req: PayloadRequest\n showHiddenFields?: boolean\n}\n\ntype CheckLoginPermissionArgs<TSlug extends AuthCollectionSlug> = {\n loggingInWithUsername?: boolean\n req: PayloadRequest\n user: DataFromCollectionSlug<TSlug>\n}\n\n/**\n * Throws an error if the user is locked or does not exist.\n * This does not check the login attempts, only the lock status. Whoever increments login attempts\n * is responsible for locking the user properly, not whoever checks the login permission.\n */\nexport const checkLoginPermission = <TSlug extends AuthCollectionSlug>({\n loggingInWithUsername,\n req,\n user,\n}: CheckLoginPermissionArgs<TSlug>) => {\n if (!user) {\n throw new AuthenticationError(req.t, Boolean(loggingInWithUsername))\n }\n\n if (isUserLocked(new Date(user.lockUntil))) {\n throw new LockedAuth(req.t)\n }\n}\n\nexport const loginOperation = async <TSlug extends AuthCollectionSlug>(\n incomingArgs: Arguments<TSlug>,\n): Promise<LoginResult<TSlug>> => {\n let args = incomingArgs\n\n if (args.collection.config.auth.disableLocalStrategy) {\n throw new Forbidden(args.req.t)\n }\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'login',\n overrideAccess: args.overrideAccess!,\n })\n\n const {\n collection: { config: collectionConfig },\n data,\n depth,\n overrideAccess = false,\n req,\n req: {\n fallbackLocale,\n locale,\n payload,\n payload: { secret },\n },\n showHiddenFields,\n } = args\n\n // /////////////////////////////////////\n // Login\n // /////////////////////////////////////\n\n const { email: unsanitizedEmail, password } = data\n const loginWithUsername = collectionConfig.auth.loginWithUsername\n\n const sanitizedEmail =\n typeof unsanitizedEmail === 'string' ? unsanitizedEmail.toLowerCase().trim() : null\n const sanitizedUsername =\n 'username' in data && typeof data?.username === 'string'\n ? data.username.toLowerCase().trim()\n : null\n\n const { canLoginWithEmail, canLoginWithUsername } = getLoginOptions(loginWithUsername)\n\n // cannot login with email, did not provide username\n if (!canLoginWithEmail && !sanitizedUsername) {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [{ message: req.i18n.t('validation:required'), path: 'username' }],\n })\n }\n\n // cannot login with username, did not provide email\n if (!canLoginWithUsername && !sanitizedEmail) {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [{ message: req.i18n.t('validation:required'), path: 'email' }],\n })\n }\n\n // can login with either email or username, did not provide either\n if (!sanitizedUsername && !sanitizedEmail) {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [\n { message: req.i18n.t('validation:required'), path: 'email' },\n { message: req.i18n.t('validation:required'), path: 'username' },\n ],\n })\n }\n\n // did not provide password for login\n if (typeof password !== 'string' || password.trim() === '') {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [{ message: req.i18n.t('validation:required'), path: 'password' }],\n })\n }\n\n let whereConstraint: Where = {}\n const emailConstraint: Where = {\n email: {\n equals: sanitizedEmail,\n },\n }\n const usernameConstraint: Where = {\n username: {\n equals: sanitizedUsername,\n },\n }\n\n if (canLoginWithEmail && canLoginWithUsername && (sanitizedUsername || sanitizedEmail)) {\n if (sanitizedUsername) {\n whereConstraint = {\n or: [\n usernameConstraint,\n {\n email: {\n equals: sanitizedUsername,\n },\n },\n ],\n }\n } else {\n whereConstraint = {\n or: [\n emailConstraint,\n {\n username: {\n equals: sanitizedEmail,\n },\n },\n ],\n }\n }\n } else if (canLoginWithEmail && sanitizedEmail) {\n whereConstraint = emailConstraint\n } else if (canLoginWithUsername && sanitizedUsername) {\n whereConstraint = usernameConstraint\n }\n\n // Exclude trashed users\n whereConstraint = appendNonTrashedFilter({\n enableTrash: collectionConfig.trash,\n trash: false,\n where: whereConstraint,\n })\n\n let user = (await payload.db.findOne<TypedUser>({\n collection: collectionConfig.slug,\n req,\n where: whereConstraint,\n })) as TypedUser\n\n checkLoginPermission({\n loggingInWithUsername: Boolean(canLoginWithUsername && sanitizedUsername),\n req,\n user,\n })\n\n user.collection = collectionConfig.slug\n user._strategy = 'local-jwt'\n\n const authResult = await authenticateLocalStrategy({ doc: user, password })\n user = sanitizeInternalFields(user)\n\n const maxLoginAttemptsEnabled = args.collection.config.auth.maxLoginAttempts > 0\n\n if (!authResult) {\n if (maxLoginAttemptsEnabled) {\n await incrementLoginAttempts({\n collection: collectionConfig,\n payload: req.payload,\n user,\n })\n\n // Re-check login permissions and max attempts after incrementing attempts, in case parallel updates occurred\n checkLoginPermission({\n loggingInWithUsername: Boolean(canLoginWithUsername && sanitizedUsername),\n req,\n user,\n })\n }\n\n throw new AuthenticationError(req.t)\n }\n\n if (collectionConfig.auth.verify && user._verified === false) {\n throw new UnverifiedEmail({ t: req.t })\n }\n\n // Authentication successful - start transaction for remaining operations\n const shouldCommit = await initTransaction(args.req)\n let sid: string | undefined\n\n try {\n /*\n * Correct password accepted - re‑check that the account didn't\n * get locked by parallel bad attempts in the meantime.\n */\n if (maxLoginAttemptsEnabled) {\n const { lockUntil, loginAttempts } = (await payload.db.findOne<TypedUser>({\n collection: collectionConfig.slug,\n req,\n select: {\n lockUntil: true,\n loginAttempts: true,\n },\n where: { id: { equals: user.id } },\n }))!\n\n user.lockUntil = lockUntil\n user.loginAttempts = loginAttempts\n\n checkLoginPermission({\n req,\n user,\n })\n }\n\n const fieldsToSignArgs: Parameters<typeof getFieldsToSign>[0] = {\n collectionConfig,\n email: sanitizedEmail!,\n user,\n }\n\n const session = await addSessionToUser({\n collectionConfig,\n payload,\n req,\n user,\n })\n sid = session.sid\n\n if (sid) {\n fieldsToSignArgs.sid = sid\n }\n\n const fieldsToSign = getFieldsToSign(fieldsToSignArgs)\n\n if (maxLoginAttemptsEnabled) {\n await resetLoginAttempts({\n collection: collectionConfig,\n doc: user,\n payload: req.payload,\n req,\n })\n }\n\n // /////////////////////////////////////\n // beforeLogin - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.beforeLogin?.length) {\n for (const hook of collectionConfig.hooks.beforeLogin) {\n user =\n (await hook({\n collection: args.collection?.config,\n context: args.req.context,\n req: args.req,\n user,\n })) || user\n }\n }\n\n const { exp, token } = await jwtSign({\n fieldsToSign,\n secret,\n tokenExpiration: collectionConfig.auth.tokenExpiration,\n })\n\n req.user = user\n\n // /////////////////////////////////////\n // afterLogin - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterLogin?.length) {\n for (const hook of collectionConfig.hooks.afterLogin) {\n user =\n (await hook({\n collection: args.collection?.config,\n context: args.req.context,\n req: args.req,\n token,\n user,\n })) || user\n }\n }\n\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n user = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: depth!,\n doc: user,\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n draft: undefined,\n fallbackLocale: fallbackLocale!,\n global: null,\n locale: locale!,\n overrideAccess,\n req,\n showHiddenFields: showHiddenFields!,\n })\n\n // /////////////////////////////////////\n // afterRead - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterRead?.length) {\n for (const hook of collectionConfig.hooks.afterRead) {\n user =\n (await hook({\n collection: args.collection?.config,\n context: req.context,\n doc: user,\n overrideAccess,\n req,\n })) || user\n }\n }\n\n let result: LoginResult<TSlug> = {\n exp,\n token,\n user,\n }\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n result = await buildAfterOperation({\n args,\n collection: args.collection?.config,\n operation: 'login',\n overrideAccess: args.overrideAccess!,\n result,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n // /////////////////////////////////////\n // Return results\n // /////////////////////////////////////\n\n return result\n } catch (error: unknown) {\n if (sid) {\n await revokeSession({\n collectionConfig,\n payload,\n req,\n sid,\n user,\n })\n }\n await killTransaction(args.req)\n throw error\n }\n}\n"],"names":["buildAfterOperation","buildBeforeOperation","AuthenticationError","LockedAuth","UnverifiedEmail","ValidationError","afterRead","commitTransaction","Forbidden","initTransaction","appendNonTrashedFilter","killTransaction","sanitizeInternalFields","getFieldsToSign","getLoginOptions","isUserLocked","jwtSign","addSessionToUser","revokeSession","authenticateLocalStrategy","incrementLoginAttempts","resetLoginAttempts","checkLoginPermission","loggingInWithUsername","req","user","t","Boolean","Date","lockUntil","loginOperation","incomingArgs","args","collection","config","auth","disableLocalStrategy","operation","overrideAccess","collectionConfig","data","depth","fallbackLocale","locale","payload","secret","showHiddenFields","email","unsanitizedEmail","password","loginWithUsername","sanitizedEmail","toLowerCase","trim","sanitizedUsername","username","canLoginWithEmail","canLoginWithUsername","slug","errors","message","i18n","path","whereConstraint","emailConstraint","equals","usernameConstraint","or","enableTrash","trash","where","db","findOne","_strategy","authResult","doc","maxLoginAttemptsEnabled","maxLoginAttempts","verify","_verified","shouldCommit","sid","loginAttempts","select","id","fieldsToSignArgs","session","fieldsToSign","hooks","beforeLogin","length","hook","context","exp","token","tokenExpiration","afterLogin","draft","undefined","global","result","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/operations/login.ts"],"sourcesContent":["import type {\n AuthOperationsFromCollectionSlug,\n Collection,\n DataFromCollectionSlug,\n} from '../../collections/config/types.js'\nimport type { AuthCollectionSlug, TypedUser } from '../../index.js'\nimport type { PayloadRequest, Where } from '../../types/index.js'\n\nimport { buildAfterOperation } from '../../collections/operations/utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from '../../collections/operations/utilities/buildBeforeOperation.js'\nimport {\n AuthenticationError,\n LockedAuth,\n UnverifiedEmail,\n ValidationError,\n} from '../../errors/index.js'\nimport { commitTransaction, Forbidden, initTransaction } from '../../index.js'\nimport { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { sanitizeInternalFields } from '../../utilities/sanitizeInternalFields.js'\nimport { applyUserReadAccess } from '../applyUserReadAccess.js'\nimport { getFieldsToSign } from '../getFieldsToSign.js'\nimport { getLoginOptions } from '../getLoginOptions.js'\nimport { isUserLocked } from '../isUserLocked.js'\nimport { jwtSign } from '../jwt.js'\nimport { addSessionToUser, revokeSession } from '../sessions.js'\nimport { authenticateLocalStrategy } from '../strategies/local/authenticate.js'\nimport { generatePasswordSaltHash } from '../strategies/local/generatePasswordSaltHash.js'\nimport { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts.js'\nimport { resetLoginAttempts } from '../strategies/local/resetLoginAttempts.js'\n\nexport type LoginResult<TSlug extends AuthCollectionSlug> = {\n exp?: number\n token?: string\n user?: DataFromCollectionSlug<TSlug>\n}\n\nexport type Arguments<TSlug extends AuthCollectionSlug> = {\n collection: Collection\n data: AuthOperationsFromCollectionSlug<TSlug>['login']\n depth?: number\n overrideAccess?: boolean\n req: PayloadRequest\n showHiddenFields?: boolean\n}\n\ntype CheckLoginPermissionArgs<TSlug extends AuthCollectionSlug> = {\n loggingInWithUsername?: boolean\n req: PayloadRequest\n user: DataFromCollectionSlug<TSlug>\n}\n\n/**\n * Throws an error if the user is locked or does not exist.\n * This does not check the login attempts, only the lock status. Whoever increments login attempts\n * is responsible for locking the user properly, not whoever checks the login permission.\n */\nexport const checkLoginPermission = <TSlug extends AuthCollectionSlug>({\n loggingInWithUsername,\n req,\n user,\n}: CheckLoginPermissionArgs<TSlug>) => {\n if (!user) {\n throw new AuthenticationError(req.t, Boolean(loggingInWithUsername))\n }\n\n if (isUserLocked(new Date(user.lockUntil))) {\n throw new LockedAuth(req.t)\n }\n}\n\nexport const loginOperation = async <TSlug extends AuthCollectionSlug>(\n incomingArgs: Arguments<TSlug>,\n): Promise<LoginResult<TSlug>> => {\n let args = incomingArgs\n\n if (args.collection.config.auth.disableLocalStrategy) {\n throw new Forbidden(args.req.t)\n }\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'login',\n overrideAccess: args.overrideAccess!,\n })\n\n const {\n collection: { config: collectionConfig },\n data,\n depth,\n overrideAccess = false,\n req,\n req: {\n payload,\n payload: { secret },\n },\n showHiddenFields,\n } = args\n\n // /////////////////////////////////////\n // Login\n // /////////////////////////////////////\n\n const { email: unsanitizedEmail, password } = data\n const loginWithUsername = collectionConfig.auth.loginWithUsername\n\n const sanitizedEmail =\n typeof unsanitizedEmail === 'string' ? unsanitizedEmail.toLowerCase().trim() : null\n const sanitizedUsername =\n 'username' in data && typeof data?.username === 'string'\n ? data.username.toLowerCase().trim()\n : null\n\n const { canLoginWithEmail, canLoginWithUsername } = getLoginOptions(loginWithUsername)\n\n // cannot login with email, did not provide username\n if (!canLoginWithEmail && !sanitizedUsername) {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [{ message: req.i18n.t('validation:required'), path: 'username' }],\n })\n }\n\n // cannot login with username, did not provide email\n if (!canLoginWithUsername && !sanitizedEmail) {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [{ message: req.i18n.t('validation:required'), path: 'email' }],\n })\n }\n\n // can login with either email or username, did not provide either\n if (!sanitizedUsername && !sanitizedEmail) {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [\n { message: req.i18n.t('validation:required'), path: 'email' },\n { message: req.i18n.t('validation:required'), path: 'username' },\n ],\n })\n }\n\n // did not provide password for login\n if (typeof password !== 'string' || password.trim() === '') {\n throw new ValidationError({\n collection: collectionConfig.slug,\n errors: [{ message: req.i18n.t('validation:required'), path: 'password' }],\n })\n }\n\n let whereConstraint: Where = {}\n const emailConstraint: Where = {\n email: {\n equals: sanitizedEmail,\n },\n }\n const usernameConstraint: Where = {\n username: {\n equals: sanitizedUsername,\n },\n }\n\n if (canLoginWithEmail && canLoginWithUsername && (sanitizedUsername || sanitizedEmail)) {\n if (sanitizedUsername) {\n whereConstraint = {\n or: [\n usernameConstraint,\n {\n email: {\n equals: sanitizedUsername,\n },\n },\n ],\n }\n } else {\n whereConstraint = {\n or: [\n emailConstraint,\n {\n username: {\n equals: sanitizedEmail,\n },\n },\n ],\n }\n }\n } else if (canLoginWithEmail && sanitizedEmail) {\n whereConstraint = emailConstraint\n } else if (canLoginWithUsername && sanitizedUsername) {\n whereConstraint = usernameConstraint\n }\n\n // Exclude trashed users\n whereConstraint = appendNonTrashedFilter({\n enableTrash: collectionConfig.trash,\n trash: false,\n where: whereConstraint,\n })\n\n let user = (await payload.db.findOne<TypedUser>({\n collection: collectionConfig.slug,\n req,\n where: whereConstraint,\n })) as TypedUser\n\n checkLoginPermission({\n loggingInWithUsername: Boolean(canLoginWithUsername && sanitizedUsername),\n req,\n user,\n })\n\n user.collection = collectionConfig.slug\n user._strategy = 'local-jwt'\n\n const authenticatedHash = user.hash\n const authenticatedSalt = user.salt\n const authResult = await authenticateLocalStrategy({ doc: user, password })\n user = sanitizeInternalFields(user)\n\n const maxLoginAttemptsEnabled = args.collection.config.auth.maxLoginAttempts > 0\n\n if (!authResult) {\n if (maxLoginAttemptsEnabled) {\n await incrementLoginAttempts({\n collection: collectionConfig,\n payload: req.payload,\n user,\n })\n\n // Re-check login permissions and max attempts after incrementing attempts, in case parallel updates occurred\n checkLoginPermission({\n loggingInWithUsername: Boolean(canLoginWithUsername && sanitizedUsername),\n req,\n user,\n })\n }\n\n throw new AuthenticationError(req.t)\n }\n\n if (collectionConfig.auth.verify && user._verified === false) {\n throw new UnverifiedEmail({ t: req.t })\n }\n\n // Authentication successful - start transaction for remaining operations\n const shouldCommit = await initTransaction(args.req)\n let sid: string | undefined\n\n try {\n /*\n * Correct password accepted - re‑check that the account didn't\n * get locked by parallel bad attempts in the meantime.\n */\n if (maxLoginAttemptsEnabled) {\n const { lockUntil, loginAttempts } = (await payload.db.findOne<TypedUser>({\n collection: collectionConfig.slug,\n req,\n select: {\n lockUntil: true,\n loginAttempts: true,\n },\n where: { id: { equals: user.id } },\n }))!\n\n user.lockUntil = lockUntil\n user.loginAttempts = loginAttempts\n\n checkLoginPermission({\n req,\n user,\n })\n }\n\n const fieldsToSignArgs: Parameters<typeof getFieldsToSign>[0] = {\n collectionConfig,\n email: sanitizedEmail!,\n user,\n }\n\n const session = await addSessionToUser({\n collectionConfig,\n payload,\n req,\n user,\n })\n sid = session.sid\n\n if (sid) {\n fieldsToSignArgs.sid = sid\n }\n\n if (\n authResult.shouldUpdatePasswordHash &&\n typeof authenticatedHash === 'string' &&\n typeof authenticatedSalt === 'string'\n ) {\n try {\n const { hash, salt } = await generatePasswordSaltHash({\n collection: collectionConfig,\n isPasswordAuthenticated: true,\n password,\n req,\n })\n\n await payload.db.updateOne({\n collection: collectionConfig.slug,\n data: { hash, salt },\n req,\n select: { id: true },\n where: {\n id: { equals: user.id },\n hash: { equals: authenticatedHash },\n salt: { equals: authenticatedSalt },\n },\n })\n } catch (err) {\n // Rehashing is opportunistic and is retried on the next login, so a failure here\n // must not reject an otherwise valid login or discard the session already created\n payload.logger.error({ err, msg: 'Failed to update the stored password hash' })\n }\n }\n\n const fieldsToSign = getFieldsToSign(fieldsToSignArgs)\n\n if (maxLoginAttemptsEnabled) {\n await resetLoginAttempts({\n collection: collectionConfig,\n doc: user,\n payload: req.payload,\n req,\n })\n }\n\n // /////////////////////////////////////\n // beforeLogin - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.beforeLogin?.length) {\n for (const hook of collectionConfig.hooks.beforeLogin) {\n user =\n (await hook({\n collection: args.collection?.config,\n context: args.req.context,\n req: args.req,\n user,\n })) || user\n }\n }\n\n const { exp, token } = await jwtSign({\n fieldsToSign,\n secret,\n tokenExpiration: collectionConfig.auth.tokenExpiration,\n })\n\n req.user = user\n\n // /////////////////////////////////////\n // afterLogin - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterLogin?.length) {\n for (const hook of collectionConfig.hooks.afterLogin) {\n user =\n (await hook({\n collection: args.collection?.config,\n context: args.req.context,\n req: args.req,\n token,\n user,\n })) || user\n }\n }\n\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n const userWithReadAccess = await applyUserReadAccess({\n collection: collectionConfig,\n depth: depth!,\n overrideAccess,\n req,\n showHiddenFields: showHiddenFields!,\n user,\n })\n\n let result: LoginResult<TSlug> = {\n exp,\n token,\n user: userWithReadAccess,\n }\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n result = await buildAfterOperation({\n args,\n collection: args.collection?.config,\n operation: 'login',\n overrideAccess: args.overrideAccess!,\n result,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n // /////////////////////////////////////\n // Return results\n // /////////////////////////////////////\n\n return result\n } catch (error: unknown) {\n if (sid) {\n await revokeSession({\n collectionConfig,\n payload,\n req,\n sid,\n user,\n })\n }\n await killTransaction(args.req)\n throw error\n }\n}\n"],"names":["buildAfterOperation","buildBeforeOperation","AuthenticationError","LockedAuth","UnverifiedEmail","ValidationError","commitTransaction","Forbidden","initTransaction","appendNonTrashedFilter","killTransaction","sanitizeInternalFields","applyUserReadAccess","getFieldsToSign","getLoginOptions","isUserLocked","jwtSign","addSessionToUser","revokeSession","authenticateLocalStrategy","generatePasswordSaltHash","incrementLoginAttempts","resetLoginAttempts","checkLoginPermission","loggingInWithUsername","req","user","t","Boolean","Date","lockUntil","loginOperation","incomingArgs","args","collection","config","auth","disableLocalStrategy","operation","overrideAccess","collectionConfig","data","depth","payload","secret","showHiddenFields","email","unsanitizedEmail","password","loginWithUsername","sanitizedEmail","toLowerCase","trim","sanitizedUsername","username","canLoginWithEmail","canLoginWithUsername","slug","errors","message","i18n","path","whereConstraint","emailConstraint","equals","usernameConstraint","or","enableTrash","trash","where","db","findOne","_strategy","authenticatedHash","hash","authenticatedSalt","salt","authResult","doc","maxLoginAttemptsEnabled","maxLoginAttempts","verify","_verified","shouldCommit","sid","loginAttempts","select","id","fieldsToSignArgs","session","shouldUpdatePasswordHash","isPasswordAuthenticated","updateOne","err","logger","error","msg","fieldsToSign","hooks","beforeLogin","length","hook","context","exp","token","tokenExpiration","afterLogin","userWithReadAccess","result"],"mappings":"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"}
|