mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-05 04:16:31 +02:00
Merge remote-tracking branch 'remotes/from/ce/main'
This commit is contained in:
commit
5c75028a7f
3
changelog/_14430.txt
Normal file
3
changelog/_14430.txt
Normal file
@ -0,0 +1,3 @@
|
||||
```release-note:bug
|
||||
ui: Update KV max_version validation to disallow negative values.
|
||||
```
|
||||
3
changelog/_14445.txt
Normal file
3
changelog/_14445.txt
Normal file
@ -0,0 +1,3 @@
|
||||
```release-note:bug
|
||||
ui: Fix secrets to secrets-engines redirect for bookmarked URLs.
|
||||
```
|
||||
@ -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'] = [
|
||||
|
||||
@ -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.',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@ -168,6 +168,7 @@ Router.map(function () {
|
||||
});
|
||||
});
|
||||
this.route('secrets-redirect', { path: '/secrets' }); // legacy redirect
|
||||
this.route('secrets-redirect-with-path', { path: '/secrets/*path' }); // legacy redirect with wildcard to capture full path
|
||||
this.route('secrets', { path: '/secrets-engines' }, function () {
|
||||
this.route('enable', function () {
|
||||
this.route('create', { path: '/:mount_type' });
|
||||
|
||||
27
ui/app/routes/vault/cluster/secrets-redirect-with-path.js
Normal file
27
ui/app/routes/vault/cluster/secrets-redirect-with-path.js
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright IBM Corp. 2016, 2025
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
import Route from '@ember/routing/route';
|
||||
import { service } from '@ember/service';
|
||||
|
||||
export default class SecretsRedirectWithPathRoute extends Route {
|
||||
@service router;
|
||||
|
||||
beforeModel(transition) {
|
||||
// Redirect to secrets page under /secrets-engines
|
||||
// if the user navigates to the legacy path /secrets
|
||||
// Preserve the full path after /secrets (e.g., /secrets/kv/kv/list -> /secrets-engines/kv/kv/list)
|
||||
const params = transition.to.params;
|
||||
const path = params?.path;
|
||||
|
||||
if (path) {
|
||||
// Construct the new URL with full path including /vault/secrets-engines/*path
|
||||
const newUrl = `/vault/secrets-engines/${path}`;
|
||||
this.router.replaceWith(newUrl);
|
||||
} else {
|
||||
// If no path, just redirect to the base secrets page
|
||||
this.router.replaceWith('vault.cluster.secrets');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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) => {
|
||||
|
||||
@ -10,7 +10,7 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { login, loginMethod, logout } from 'vault/tests/helpers/auth/auth-helpers';
|
||||
import { mountBackend } from 'vault/tests/helpers/components/mount-backend-form-helpers';
|
||||
import { runCmd } from 'vault/tests/helpers/commands';
|
||||
import { mountEngineCmd, runCmd, deleteEngineCmd } from 'vault/tests/helpers/commands';
|
||||
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
||||
|
||||
const tokenWithPolicy = async function (name, policy) {
|
||||
@ -120,4 +120,15 @@ module('Acceptance | cluster', function (hooks) {
|
||||
'Navigating to /secrets redirects to /secrets-engines'
|
||||
);
|
||||
});
|
||||
|
||||
test('redirects to /secrets-engines/kv/kv/list from legacy /secrets/kv/kv/list path', async function (assert) {
|
||||
await runCmd(mountEngineCmd('kv', this.backend), false);
|
||||
await visit('/vault/secrets/kv/kv/list');
|
||||
assert.strictEqual(
|
||||
currentURL(),
|
||||
'/vault/secrets-engines/kv/kv/list',
|
||||
'Navigating to /secrets redirects to /secrets-engines'
|
||||
);
|
||||
await runCmd(deleteEngineCmd('kv'));
|
||||
});
|
||||
});
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user