diff --git a/changelog/_14430.txt b/changelog/_14430.txt new file mode 100644 index 0000000000..a69ac0a8b3 --- /dev/null +++ b/changelog/_14430.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: Update KV max_version validation to disallow negative values. +``` diff --git a/ui/app/forms/secrets/engine.ts b/ui/app/forms/secrets/engine.ts index a1dcb4f48d..24b3814cee 100644 --- a/ui/app/forms/secrets/engine.ts +++ b/ui/app/forms/secrets/engine.ts @@ -20,8 +20,12 @@ export default class SecretsEngineForm extends MountForm // path validation is already defined on the MountForm class // add validation for kv max versions this.validations['kv_config.max_versions'] = [ - { type: 'number', message: 'Maximum versions must be a number.' }, + { type: 'number', options: { min: 0 }, message: 'Maximum versions must be a non-negative number.' }, { type: 'length', options: { min: 1, max: 16 }, message: 'You cannot go over 16 characters.' }, + { + validator: (data: SecretsEngineFormData) => !data?.kv_config?.max_versions?.toString().includes('.'), + message: 'Maximum versions must be a whole number.', + }, ]; // add validation for plugin_version when mounting external plugins this.validations['config.plugin_version'] = [ diff --git a/ui/app/forms/secrets/kv.ts b/ui/app/forms/secrets/kv.ts index b7d241b03f..429a35a8d0 100644 --- a/ui/app/forms/secrets/kv.ts +++ b/ui/app/forms/secrets/kv.ts @@ -43,8 +43,12 @@ export default class KvForm extends Form { }, ], max_versions: [ - { type: 'number', message: 'Maximum versions must be a number.' }, + { type: 'number', options: { min: 0 }, message: 'Maximum versions must be a non-negative number.' }, { type: 'length', options: { min: 1, max: 16 }, message: 'You cannot go over 16 characters.' }, + { + validator: ({ max_versions }: KvForm['data']) => !max_versions?.toString().includes('.'), + message: 'Maximum versions must be a whole number.', + }, ], }; diff --git a/ui/app/utils/forms/validators.js b/ui/app/utils/forms/validators.js index 4c37c51796..6be134cbf6 100644 --- a/ui/app/utils/forms/validators.js +++ b/ui/app/utils/forms/validators.js @@ -26,10 +26,12 @@ export const length = (value, { nullable = false, min, max } = {}) => { return nullable; }; -export const number = (value, { nullable = false } = {}) => { +export const number = (value, { nullable = false, min, max } = {}) => { // since 0 is falsy, !value returns true even though 0 is a valid number if (!value && value !== 0) return nullable; - return !isNaN(value); + const underMin = isPresent(min) ? value < min : false; + const overMax = isPresent(max) ? value > max : false; + return !isNaN(value) && !underMin && !overMax; }; export const containsWhiteSpace = (value) => { diff --git a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js index b8963d7c0f..46fe32d4ef 100644 --- a/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/kv-v2-workflow-create-test.js @@ -180,10 +180,17 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook // max_versions validation await fillIn(FORM.inputByAttr('max_versions'), 'seven'); await click(FORM.saveBtn); - assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('Maximum versions must be a number.'); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a non-negative number.'); await fillIn(FORM.inputByAttr('max_versions'), '99999999999999999'); await click(FORM.saveBtn); assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('You cannot go over 16 characters.'); + await fillIn(FORM.inputByAttr('max_versions'), '1.23'); + await click(FORM.saveBtn); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a whole number.'); await fillIn(FORM.inputByAttr('max_versions'), '7'); // Fill in other metadata @@ -436,10 +443,17 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook // max_versions validation await fillIn(FORM.inputByAttr('max_versions'), 'seven'); await click(FORM.saveBtn); - assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('Maximum versions must be a number.'); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a non-negative number.'); await fillIn(FORM.inputByAttr('max_versions'), '99999999999999999'); await click(FORM.saveBtn); assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('You cannot go over 16 characters.'); + await fillIn(FORM.inputByAttr('max_versions'), '1.23'); + await click(FORM.saveBtn); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a whole number.'); await fillIn(FORM.inputByAttr('max_versions'), '7'); // Fill in other metadata @@ -583,10 +597,17 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook // max_versions validation await fillIn(FORM.inputByAttr('max_versions'), 'seven'); await click(FORM.saveBtn); - assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('Maximum versions must be a number.'); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a non-negative number.'); await fillIn(FORM.inputByAttr('max_versions'), '99999999999999999'); await click(FORM.saveBtn); assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('You cannot go over 16 characters.'); + await fillIn(FORM.inputByAttr('max_versions'), '1.23'); + await click(FORM.saveBtn); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a whole number.'); await fillIn(FORM.inputByAttr('max_versions'), '7'); // Fill in other metadata @@ -750,10 +771,17 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook // max_versions validation await fillIn(FORM.inputByAttr('max_versions'), 'seven'); await click(FORM.saveBtn); - assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('Maximum versions must be a number.'); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a non-negative number.'); await fillIn(FORM.inputByAttr('max_versions'), '99999999999999999'); await click(FORM.saveBtn); assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('You cannot go over 16 characters.'); + await fillIn(FORM.inputByAttr('max_versions'), '1.23'); + await click(FORM.saveBtn); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a whole number.'); await fillIn(FORM.inputByAttr('max_versions'), '7'); // Fill in other metadata @@ -976,10 +1004,17 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook // max_versions validation await fillIn(FORM.inputByAttr('max_versions'), 'seven'); await click(FORM.saveBtn); - assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('Maximum versions must be a number.'); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a non-negative number.'); await fillIn(FORM.inputByAttr('max_versions'), '99999999999999999'); await click(FORM.saveBtn); assert.dom(GENERAL.validationErrorByAttr('max_versions')).hasText('You cannot go over 16 characters.'); + await fillIn(FORM.inputByAttr('max_versions'), '1.23'); + await click(FORM.saveBtn); + assert + .dom(GENERAL.validationErrorByAttr('max_versions')) + .hasText('Maximum versions must be a whole number.'); await fillIn(FORM.inputByAttr('max_versions'), '7'); // Fill in other metadata diff --git a/ui/tests/integration/components/kv/page/kv-page-metadata-edit-test.js b/ui/tests/integration/components/kv/page/kv-page-metadata-edit-test.js index 69c7c408a9..2a443f8583 100644 --- a/ui/tests/integration/components/kv/page/kv-page-metadata-edit-test.js +++ b/ui/tests/integration/components/kv/page/kv-page-metadata-edit-test.js @@ -122,7 +122,10 @@ module('Integration | Component | kv-v2 | Page::Secret::Metadata::Edit', functio await click(FORM.saveBtn); assert .dom(FORM.validationError('max_versions')) - .hasText('Maximum versions must be a number.', 'Validation message is shown for max_versions'); + .hasText( + 'Maximum versions must be a non-negative number.', + 'Validation message is shown for max_versions' + ); await click(FORM.cancelBtn); assert.true(this.onCancel.called, 'onCancel action is called');