mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-05 20:36:26 +02:00
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:
parent
5f4e53e5a2
commit
9efa76ac4c
@ -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>
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
@ -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);
|
||||
},
|
||||
});
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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}}"
|
||||
|
||||
@ -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}}
|
||||
|
||||
@ -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}} />
|
||||
@ -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}} />
|
||||
@ -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" />
|
||||
@ -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}}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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}}
|
||||
|
||||
@ -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}}
|
||||
/>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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' },
|
||||
];
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -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' },
|
||||
];
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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' },
|
||||
];
|
||||
|
||||
@ -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' },
|
||||
];
|
||||
|
||||
@ -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' },
|
||||
];
|
||||
|
||||
|
||||
@ -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' },
|
||||
];
|
||||
|
||||
|
||||
@ -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' },
|
||||
];
|
||||
}
|
||||
|
||||
@ -11,4 +11,5 @@
|
||||
@filterValue={{this.model.filterValue}}
|
||||
@failedDirectoryQuery={{this.model.failedDirectoryQuery}}
|
||||
@breadcrumbs={{this.breadcrumbs}}
|
||||
@currentRouteParams={{array this.model.backend this.model.pathToSecret}}
|
||||
/>
|
||||
@ -10,4 +10,5 @@
|
||||
@filterValue={{this.model.filterValue}}
|
||||
@failedDirectoryQuery={{this.model.failedDirectoryQuery}}
|
||||
@breadcrumbs={{this.breadcrumbs}}
|
||||
@currentRouteParams={{array this.model.backend}}
|
||||
/>
|
||||
@ -7,4 +7,5 @@
|
||||
@metadata={{this.model.metadata}}
|
||||
@path={{this.model.path}}
|
||||
@breadcrumbs={{this.breadcrumbs}}
|
||||
@backend={{this.model.backend}}
|
||||
/>
|
||||
@ -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}/`] };
|
||||
});
|
||||
}
|
||||
|
||||
@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user