Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/server/plugins/engine/components/EmailAddressField.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { type EmailAddressFieldComponent } from '@defra/forms-model'
import joi from 'joi'
import {
preventUnicodeInEmail,

Check failure on line 2 in src/server/plugins/engine/components/EmailAddressField.ts

View workflow job for this annotation

GitHub Actions / Build (Node 22)

Module '"@defra/forms-model"' has no exported member 'preventUnicodeInEmail'.

Check failure on line 2 in src/server/plugins/engine/components/EmailAddressField.ts

View workflow job for this annotation

GitHub Actions / Build (Node 23)

Module '"@defra/forms-model"' has no exported member 'preventUnicodeInEmail'.

Check failure on line 2 in src/server/plugins/engine/components/EmailAddressField.ts

View workflow job for this annotation

GitHub Actions / Build (Node 24)

Module '"@defra/forms-model"' has no exported member 'preventUnicodeInEmail'.
type EmailAddressFieldComponent
} from '@defra/forms-model'
import joi, { type CustomHelpers } from 'joi'

import { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'
import { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'
Expand All @@ -20,7 +23,15 @@

const { options } = def

let formSchema = joi.string().email().trim().label(this.label).required()
let formSchema = joi
.string()
.trim()
.email()
.custom((value, helpers: CustomHelpers<string>) =>
preventUnicodeInEmail(value, helpers)
)
.label(this.label)
.required()

if (options.required === false) {
formSchema = formSchema.allow('')
Expand Down Expand Up @@ -69,7 +80,8 @@
return {
baseErrors: [
{ type: 'required', template: messageTemplate.required },
{ type: 'format', template: messageTemplate.format }
{ type: 'format', template: messageTemplate.format },
{ type: 'unicode', template: messageTemplate.unicode }
],
advancedSettingsErrors: []
}
Expand Down
2 changes: 1 addition & 1 deletion src/server/plugins/engine/pageControllers/helpers/state.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ControllerType, getHiddenFields } from '@defra/forms-model'
import { validate as isValidUUID } from 'uuid'

import { getCacheService } from '~/src/server/plugins/engine/helpers.js'
import {
Expand All @@ -16,6 +15,7 @@ import {
} from '~/src/server/plugins/engine/types.js'
import { type FormQuery } from '~/src/server/routes/types.js'
import { type Services } from '~/src/server/types.js'
import { isValidUUID } from '~/src/server/utils/utils.js'

const GUID_LENGTH = 36

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const messageTemplate: Record<string, JoiExpression> = {
'Enter {{lowerFirst(#label)}} in the correct format',
opts
) as JoiExpression,
unicode: '{{#label}} includes invalid characters, for example, long dashes',
number: '{{#label}} must be a number',
numberPrecision: '{{#label}} must have {{#limit}} or fewer decimal places',
numberInteger: '{{#label}} must be a whole number',
Expand All @@ -69,6 +70,7 @@ export const messages: LanguageMessagesExt = {
'string.empty': messageTemplate.required,
'string.max': messageTemplate.max,
'string.email': messageTemplate.format,
'string.unicode': messageTemplate.unicode,
'string.pattern.base': messageTemplate.pattern,
'string.maxWords': messageTemplate.maxWords,

Expand Down
11 changes: 11 additions & 0 deletions src/server/utils/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getTraceId } from '@defra/hapi-tracing'
import Joi from 'joi'

import { config } from '~/src/config/index.js'

Expand All @@ -22,3 +23,13 @@ export function applyTraceHeaders(

return existingHeaders ? Object.assign(existingHeaders, headers) : headers
}

/**
* Validates if a string conforms to the uuid structure
* @param {string} str
* @returns
*/
export function isValidUUID(str) {
const { error } = Joi.string().uuid().validate(str)
return error === undefined
}
17 changes: 16 additions & 1 deletion src/server/utils/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getTraceId } from '@defra/hapi-tracing'

import { config } from '~/src/config/index.js'
import { applyTraceHeaders } from '~/src/server/utils/utils.js'
import { applyTraceHeaders, isValidUUID } from '~/src/server/utils/utils.js'

jest.mock('@defra/hapi-tracing')

Expand Down Expand Up @@ -51,4 +51,19 @@ describe('Header helper functions', () => {

expect(result).toBe(existingHeaders)
})

it.each([
{ uuid: '1f457a37-7b99-452e-8324-df9e041abff2', valid: true },
{ uuid: '0c9a2690-9a0c-4a2c-98d7-e9ef95615ac9', valid: true },
{ uuid: 'f223de3b-5ae5-44b2-8cee-ea8439adc335', valid: true },
{ uuid: '82ecc90c-bc47-4ec5-80af-1a9fc1c4c08c', valid: true },
{ uuid: 'd99ff582-ecce-474f-a44b-bc5961d977c5', valid: true },
{ uuid: '7afffc8a-81ab-4aa6-a8f5-ecf6a600a781', valid: true },
{ uuid: '7afffc8a81ab4aa6a8f5ecf6a600a781', valid: true },
{ uuid: '', valid: false },
{ uuid: 'uuid', valid: false },
{ uuid: 'h4f84ef8-b5e1-4544-94aa-1b671d50d8cb', valid: false }
])('should validate uuid appropriately %s', ({ uuid, valid }) => {
expect(isValidUUID(uuid)).toBe(valid)
})
})
Loading