UI: Add necessary params to links in Access & KV v2 (#26561)

* refactor tabs-for-auth-section helper

* Fill out route params in generated-item + list compoenents

* Add optional route params to ListView pagination

* Add backend to KV breadcrumb link route models

* fix links in kv v2 pages, update kv-breadcrumbs-test

* remove todo
This commit is contained in:
Chelsea Shaw 2024-04-23 09:36:08 -05:00 committed by GitHub
parent 5f4e53e5a2
commit 9efa76ac4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 262 additions and 111 deletions

View File

@ -10,7 +10,7 @@
<ul>
{{#each tabs as |tab|}}
<li>
<LinkTo @route={{get tab.routeParams 0}} @model={{get tab.routeParams 1}} data-test-auth-section-tab>
<LinkTo @route={{tab.route}} @models={{tab.routeParams}} data-test-auth-section-tab>
{{tab.label}}
</LinkTo>
</li>

View File

@ -11,88 +11,101 @@ const TABS_FOR_SETTINGS = {
aws: [
{
label: 'Client',
routeParams: ['vault.cluster.settings.auth.configure.section', 'client'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['client'],
},
{
label: 'Identity Allow List Tidy',
routeParams: ['vault.cluster.settings.auth.configure.section', 'identity-accesslist'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['identity-accesslist'],
},
{
label: 'Role Tag Deny List Tidy',
routeParams: ['vault.cluster.settings.auth.configure.section', 'roletag-denylist'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['roletag-denylist'],
},
],
azure: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
github: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
gcp: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
jwt: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
oidc: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
kubernetes: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
ldap: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
okta: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
radius: [
{
label: 'Configuration',
routeParams: ['vault.cluster.settings.auth.configure.section', 'configuration'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['configuration'],
},
],
};
const TABS_FOR_SHOW = {};
export function tabsForAuthSection([model, sectionType = 'authSettings', paths]) {
export function tabsForAuthSection([authMethodModel, sectionType = 'authSettings', paths]) {
let tabs;
if (sectionType === 'authSettings') {
tabs = (TABS_FOR_SETTINGS[model.type] || []).slice();
tabs = (TABS_FOR_SETTINGS[authMethodModel.type] || []).slice();
tabs.push({
label: 'Method Options',
routeParams: ['vault.cluster.settings.auth.configure.section', 'options'],
route: 'vault.cluster.settings.auth.configure.section',
routeParams: ['options'],
});
return tabs;
}
if (paths || model.paths) {
if (model.paths) {
paths = model.paths.paths.filter((path) => path.navigation);
if (paths || authMethodModel.paths) {
if (authMethodModel.paths) {
paths = authMethodModel.paths.paths.filter((path) => path.navigation);
}
// TODO: we're unsure if we actually need compact here
@ -100,18 +113,24 @@ export function tabsForAuthSection([model, sectionType = 'authSettings', paths])
tabs = paths.compact().map((path) => {
return {
label: capitalize(pluralize(path.itemName)),
routeParams: ['vault.cluster.access.method.item.list', path.itemType],
route: 'vault.cluster.access.method.item.list',
routeParams: [path.itemType],
};
});
} else {
tabs = (TABS_FOR_SHOW[model.type] || []).slice();
tabs = (TABS_FOR_SHOW[authMethodModel.type] || []).slice();
}
tabs.push({
label: 'Configuration',
routeParams: ['vault.cluster.access.method.section', 'configuration'],
route: 'vault.cluster.access.method.section',
routeParams: ['configuration'],
});
return tabs;
return tabs.map((tab) => ({
label: tab.label,
route: tab.route,
routeParams: [authMethodModel.id, ...tab.routeParams],
}));
}
export default buildHelper(tabsForAuthSection);

View File

@ -11,9 +11,11 @@ export default class AccessMethodIndexRoute extends Route {
@service router;
beforeModel() {
let { methodType, paths } = this.modelFor('vault.cluster.access.method');
paths = paths ? paths.paths.filter((path) => path.navigation === true) : null;
const activeTab = tabsForAuthSection([methodType, 'authConfig', paths])[0].routeParams;
return this.router.transitionTo(...activeTab);
const methodModel = this.modelFor('vault.cluster.access.method');
const paths = methodModel.paths
? methodModel.paths.paths.filter((path) => path.navigation === true)
: null;
const activeTab = tabsForAuthSection([methodModel, 'authConfig', paths])[0];
return this.router.transitionTo(activeTab.route, ...activeTab.routeParams);
}
}

View File

@ -22,6 +22,8 @@ export default Route.extend(UnsavedModelRoute, {
setupController(controller) {
this._super(...arguments);
const { item_type: itemType } = this.paramsFor('vault.cluster.access.method.item');
const { path: method } = this.paramsFor('vault.cluster.access.method');
controller.set('itemType', singularize(itemType));
controller.set('method', method);
},
});

View File

@ -22,6 +22,8 @@ export default Route.extend({
setupController(controller) {
this._super(...arguments);
const { item_type: itemType } = this.paramsFor('vault.cluster.access.method.item');
const { path: method } = this.paramsFor('vault.cluster.access.method');
controller.set('itemType', singularize(itemType));
controller.set('method', method);
},
});

View File

@ -12,7 +12,7 @@ export default class SettingsAuthConfigureRoute extends Route {
beforeModel() {
const model = this.modelFor('vault.cluster.settings.auth.configure');
const section = tabsForAuthSection([model])[0].routeParams.lastObject;
const section = tabsForAuthSection([model])[0].routeParams.slice().pop();
return this.router.transitionTo('vault.cluster.settings.auth.configure.section', section);
}
}

View File

@ -23,7 +23,7 @@
<ul>
{{#each tabs as |tab|}}
<li>
<LinkTo @route={{get tab.routeParams 0}} @model={{get tab.routeParams 1}} data-test-auth-section-tab={{true}}>
<LinkTo @route={{tab.route}} @models={{tab.routeParams}} data-test-auth-section-tab>
{{tab.label}}
</LinkTo>
</li>
@ -37,7 +37,7 @@
<ToolbarActions>
<ToolbarLink
@route="vault.cluster.access.method.item.create"
@model={{@itemType}}
@models={{array @methodModel.id @itemType}}
@type="add"
data-test-entity-create-link={{@itemType}}
>
@ -46,7 +46,13 @@
</ToolbarLink>
</ToolbarActions>
</Toolbar>
<ListView @items={{@model}} @itemNoun={{@itemType}} @paginationRouteName="vault.cluster.access.method.item.list" as |list|>
<ListView
@items={{@model}}
@itemNoun={{@itemType}}
@paginationRouteName="vault.cluster.access.method.item.list"
@paginationRouteParams={{array @methodModel.id @itemType}}
as |list|
>
{{#if list.empty}}
<list.empty
@title="No {{pluralize @itemType}} yet"
@ -56,11 +62,11 @@
@icon="plus"
@text="Create {{singularize @itemType}}"
@route="vault.cluster.access.method.item.create"
@model={{@itemType}}
@models={{array @methodModel.id @itemType}}
/>
</list.empty>
{{else if list.item}}
<ListItem @linkParams={{array "vault.cluster.access.method.item.show" @itemType list.item.id}} as |Item|>
<ListItem @linkParams={{array "vault.cluster.access.method.item.show" @methodModel.id @itemType list.item.id}} as |Item|>
<Item.content>
<Icon @name="folder" class="has-text-grey-light" />{{list.item.id}}
</Item.content>
@ -75,12 +81,12 @@
<dd.Interactive
@text="View {{singularize @itemType}}"
@route="vault.cluster.access.method.item.show"
@model={{list.item.id}}
@models={{array @methodModel.id @itemType list.item.id}}
/>
<dd.Interactive
@text="Edit {{singularize @itemType}}"
@route="vault.cluster.access.method.item.edit"
@model={{list.item.id}}
@models={{array @methodModel.id @itemType list.item.id}}
/>
<dd.Interactive
@text="Delete {{singularize @itemType}}"

View File

@ -9,7 +9,7 @@
<Hds::Breadcrumb::Item
@text={{pluralize this.itemType}}
@route="vault.cluster.access.method.item.list"
@model={{this.itemType}}
@models={{array this.mountPath this.itemType}}
/>
<Hds::Breadcrumb::Item @text={{if (eq this.mode "show") this.model.id (capitalize this.mode)}} @current={{true}} />
</Hds::Breadcrumb>
@ -43,7 +43,7 @@
<div class="toolbar-separator"></div>
<ToolbarLink
@route="vault.cluster.access.method.item.edit"
@models={{array this.itemType this.model.id}}
@models={{array this.mountPath this.itemType this.model.id}}
data-test-configure-link="true"
>
Edit
@ -75,6 +75,7 @@
@text="Cancel"
@color="secondary"
@route="vault.cluster.access.method.item.list"
@models={{array this.mountPath this.itemType}}
data-test-cancel-link={{true}}
/>
{{else}}
@ -82,7 +83,7 @@
@text="Cancel"
@color="secondary"
@route="vault.cluster.access.method.item.show"
@model={{this.model.id}}
@models={{array this.mountPath this.itemType this.model.id}}
data-test-cancel-link={{true}}
/>
{{/if}}

View File

@ -3,4 +3,4 @@
SPDX-License-Identifier: BUSL-1.1
~}}
<GeneratedItem @model={{this.model}} @mode="create" @itemType={{this.model.itemType}} />
<GeneratedItem @mountPath={{this.method}} @model={{this.model}} @mode="create" @itemType={{this.model.itemType}} />

View File

@ -3,4 +3,4 @@
SPDX-License-Identifier: BUSL-1.1
~}}
<GeneratedItem @model={{this.model}} @mode="edit" @itemType={{this.itemType}} />
<GeneratedItem @mountPath={{this.method}} @model={{this.model}} @mode="edit" @itemType={{this.itemType}} />

View File

@ -3,4 +3,4 @@
SPDX-License-Identifier: BUSL-1.1
~}}
<GeneratedItem @model={{this.model}} @itemType={{this.itemType}} @mode="show" />
<GeneratedItem @mountPath={{this.method}} @model={{this.model}} @itemType={{this.itemType}} @mode="show" />

View File

@ -15,6 +15,7 @@
@currentPage={{@items.meta.currentPage}}
@currentPageSize={{@items.meta.pageSize}}
@route={{@paginationRouteName}}
@models={{@paginationRouteParams}}
@showSizeSelector={{false}}
@totalItems={{@items.meta.total}}
@queryFunction={{this.paginationQueryParams}}

View File

@ -45,7 +45,13 @@
</ToolbarLink>
</ToolbarActions>
</Toolbar>
<ListView @items={{this.model}} @itemNoun="credentials" @paginationRouteName="credentials.index" as |list|>
<ListView
@items={{this.model}}
@itemNoun="credentials"
@paginationRouteName="credentials.index"
@paginationRouteParams={{array this.scope this.role}}
as |list|
>
{{#if list.empty}}
<list.empty
@title="No credentials yet for this role"

View File

@ -5,8 +5,17 @@
<KvPageHeader @breadcrumbs={{@breadcrumbs}} @mountName={{@backend}}>
<:tabLinks>
<li><LinkTo @route={{this.router.currentRoute.localName}} data-test-secrets-tab="Secrets">Secrets</LinkTo></li>
<li><LinkTo @route="configuration" data-test-secrets-tab="Configuration">Configuration</LinkTo></li>
<li>
<LinkTo
@route={{this.router.currentRoute.localName}}
@models={{@currentRouteParams}}
data-test-secrets-tab="Secrets"
@current-when={{true}}
>Secrets</LinkTo>
</li>
<li>
<LinkTo @route="configuration" @model={{@backend}} data-test-secrets-tab="Configuration">Configuration</LinkTo>
</li>
</:tabLinks>
<:toolbarFilters>
@ -17,7 +26,13 @@
</:toolbarFilters>
<:toolbarActions>
<ToolbarLink data-test-toolbar-create-secret @route="create" @query={{hash initialKey=@filterValue}} @type="add">
<ToolbarLink
data-test-toolbar-create-secret
@route="create"
@model={{@backend}}
@query={{hash initialKey=@filterValue}}
@type="add"
>
Create secret
</ToolbarLink>
</:toolbarActions>
@ -57,7 +72,7 @@
<LinkedBlock
data-test-list-item={{metadata.path}}
class="list-item-row"
@params={{array (if metadata.pathIsDirectory "list-directory" "secret.details") metadata.fullSecretPath}}
@params={{array (if metadata.pathIsDirectory "list-directory" "secret.details") @backend metadata.fullSecretPath}}
@linkPrefix={{this.mountPoint}}
>
<div class="level is-mobile">
@ -79,21 +94,30 @@
data-test-popup-menu-trigger
/>
{{#if metadata.pathIsDirectory}}
<dd.Interactive @text="Content" @route="list-directory" @model={{metadata.fullSecretPath}} />
<dd.Interactive
@text="Content"
@route="list-directory"
@models={{array @backend metadata.fullSecretPath}}
/>
{{else}}
<dd.Interactive @text="Details" @route="secret.details" @model={{metadata.fullSecretPath}} />
<dd.Interactive
@text="Details"
@route="secret.details"
@models={{array @backend metadata.fullSecretPath}}
/>
{{#if metadata.canReadMetadata}}
<dd.Interactive
@text="View version history"
@route="secret.metadata.versions"
@model={{metadata.fullSecretPath}}
@models={{array @backend metadata.fullSecretPath}}
/>
{{/if}}
{{#if metadata.canCreateVersionData}}
\
<dd.Interactive
@text="Create new version"
@route="secret.details.edit"
@model={{metadata.fullSecretPath}}
@models={{array @backend metadata.fullSecretPath}}
data-test-popup-create-new-version
/>
{{/if}}
@ -120,12 +144,12 @@
@confirmMessage="This will permanently delete this secret and all its versions."
/>
{{/if}}
{{! Pagination }}
<Hds::Pagination::Numbered
@currentPage={{@secrets.meta.currentPage}}
@currentPageSize={{@secrets.meta.pageSize}}
@route={{this.router.currentRoute.localName}}
@showSizeSelector={{false}}
@models={{@currentRouteParams}}
@totalItems={{@secrets.meta.total}}
@queryFunction={{this.paginationQueryParams}}
data-test-pagination

View File

@ -44,11 +44,27 @@
</:syncDetails>
<:tabLinks>
<li><LinkTo @route="secret.details" data-test-secrets-tab="Secret">Secret</LinkTo></li>
<li><LinkTo @route="secret.metadata.index" data-test-secrets-tab="Metadata">Metadata</LinkTo></li>
<li><LinkTo @route="secret.paths" data-test-secrets-tab="Paths">Paths</LinkTo></li>
<li>
<LinkTo @route="secret.details" @models={{array @secret.backend @path}} data-test-secrets-tab="Secret">Secret</LinkTo>
</li>
<li>
<LinkTo
@route="secret.metadata.index"
@models={{array @secret.backend @path}}
data-test-secrets-tab="Metadata"
>Metadata</LinkTo>
</li>
<li>
<LinkTo @route="secret.paths" @models={{array @secret.backend @path}} data-test-secrets-tab="Paths">Paths</LinkTo>
</li>
{{#if @secret.canReadMetadata}}
<li><LinkTo @route="secret.metadata.versions" data-test-secrets-tab="Version History">Version History</LinkTo></li>
<li>
<LinkTo
@route="secret.metadata.versions"
@models={{array @secret.backend @path}}
data-test-secrets-tab="Version History"
>Version History</LinkTo>
</li>
{{/if}}
</:tabLinks>
@ -97,7 +113,14 @@
<KvVersionDropdown @displayVersion={{this.version}} @metadata={{@metadata}} @onClose={{this.closeVersionMenu}} />
{{/if}}
{{#if @secret.canEditData}}
<ToolbarLink data-test-create-new-version @route="secret.details.edit" @type="add">Create new version</ToolbarLink>
<ToolbarLink
data-test-create-new-version
@route="secret.details.edit"
@models={{array @secret.backend @path}}
@type="add"
>
Create new version
</ToolbarLink>
{{/if}}
</:toolbarActions>
</KvPageHeader>

View File

@ -5,11 +5,27 @@
<KvPageHeader @breadcrumbs={{@breadcrumbs}} @pageTitle={{@path}}>
<:tabLinks>
<li><LinkTo @route="secret.details" data-test-secrets-tab="Secret">Secret</LinkTo></li>
<li><LinkTo @route="secret.metadata.index" data-test-secrets-tab="Metadata">Metadata</LinkTo></li>
<li><LinkTo @route="secret.paths" data-test-secrets-tab="Paths">Paths</LinkTo></li>
<li>
<LinkTo @route="secret.details" @models={{array @secret.backend @path}} data-test-secrets-tab="Secret">Secret</LinkTo>
</li>
<li>
<LinkTo
@route="secret.metadata.index"
@models={{array @secret.backend @path}}
data-test-secrets-tab="Metadata"
>Metadata</LinkTo>
</li>
<li>
<LinkTo @route="secret.paths" @models={{array @secret.backend @path}} data-test-secrets-tab="Paths">Paths</LinkTo>
</li>
{{#if @secret.canReadMetadata}}
<li><LinkTo @route="secret.metadata.versions" data-test-secrets-tab="Version History">Version History</LinkTo></li>
<li>
<LinkTo
@route="secret.metadata.versions"
@models={{array @secret.backend @path}}
data-test-secrets-tab="Version History"
>Version History</LinkTo>
</li>
{{/if}}
</:tabLinks>
@ -23,7 +39,9 @@
/>
{{/if}}
{{#if @secret.canUpdateMetadata}}
<ToolbarLink @route="secret.metadata.edit" data-test-edit-metadata>Edit metadata</ToolbarLink>
<ToolbarLink @route="secret.metadata.edit" @models={{array @secret.backend @path}} data-test-edit-metadata>
Edit metadata
</ToolbarLink>
{{/if}}
</:toolbarActions>
</KvPageHeader>
@ -46,7 +64,7 @@
@icon="plus"
@text="Add metadata"
@route="secret.metadata.edit"
@model={{@path}}
@models={{array @secret.backend @path}}
data-test-add-custom-metadata
/>
{{/if}}

View File

@ -5,15 +5,32 @@
<KvPageHeader @breadcrumbs={{@breadcrumbs}} @pageTitle={{@path}}>
<:tabLinks>
<li><LinkTo @route="secret.details" data-test-secrets-tab="Secret">Secret</LinkTo></li>
<li><LinkTo @route="secret.metadata.index" data-test-secrets-tab="Metadata">Metadata</LinkTo></li>
<li><LinkTo @route="secret.paths" data-test-secrets-tab="Paths">Paths</LinkTo></li>
<li><LinkTo @route="secret.metadata.versions" data-test-secrets-tab="Version History">Version History</LinkTo></li>
<li>
<LinkTo @route="secret.details" @models={{array @backend @path}} data-test-secrets-tab="Secret">Secret</LinkTo>
</li>
<li>
<LinkTo
@route="secret.metadata.index"
@models={{array @backend @path}}
data-test-secrets-tab="Metadata"
>Metadata</LinkTo>
</li>
<li>
<LinkTo @route="secret.paths" @models={{array @backend @path}} data-test-secrets-tab="Paths">Paths</LinkTo>
</li>
<li>
<LinkTo
@route="secret.metadata.versions"
@models={{array @backend @path}}
data-test-secrets-tab="Version History"
current-when={{true}}
>Version History</LinkTo>
</li>
</:tabLinks>
<:toolbarActions>
{{#if @metadata.canReadMetadata}}
<ToolbarLink @route="secret.metadata.diff">Version diff</ToolbarLink>
<ToolbarLink @route="secret.metadata.diff" @models={{array @backend @path}}>Version diff</ToolbarLink>
{{/if}}
</:toolbarActions>
</KvPageHeader>
@ -25,7 +42,7 @@
{{#each @metadata.sortedVersions as |versionData|}}
<LinkedBlock
class="list-item-row"
@params={{array "vault.cluster.secrets.backend.kv.secret.details" @metadata.path}}
@params={{array "vault.cluster.secrets.backend.kv.secret.details" @backend @metadata.path}}
@queryParams={{hash version=versionData.version}}
data-test-version-linked-block={{versionData.version}}
>
@ -80,12 +97,14 @@
<dd.Interactive
@text="View version {{versionData.version}}"
@route="secret.details"
@models={{array @backend @path}}
@query={{hash version=versionData.version}}
/>
{{#if (and @metadata.canCreateVersionData (not versionData.destroyed) (not versionData.isSecretDeleted))}}
<dd.Interactive
@text="Create new version from {{versionData.version}}"
@route="secret.details.edit"
@models={{array @backend @path}}
@query={{hash version=versionData.version}}
data-test-create-new-version-from={{versionData.version}}
/>

View File

@ -5,11 +5,33 @@
<KvPageHeader @breadcrumbs={{@breadcrumbs}} @pageTitle={{@path}}>
<:tabLinks>
<li><LinkTo @route="secret.details" data-test-secrets-tab="Secret">Secret</LinkTo></li>
<li><LinkTo @route="secret.metadata.index" data-test-secrets-tab="Metadata">Metadata</LinkTo></li>
<li><LinkTo @route="secret.paths" data-test-secrets-tab="Paths">Paths</LinkTo></li>
<li>
<LinkTo @route="secret.details" @models={{array @backend @path}} data-test-secrets-tab="Secret">Secret</LinkTo>
</li>
<li>
<LinkTo
@route="secret.metadata.index"
@models={{array @backend @path}}
data-test-secrets-tab="Metadata"
>Metadata</LinkTo>
</li>
<li>
<LinkTo
@route="secret.paths"
@models={{array @backend @path}}
data-test-secrets-tab="Paths"
@current-when={{true}}
>Paths</LinkTo>
</li>
{{#if @canReadMetadata}}
<li><LinkTo @route="secret.metadata.versions" data-test-secrets-tab="Version History">Version History</LinkTo></li>
<li>
<LinkTo
@route="secret.metadata.versions"
@models={{array @backend @path}}
data-test-secrets-tab="Version History"
>Version History
</LinkTo>
</li>
{{/if}}
</:tabLinks>
</KvPageHeader>

View File

@ -25,7 +25,7 @@ export default class KvConfigurationRoute extends Route {
super.setupController(controller, resolvedModel);
controller.breadcrumbs = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.mountConfig.id, route: 'list' },
{ label: resolvedModel.mountConfig.id, route: 'list', model: resolvedModel.engineConfig.backend },
{ label: 'configuration' },
];
}

View File

@ -32,8 +32,8 @@ export default class KvSecretsCreateRoute extends Route {
const crumbs = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path),
{ label: 'create' },
];
controller.breadcrumbs = crumbs;

View File

@ -13,7 +13,7 @@ export default class KvErrorRoute extends Route {
super.setupController(...arguments);
controller.breadcrumbs = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: this.secretMountPath.currentPath, route: 'list' },
{ label: this.secretMountPath.currentPath, route: 'list', model: this.secretMountPath.currentPath },
];
controller.mountName = this.secretMountPath.currentPath;
}

View File

@ -78,8 +78,8 @@ export default class KvSecretsListRoute extends Route {
} else {
breadcrumbsArray = [
...breadcrumbsArray,
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.pathToSecret, true),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.pathToSecret, true),
];
}

View File

@ -36,8 +36,8 @@ export default class KvSecretDetailsEditRoute extends Route {
controller.breadcrumbs = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path),
{ label: 'edit' },
];
}

View File

@ -12,8 +12,8 @@ export default class KvSecretDetailsIndexRoute extends Route {
const breadcrumbsArray = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path, true),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path, true),
];
controller.breadcrumbs = breadcrumbsArray;
}

View File

@ -13,8 +13,8 @@ export default class KvSecretMetadataDiffRoute extends Route {
super.setupController(controller, resolvedModel);
const breadcrumbsArray = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path),
{ label: 'version history', route: 'secret.metadata.versions' },
{ label: 'diff' },
];

View File

@ -14,8 +14,8 @@ export default class KvSecretMetadataEditRoute extends Route {
super.setupController(controller, resolvedModel);
const breadcrumbsArray = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path),
{ label: 'metadata', route: 'secret.metadata' },
{ label: 'edit' },
];

View File

@ -14,8 +14,8 @@ export default class KvSecretMetadataIndexRoute extends Route {
super.setupController(controller, resolvedModel);
const breadcrumbsArray = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path),
{ label: 'metadata' },
];

View File

@ -11,8 +11,8 @@ export default class KvSecretMetadataVersionsRoute extends Route {
super.setupController(controller, resolvedModel);
const breadcrumbsArray = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path),
{ label: 'version history' },
];

View File

@ -12,8 +12,8 @@ export default class KvSecretPathsRoute extends Route {
controller.breadcrumbs = [
{ label: 'secrets', route: 'secrets', linkExternal: true },
{ label: resolvedModel.backend, route: 'list' },
...breadcrumbsForSecret(resolvedModel.path),
{ label: resolvedModel.backend, route: 'list', model: resolvedModel.backend },
...breadcrumbsForSecret(resolvedModel.backend, resolvedModel.path),
{ label: 'paths' },
];
}

View File

@ -11,4 +11,5 @@
@filterValue={{this.model.filterValue}}
@failedDirectoryQuery={{this.model.failedDirectoryQuery}}
@breadcrumbs={{this.breadcrumbs}}
@currentRouteParams={{array this.model.backend this.model.pathToSecret}}
/>

View File

@ -10,4 +10,5 @@
@filterValue={{this.model.filterValue}}
@failedDirectoryQuery={{this.model.failedDirectoryQuery}}
@breadcrumbs={{this.breadcrumbs}}
@currentRouteParams={{array this.model.backend}}
/>

View File

@ -7,4 +7,5 @@
@metadata={{this.model.metadata}}
@path={{this.model.path}}
@breadcrumbs={{this.breadcrumbs}}
@backend={{this.model.backend}}
/>

View File

@ -32,8 +32,8 @@ function splitSegments(secretPath) {
* @param {boolean} lastItemCurrent
* @returns array of breadcrumbs specific to KV engine
*/
export function breadcrumbsForSecret(secretPath, lastItemCurrent = false) {
if (!secretPath) return [];
export function breadcrumbsForSecret(backend, secretPath, lastItemCurrent = false) {
if (!backend || !secretPath) return [];
const isDir = pathIsDirectory(secretPath);
const segments = splitSegments(secretPath);
@ -45,9 +45,9 @@ export function breadcrumbsForSecret(secretPath, lastItemCurrent = false) {
};
}
if (!isDir) {
return { label: segment.label, route: 'secret.details', model: segment.model };
return { label: segment.label, route: 'secret.details', models: [backend, segment.model] };
}
}
return { label: segment.label, route: 'list-directory', model: `${segment.model}/` };
return { label: segment.label, route: 'list-directory', models: [backend, `${segment.model}/`] };
});
}

View File

@ -41,60 +41,63 @@ module('Unit | Utility | kv-breadcrumbs', function () {
});
test('breadcrumbsForSecret works', function (assert) {
let results = breadcrumbsForSecret('beep/bop/boop');
let results = breadcrumbsForSecret('kv-mount', 'beep/bop/boop');
assert.deepEqual(
results,
[
{ label: 'beep', route: 'list-directory', model: 'beep/' },
{ label: 'bop', route: 'list-directory', model: 'beep/bop/' },
{ label: 'boop', route: 'secret.details', model: 'beep/bop/boop' },
{ label: 'beep', route: 'list-directory', models: ['kv-mount', 'beep/'] },
{ label: 'bop', route: 'list-directory', models: ['kv-mount', 'beep/bop/'] },
{ label: 'boop', route: 'secret.details', models: ['kv-mount', 'beep/bop/boop'] },
],
'correct when full nested path to secret'
);
results = breadcrumbsForSecret('beep/bop/boop', true);
results = breadcrumbsForSecret('kv-mount', 'beep/bop/boop', true);
assert.deepEqual(
results,
[
{ label: 'beep', route: 'list-directory', model: 'beep/' },
{ label: 'bop', route: 'list-directory', model: 'beep/bop/' },
{ label: 'beep', route: 'list-directory', models: ['kv-mount', 'beep/'] },
{ label: 'bop', route: 'list-directory', models: ['kv-mount', 'beep/bop/'] },
{ label: 'boop' },
],
'correct when full nested path to secret and last item current'
);
results = breadcrumbsForSecret('beep');
results = breadcrumbsForSecret('kv-mount', 'beep');
assert.deepEqual(
results,
[{ label: 'beep', route: 'secret.details', model: 'beep' }],
[{ label: 'beep', route: 'secret.details', models: ['kv-mount', 'beep'] }],
'correct when non-nested secret path'
);
results = breadcrumbsForSecret('beep', true);
results = breadcrumbsForSecret('kv-mount', 'beep', true);
assert.deepEqual(
results,
[{ label: 'beep' }],
'correct when non-nested secret path and last item current'
);
results = breadcrumbsForSecret('beep/bop/');
results = breadcrumbsForSecret('kv-mount', 'beep/bop/');
assert.deepEqual(
results,
[
{ label: 'beep', route: 'list-directory', model: 'beep/' },
{ label: 'bop', route: 'list-directory', model: 'beep/bop/' },
{ label: 'beep', route: 'list-directory', models: ['kv-mount', 'beep/'] },
{ label: 'bop', route: 'list-directory', models: ['kv-mount', 'beep/bop/'] },
],
'correct when path is directory'
);
results = breadcrumbsForSecret('beep/bop/', true);
results = breadcrumbsForSecret('kv-mount', 'beep/bop/', true);
assert.deepEqual(
results,
[{ label: 'beep', route: 'list-directory', model: 'beep/' }, { label: 'bop' }],
[{ label: 'beep', route: 'list-directory', models: ['kv-mount', 'beep/'] }, { label: 'bop' }],
'correct when path is directory and last item current'
);
results = breadcrumbsForSecret();
assert.deepEqual(results, [], 'fails gracefully if backend is undefined');
results = breadcrumbsForSecret('backend-only');
assert.deepEqual(results, [], 'fails gracefully if secretPath is undefined');
});
});