Replace KV v2 List route with wildcard instead of dynamic segment (#23620)

* initial work on the LIST route.

* fix

* changelog

* add s

* add in prepending forward slash
This commit is contained in:
Angel Garbarino
2023-10-13 11:01:23 -06:00
committed by GitHub
parent b0ce08bb4b
commit 27170b662d
5 changed files with 38 additions and 34 deletions

3
changelog/23620.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:bug
ui: Fixes issue where you could not share the list view URL from the KV v2 secrets engine.
```

View File

@@ -7,9 +7,10 @@ import buildRoutes from 'ember-engines/routes';
export default buildRoutes(function () { export default buildRoutes(function () {
// There are two list routes because Ember won't let a route param (e.g. *path_to_secret) be blank. // There are two list routes because Ember won't let a route param (e.g. *path_to_secret) be blank.
// :path_to_secret is used when we're listing a secret directory. Example { path: '/:beep%2Fboop%2F/directory' }); // *path_to_secret is used when we're listing a secret directory.
// Must use a wildcard for path-to-secret because the value can contain a forward slash if it's a secret directory. Ember's router decodes encoded forward slashes which leads to beep%2fboop becoming beep/boop and messing up routing after copying and pasting the URL.
this.route('list'); this.route('list');
this.route('list-directory', { path: '/:path_to_secret/directory' }); this.route('list-directory', { path: '/list/*path_to_secret' });
this.route('create'); this.route('create');
this.route('secret', { path: '/:name' }, function () { this.route('secret', { path: '/:name' }, function () {
this.route('paths'); this.route('paths');

View File

@@ -213,7 +213,7 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
}); });
test('creates a secret at a sub-directory (a)', async function (assert) { test('creates a secret at a sub-directory (a)', async function (assert) {
const backend = this.backend; const backend = this.backend;
await visit(`/vault/secrets/${backend}/kv/app%2F/directory`); await visit(`/vault/secrets/${backend}/kv/list/app/`);
assert.dom(PAGE.list.item('first')).exists('Lists first sub-secret'); assert.dom(PAGE.list.item('first')).exists('Lists first sub-secret');
assert.dom(PAGE.list.item('new')).doesNotExist('Does not show new secret'); assert.dom(PAGE.list.item('new')).doesNotExist('Does not show new secret');
await click(PAGE.list.createSecret); await click(PAGE.list.createSecret);
@@ -232,7 +232,7 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
'Redirects to detail after save' 'Redirects to detail after save'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2F/directory`, 'sub-dir page'); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/`, 'sub-dir page');
assert.dom(PAGE.list.item('new')).exists('Lists new secret in sub-dir'); assert.dom(PAGE.list.item('new')).exists('Lists new secret in sub-dir');
}); });
test('create new version of secret from older version (a)', async function (assert) { test('create new version of secret from older version (a)', async function (assert) {
@@ -390,7 +390,7 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
}); });
test('creates a secret at a sub-directory (dr)', async function (assert) { test('creates a secret at a sub-directory (dr)', async function (assert) {
const backend = this.backend; const backend = this.backend;
await visit(`/vault/secrets/${backend}/kv/app%2F/directory`); await visit(`/vault/secrets/${backend}/kv/list/app/`);
assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets'); assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets');
await click(PAGE.list.createSecret); await click(PAGE.list.createSecret);
assert.strictEqual( assert.strictEqual(
@@ -535,7 +535,7 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
}); });
test('creates a secret at a sub-directory (dlr)', async function (assert) { test('creates a secret at a sub-directory (dlr)', async function (assert) {
const backend = this.backend; const backend = this.backend;
await visit(`/vault/secrets/${backend}/kv/app%2F/directory`); await visit(`/vault/secrets/${backend}/kv/list/app/`);
assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets'); assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets');
await click(PAGE.list.createSecret); await click(PAGE.list.createSecret);
assert.strictEqual( assert.strictEqual(
@@ -704,7 +704,7 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
}); });
test('creates a secret at a sub-directory (mm)', async function (assert) { test('creates a secret at a sub-directory (mm)', async function (assert) {
const backend = this.backend; const backend = this.backend;
await visit(`/vault/secrets/${backend}/kv/app%2F/directory`); await visit(`/vault/secrets/${backend}/kv/list/app/`);
assert.dom(PAGE.list.item('first')).exists('Lists first sub-secret'); assert.dom(PAGE.list.item('first')).exists('Lists first sub-secret');
assert.dom(PAGE.list.item('new')).doesNotExist('Does not show new secret'); assert.dom(PAGE.list.item('new')).doesNotExist('Does not show new secret');
await click(PAGE.list.createSecret); await click(PAGE.list.createSecret);
@@ -941,7 +941,7 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
}); });
test('creates a secret at a sub-directory (sc)', async function (assert) { test('creates a secret at a sub-directory (sc)', async function (assert) {
const backend = this.backend; const backend = this.backend;
await visit(`/vault/secrets/${backend}/kv/app%2F/directory`); await visit(`/vault/secrets/${backend}/kv/list/app/`);
assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets'); assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets');
await click(PAGE.list.createSecret); await click(PAGE.list.createSecret);
assert.strictEqual( assert.strictEqual(
@@ -959,7 +959,7 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
'Redirects to detail after save' 'Redirects to detail after save'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2F/directory`, 'sub-dir page'); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/`, 'sub-dir page');
assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets'); assert.dom(PAGE.list.item()).doesNotExist('Does not list any secrets');
}); });
test('create new version of secret from older version (sc)', async function (assert) { test('create new version of secret from older version (sc)', async function (assert) {

View File

@@ -84,7 +84,7 @@ module('Acceptance | kv-v2 workflow | edge cases', function (hooks) {
// URL correct // URL correct
assert.strictEqual( assert.strictEqual(
currentURL(), currentURL(),
`/vault/secrets/${backend}/kv/${root}%2F/directory`, `/vault/secrets/${backend}/kv/list/${root}/`,
'visits list-directory of root' 'visits list-directory of root'
); );
@@ -125,7 +125,7 @@ module('Acceptance | kv-v2 workflow | edge cases', function (hooks) {
await click(PAGE.breadcrumbAtIdx(previousCrumb)); await click(PAGE.breadcrumbAtIdx(previousCrumb));
assert.strictEqual( assert.strictEqual(
currentURL(), currentURL(),
`/vault/secrets/${backend}/kv/${root}%2F${subdirectory}%2F/directory`, `/vault/secrets/${backend}/kv/list/${root}/${subdirectory}/`,
'goes back to subdirectory list' 'goes back to subdirectory list'
); );
assert.dom(PAGE.list.filter).hasValue(`${root}/${subdirectory}/`); assert.dom(PAGE.list.filter).hasValue(`${root}/${subdirectory}/`);
@@ -136,7 +136,7 @@ module('Acceptance | kv-v2 workflow | edge cases', function (hooks) {
await click(PAGE.breadcrumbAtIdx(previousCrumb)); await click(PAGE.breadcrumbAtIdx(previousCrumb));
assert.strictEqual( assert.strictEqual(
currentURL(), currentURL(),
`/vault/secrets/${backend}/kv/${root}%2F/directory`, `/vault/secrets/${backend}/kv/list/${root}/`,
'goes back to root directory' 'goes back to root directory'
); );
assert.dom(PAGE.list.item(`${subdirectory}/`)).exists('renders linked block for subdirectory'); assert.dom(PAGE.list.item(`${subdirectory}/`)).exists('renders linked block for subdirectory');
@@ -253,7 +253,7 @@ module('Acceptance | kv-v2 workflow | edge cases', function (hooks) {
}); });
test('no ghost item after editing metadata', async function (assert) { test('no ghost item after editing metadata', async function (assert) {
await visit(`/vault/secrets/${this.backend}/kv/edge/directory`); await visit(`/vault/secrets/${this.backend}/kv/list/edge/`);
assert.dom(PAGE.list.item()).exists({ count: 2 }, 'two secrets are listed'); assert.dom(PAGE.list.item()).exists({ count: 2 }, 'two secrets are listed');
await click(PAGE.list.item('two')); await click(PAGE.list.item('two'));
await click(PAGE.secretTab('Metadata')); await click(PAGE.secretTab('Metadata'));

View File

@@ -165,14 +165,14 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
// Navigate through list items // Navigate through list items
await click(PAGE.list.item('app/')); await click(PAGE.list.item('app/'));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2F/directory`); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/`);
assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']); assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']);
assert.dom(PAGE.title).hasText(`${backend} Version 2`); assert.dom(PAGE.title).hasText(`${backend} Version 2`);
assert.dom(PAGE.list.filter).hasValue('app/', 'List filter input is prefilled'); assert.dom(PAGE.list.filter).hasValue('app/', 'List filter input is prefilled');
assert.dom(PAGE.list.item('nested/')).exists('Shows nested secret'); assert.dom(PAGE.list.item('nested/')).exists('Shows nested secret');
await click(PAGE.list.item('nested/')); await click(PAGE.list.item('nested/'));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/nested/`);
assertCorrectBreadcrumbs(assert, ['secret', backend, 'app', 'nested']); assertCorrectBreadcrumbs(assert, ['secret', backend, 'app', 'nested']);
assert.dom(PAGE.title).hasText(`${backend} Version 2`); assert.dom(PAGE.title).hasText(`${backend} Version 2`);
assert.dom(PAGE.list.filter).hasValue('app/nested/', 'List filter input is prefilled'); assert.dom(PAGE.list.filter).hasValue('app/nested/', 'List filter input is prefilled');
@@ -189,13 +189,13 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
await click(PAGE.breadcrumbAtIdx(3)); await click(PAGE.breadcrumbAtIdx(3));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/nested/`),
'links back to list directory' 'links back to list directory'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/`),
'links back to list directory' 'links back to list directory'
); );
@@ -416,13 +416,13 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
await click(PAGE.breadcrumbAtIdx(3)); await click(PAGE.breadcrumbAtIdx(3));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/nested/`),
'links back to list directory' 'links back to list directory'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/`),
'links back to list directory' 'links back to list directory'
); );
@@ -585,7 +585,7 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
// Navigate through list items // Navigate through list items
await click(PAGE.list.item('app/')); await click(PAGE.list.item('app/'));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2F/directory`); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/`);
assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']); assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']);
assert.dom(PAGE.title).hasText(`${backend} Version 2`); assert.dom(PAGE.title).hasText(`${backend} Version 2`);
assert.dom(PAGE.list.filter).doesNotExist('List filter hidden since no nested list access'); assert.dom(PAGE.list.filter).doesNotExist('List filter hidden since no nested list access');
@@ -606,13 +606,13 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
await click(PAGE.breadcrumbAtIdx(3)); await click(PAGE.breadcrumbAtIdx(3));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/nested/`),
'links back to list directory' 'links back to list directory'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/`),
'links back to list directory' 'links back to list directory'
); );
@@ -771,14 +771,14 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
// Navigate through list items // Navigate through list items
await click(PAGE.list.item('app/')); await click(PAGE.list.item('app/'));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2F/directory`); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/`);
assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']); assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']);
assert.dom(PAGE.title).hasText(`${backend} Version 2`); assert.dom(PAGE.title).hasText(`${backend} Version 2`);
assert.dom(PAGE.list.filter).hasValue('app/', 'List filter input is prefilled'); assert.dom(PAGE.list.filter).hasValue('app/', 'List filter input is prefilled');
assert.dom(PAGE.list.item('nested/')).exists('Shows nested secret'); assert.dom(PAGE.list.item('nested/')).exists('Shows nested secret');
await click(PAGE.list.item('nested/')); await click(PAGE.list.item('nested/'));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/nested/`);
assertCorrectBreadcrumbs(assert, ['secret', backend, 'app', 'nested']); assertCorrectBreadcrumbs(assert, ['secret', backend, 'app', 'nested']);
assert.dom(PAGE.title).hasText(`${backend} Version 2`); assert.dom(PAGE.title).hasText(`${backend} Version 2`);
assert.dom(PAGE.list.filter).hasValue('app/nested/', 'List filter input is prefilled'); assert.dom(PAGE.list.filter).hasValue('app/nested/', 'List filter input is prefilled');
@@ -797,13 +797,13 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
await click(PAGE.breadcrumbAtIdx(3)); await click(PAGE.breadcrumbAtIdx(3));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/nested/`),
'links back to list directory' 'links back to list directory'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/`),
'links back to list directory' 'links back to list directory'
); );
@@ -989,13 +989,13 @@ module('Acceptance | kv-v2 workflow | navigation', function (hooks) {
await click(PAGE.breadcrumbAtIdx(3)); await click(PAGE.breadcrumbAtIdx(3));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/nested/`),
'links back to list directory' 'links back to list directory'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/`),
'links back to list directory' 'links back to list directory'
); );
@@ -1152,14 +1152,14 @@ path "${this.backend}/*" {
// Navigate through list items // Navigate through list items
await click(PAGE.list.item('app/')); await click(PAGE.list.item('app/'));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2F/directory`); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/`);
assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']); assertCorrectBreadcrumbs(assert, ['secret', backend, 'app']);
assert.dom(PAGE.title).hasText(`${backend} Version 2`); assert.dom(PAGE.title).hasText(`${backend} Version 2`);
assert.dom(PAGE.list.filter).hasValue('app/', 'List filter input is prefilled'); assert.dom(PAGE.list.filter).hasValue('app/', 'List filter input is prefilled');
assert.dom(PAGE.list.item('nested/')).exists('Shows nested secret'); assert.dom(PAGE.list.item('nested/')).exists('Shows nested secret');
await click(PAGE.list.item('nested/')); await click(PAGE.list.item('nested/'));
assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`); assert.strictEqual(currentURL(), `/vault/secrets/${backend}/kv/list/app/nested/`);
assertCorrectBreadcrumbs(assert, ['secret', backend, 'app', 'nested']); assertCorrectBreadcrumbs(assert, ['secret', backend, 'app', 'nested']);
assert.dom(PAGE.title).hasText(`${backend} Version 2`); assert.dom(PAGE.title).hasText(`${backend} Version 2`);
assert.dom(PAGE.list.filter).hasValue('app/nested/', 'List filter input is prefilled'); assert.dom(PAGE.list.filter).hasValue('app/nested/', 'List filter input is prefilled');
@@ -1174,12 +1174,12 @@ path "${this.backend}/*" {
); );
await grantAccess({ await grantAccess({
apiPath: `${backend}/data/app/nested/secret`, apiPath: `${backend}/data/app/nested/secret`,
originUrl: `/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`, originUrl: `/vault/secrets/${backend}/kv/list/app/nested/`,
userToken: this.userToken, userToken: this.userToken,
}); });
assert.strictEqual( assert.strictEqual(
currentURL(), currentURL(),
`/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`, `/vault/secrets/${backend}/kv/list/app/nested/`,
'navigates to list url where secret is' 'navigates to list url where secret is'
); );
await click(PAGE.list.item('secret')); await click(PAGE.list.item('secret'));
@@ -1195,13 +1195,13 @@ path "${this.backend}/*" {
await click(PAGE.breadcrumbAtIdx(3)); await click(PAGE.breadcrumbAtIdx(3));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2Fnested%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/nested/`),
'links back to list directory' 'links back to list directory'
); );
await click(PAGE.breadcrumbAtIdx(2)); await click(PAGE.breadcrumbAtIdx(2));
assert.ok( assert.ok(
currentURL().startsWith(`/vault/secrets/${backend}/kv/app%2F/directory`), currentURL().startsWith(`/vault/secrets/${backend}/kv/list/app/`),
'links back to list directory' 'links back to list directory'
); );