diff --git a/package-lock.json b/package-lock.json index a56228335..b14476bc1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "license": "SEE LICENSE IN LICENSE", "dependencies": { "@aws-sdk/client-sns": "^3.997.0", - "@defra/forms-engine-plugin": "^4.5.6", - "@defra/forms-model": "^3.0.635", + "@defra/forms-engine-plugin": "^4.6.0", + "@defra/forms-model": "^3.0.644", "@defra/hapi-tracing": "^1.30.0", "@elastic/ecs-pino-format": "^1.5.0", "@hapi/boom": "^10.0.1", @@ -4043,13 +4043,13 @@ } }, "node_modules/@defra/forms-engine-plugin": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@defra/forms-engine-plugin/-/forms-engine-plugin-4.5.6.tgz", - "integrity": "sha512-xuG3LnszavdenRylVNVm3JJ6U1cEdQG+ZZmWh1VjMinqDsR1RVj6gxMwlEJpUv0SyhyuLZw0Nq1oR/0+ApMBPQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@defra/forms-engine-plugin/-/forms-engine-plugin-4.6.0.tgz", + "integrity": "sha512-DdxRNbFugUc1Fmo0/yhaHLYpRqNXJJayZrm5memuDcFxntpAaWyqvot7oyut+7EhrRpBDIWMpwWvQwlejMgspQ==", "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { - "@defra/forms-model": "^3.0.637", + "@defra/forms-model": "^3.0.644", "@defra/hapi-tracing": "^1.29.0", "@defra/interactive-map": "^0.0.17-alpha", "@elastic/ecs-pino-format": "^1.5.0", @@ -4158,9 +4158,9 @@ } }, "node_modules/@defra/forms-model": { - "version": "3.0.640", - "resolved": "https://registry.npmjs.org/@defra/forms-model/-/forms-model-3.0.640.tgz", - "integrity": "sha512-Qp4g+/WLnFSL7smhG+8K3HVlJfJ0YA28nHB9/QJMP8DcP3fAl/GCwfQ8m/gfb3uYajTQikynbyt9VhjSFTjcfA==", + "version": "3.0.644", + "resolved": "https://registry.npmjs.org/@defra/forms-model/-/forms-model-3.0.644.tgz", + "integrity": "sha512-JagkRer3CFF3feWmu6NV72rhdPQCOMQ+z8dpPPNs3DzdUL2Pf7PoYixFqSNMkvZKNWG5XPaS8SDtbjvK4IdRXg==", "license": "OGL-UK-3.0", "dependencies": { "@joi/date": "^2.1.1", @@ -18408,9 +18408,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -25411,9 +25411,9 @@ } }, "node_modules/nanoid": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", - "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.7.tgz", + "integrity": "sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==", "funding": [ { "type": "github", @@ -28394,15 +28394,6 @@ "integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==", "license": "ISC" }, - "node_modules/preact": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-8.5.3.tgz", - "integrity": "sha512-O3kKP+1YdgqHOFsZF2a9JVdtqD+RPzCQc3rP+Ualf7V6rmRDchZ9MJbiGTT7LuyqFKZqlHSOyO/oMFmI2lVTsw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", diff --git a/package.json b/package.json index 3b4a76b9f..a6ff5c1d7 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,8 @@ "license": "SEE LICENSE IN LICENSE", "dependencies": { "@aws-sdk/client-sns": "^3.997.0", - "@defra/forms-engine-plugin": "^4.5.6", - "@defra/forms-model": "^3.0.635", + "@defra/forms-engine-plugin": "^4.6.0", + "@defra/forms-model": "^3.0.644", "@defra/hapi-tracing": "^1.30.0", "@elastic/ecs-pino-format": "^1.5.0", "@hapi/boom": "^10.0.1", diff --git a/src/server/models/save-and-exit.js b/src/server/models/save-and-exit.js index 53b681b09..31114c004 100644 --- a/src/server/models/save-and-exit.js +++ b/src/server/models/save-and-exit.js @@ -2,6 +2,8 @@ import { crumbSchema, stateSchema } from '@defra/forms-engine-plugin/schema.js' import { ControllerPath, SecurityQuestionsEnum, + UNICODE_EMAIL_ERROR_MESSAGE, + preventUnicodeInEmail, slugSchema } from '@defra/forms-model' import Joi from 'joi' @@ -243,11 +245,17 @@ export const paramsSchema = Joi.object() export const payloadSchema = Joi.object() .keys({ crumb: crumbSchema, - email: Joi.string().email().required().messages({ - 'string.email': - 'Enter an email address in the correct format, for example, hello@example.com', - '*': 'Enter an email address' - }), + email: Joi.string() + .trim() + .email() + .custom((value, helpers) => preventUnicodeInEmail(value, helpers)) + .required() + .messages({ + 'string.email': + 'Enter an email address in the correct format, for example, hello@example.com', + 'string.unicode': UNICODE_EMAIL_ERROR_MESSAGE, + '*': 'Enter an email address' + }), emailConfirmation: Joi.string() .valid(Joi.ref('email')) .required() diff --git a/src/server/plugins/SummaryPageWithConfirmationEmailController.ts b/src/server/plugins/SummaryPageWithConfirmationEmailController.ts index 2c578ce38..1cae9a45f 100644 --- a/src/server/plugins/SummaryPageWithConfirmationEmailController.ts +++ b/src/server/plugins/SummaryPageWithConfirmationEmailController.ts @@ -14,17 +14,26 @@ import { type FormRequestPayload, type FormResponseToolkit } from '@defra/forms-engine-plugin/types' -import { type GovukField } from '@defra/forms-model' -import Joi from 'joi' +import { preventUnicodeInEmail, type GovukField } from '@defra/forms-model' +import Joi, { type CustomHelpers } from 'joi' export const CONFIRMATION_EMAIL_FIELD_NAME = 'userConfirmationEmailAddress' const schema = Joi.object().keys({ crumb: crumbSchema, action: actionSchema, - userConfirmationEmailAddress: Joi.string().email().allow('').messages({ - '*': 'Enter an email address in the correct format' - }) + userConfirmationEmailAddress: Joi.string() + .email() + .trim() + .custom((value, helpers: CustomHelpers) => + preventUnicodeInEmail(value, helpers) + ) + .allow('') + .messages({ + '*': 'Enter an email address in the correct format', + 'string.unicode': + 'The email address you entered includes invalid characters, for example, long dashes' + }) }) export class SummaryPageWithConfirmationEmailController extends SummaryPageController {