UI: Update kv max_version validation (#14430) (#14455)

* update kv max_version validation to ensure non-negative whole number, add min max options to number validator

* update tests

* add changelog entry

Co-authored-by: lane-wetmore <lane.wetmore@hashicorp.com>
This commit is contained in:
Vault Automation 2026-05-04 09:10:29 -06:00 committed by GitHub
parent ce37adeecf
commit ab7e7ef70f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 61 additions and 10 deletions

3
changelog/_14430.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
ui: Update KV max_version validation to disallow negative values.
```

View File

@ -20,8 +20,12 @@ export default class SecretsEngineForm extends MountForm<SecretsEngineFormData>
// 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'] = [

View File

@ -43,8 +43,12 @@ export default class KvForm extends Form<KvFormData> {
},
],
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.',
},
],
};

View File

@ -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) => {

View File

@ -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

View File

@ -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');