mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 02:57:59 +00:00
UI - make engine list more consistent with the auth method list (#4598)
* remove expanding behavior from engines list and add a configuration route * use page header component, secret tab component for the template on the secret engine configuration route * move abstraction to secret-list-header and remove secret-tabs * add attrs to secret engine model and adjust mount controller code to support that * fix top level nav so that we can use the back button properly * fix tests
This commit is contained in:
5
ui/app/components/page-header-level-left.js
Normal file
5
ui/app/components/page-header-level-left.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: '',
|
||||
});
|
||||
5
ui/app/components/page-header-level-right.js
Normal file
5
ui/app/components/page-header-level-right.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: '',
|
||||
});
|
||||
5
ui/app/components/page-header-top.js
Normal file
5
ui/app/components/page-header-top.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: '',
|
||||
});
|
||||
6
ui/app/components/page-header.js
Normal file
6
ui/app/components/page-header.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: '',
|
||||
hasLevel: true,
|
||||
});
|
||||
14
ui/app/components/secret-list-header.js
Normal file
14
ui/app/components/secret-list-header.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: '',
|
||||
|
||||
// api
|
||||
isCertTab: false,
|
||||
isConfigure: false,
|
||||
baseKey: null,
|
||||
backendCrumb: null,
|
||||
model: null,
|
||||
|
||||
|
||||
});
|
||||
@@ -30,7 +30,6 @@ export default Ember.Controller.extend({
|
||||
description: null,
|
||||
default_lease_ttl: null,
|
||||
max_lease_ttl: null,
|
||||
force_no_cache: null,
|
||||
showConfig: false,
|
||||
local: false,
|
||||
sealWrap: false,
|
||||
@@ -50,7 +49,6 @@ export default Ember.Controller.extend({
|
||||
description: null,
|
||||
default_lease_ttl: null,
|
||||
max_lease_ttl: null,
|
||||
force_no_cache: null,
|
||||
local: false,
|
||||
showConfig: false,
|
||||
sealWrap: false,
|
||||
@@ -82,7 +80,6 @@ export default Ember.Controller.extend({
|
||||
selectedType: type,
|
||||
description,
|
||||
default_lease_ttl,
|
||||
force_no_cache,
|
||||
local,
|
||||
max_lease_ttl,
|
||||
sealWrap,
|
||||
@@ -92,7 +89,6 @@ export default Ember.Controller.extend({
|
||||
'selectedType',
|
||||
'description',
|
||||
'default_lease_ttl',
|
||||
'force_no_cache',
|
||||
'local',
|
||||
'max_lease_ttl',
|
||||
'sealWrap',
|
||||
@@ -112,9 +108,8 @@ export default Ember.Controller.extend({
|
||||
|
||||
if (this.get('showConfig')) {
|
||||
attrs.config = {
|
||||
default_lease_ttl,
|
||||
max_lease_ttl,
|
||||
force_no_cache,
|
||||
defaultLeaseTtl: default_lease_ttl,
|
||||
maxLeaseTtl: max_lease_ttl,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,5 +2,7 @@ import attr from 'ember-data/attr';
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
|
||||
export default Fragment.extend({
|
||||
version: attr('number'),
|
||||
version: attr('number', {
|
||||
label: 'Version',
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -3,6 +3,8 @@ import DS from 'ember-data';
|
||||
import { queryRecord } from 'ember-computed-query';
|
||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||
|
||||
import { expandAttributeMeta } from 'vault/utils/field-to-attrs';
|
||||
|
||||
const { attr } = DS;
|
||||
const { computed } = Ember;
|
||||
|
||||
@@ -16,11 +18,26 @@ export default DS.Model.extend({
|
||||
name: attr('string'),
|
||||
type: attr('string'),
|
||||
description: attr('string'),
|
||||
config: attr('object'),
|
||||
options: fragment('mount-options'),
|
||||
config: fragment('mount-config', { defaultValue: {} }),
|
||||
options: fragment('mount-options', { defaultValue: {} }),
|
||||
local: attr('boolean'),
|
||||
sealWrap: attr('boolean'),
|
||||
|
||||
formFields: [
|
||||
'type',
|
||||
'path',
|
||||
'description',
|
||||
'accessor',
|
||||
'local',
|
||||
'sealWrap',
|
||||
'config.{defaultLeaseTtl,maxLeaseTtl}',
|
||||
'options.{version}',
|
||||
],
|
||||
|
||||
attrs: computed('formFields', function() {
|
||||
return expandAttributeMeta(this, this.get('formFields'));
|
||||
}),
|
||||
|
||||
shouldIncludeInList: computed('type', function() {
|
||||
return !LIST_EXCLUDED_BACKENDS.includes(this.get('type'));
|
||||
}),
|
||||
|
||||
@@ -68,6 +68,7 @@ Router.map(function() {
|
||||
this.route('backends', { path: '/' });
|
||||
this.route('backend', { path: '/:backend' }, function() {
|
||||
this.route('index', { path: '/' });
|
||||
this.route('configuration');
|
||||
// because globs / params can't be empty,
|
||||
// we have to special-case ids of '' with thier own routes
|
||||
this.route('list-root', { path: '/list/' });
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
model() {
|
||||
return this.modelFor('vault.cluster.secrets.backend');
|
||||
},
|
||||
});
|
||||
@@ -20,8 +20,7 @@
|
||||
}
|
||||
}
|
||||
.popup-menu-trigger {
|
||||
width: 3rem;
|
||||
height: 2rem;
|
||||
min-width: auto;
|
||||
}
|
||||
.popup-menu-trigger.is-active {
|
||||
&,
|
||||
|
||||
@@ -146,7 +146,6 @@ $button-box-shadow-standard: 0 3px 1px 0 rgba($black, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-more-icon,
|
||||
&.tool-tip-trigger {
|
||||
color: $black;
|
||||
min-width: auto;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
{{/if}}
|
||||
</li>
|
||||
<li class="{{if (is-active-route (array 'vault.cluster.policies' 'vault.cluster.policy')) 'is-active'}}">
|
||||
<a href="{{href-to "vault.cluster.policies" activeClusterName current-when='vault.cluster.policies vault.cluster.policy'}}">
|
||||
<a href="{{href-to "vault.cluster.policies" "acl" current-when='vault.cluster.policies vault.cluster.policy'}}">
|
||||
Policies
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<ul>
|
||||
{{yield}}
|
||||
{{#each secretPath as |path index|}}
|
||||
<li class="{{if (is-active-route path.path path.model isExact=true) 'is-active'}}">
|
||||
<span class="sep">/</span>
|
||||
|
||||
1
ui/app/templates/components/page-header-level-left.hbs
Normal file
1
ui/app/templates/components/page-header-level-left.hbs
Normal file
@@ -0,0 +1 @@
|
||||
{{yield}}
|
||||
1
ui/app/templates/components/page-header-level-right.hbs
Normal file
1
ui/app/templates/components/page-header-level-right.hbs
Normal file
@@ -0,0 +1 @@
|
||||
{{yield}}
|
||||
15
ui/app/templates/components/page-header.hbs
Normal file
15
ui/app/templates/components/page-header.hbs
Normal file
@@ -0,0 +1,15 @@
|
||||
<header class="page-header">
|
||||
{{#if hasLevel}}
|
||||
{{yield (hash top=(component 'page-header-top'))}}
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
{{yield (hash levelLeft=(component 'page-header-level-left'))}}
|
||||
</div>
|
||||
<div class="level-right field is-grouped">
|
||||
{{yield (hash levelRight=(component 'page-header-level-right'))}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
{{yield (hash top=(component 'page-header-top'))}}
|
||||
{{/if}}
|
||||
</header>
|
||||
@@ -1,5 +1,5 @@
|
||||
{{#basic-dropdown class="popup-menu" horizontalPosition="auto-right" verticalPosition="below" onOpen=onOpen as |d|}}
|
||||
{{#d.trigger tagName="button" class=(concat "popup-menu-trigger button is-transparent " (if d.isOpen "is-active")) data-test-popup-menu-trigger=true}}
|
||||
{{#d.trigger tagName="button" class=(concat "popup-menu-trigger button is-ghost " (if d.isOpen "is-active")) data-test-popup-menu-trigger=true}}
|
||||
{{i-con
|
||||
glyph="more"
|
||||
class="has-text-black auto-width"
|
||||
|
||||
108
ui/app/templates/components/secret-list-header.hbs
Normal file
108
ui/app/templates/components/secret-list-header.hbs
Normal file
@@ -0,0 +1,108 @@
|
||||
{{#with (options-for-backend model.type) as |options|}}
|
||||
{{#page-header as |p|}}
|
||||
{{#p.top}}
|
||||
{{#key-value-header
|
||||
baseKey=baseKey
|
||||
path="vault.cluster.secrets.backend.list"
|
||||
root=backendCrumb
|
||||
}}
|
||||
<li>
|
||||
<span class="sep">/</span>
|
||||
<a href={{href-to "vault.cluster.secrets"}}>
|
||||
secrets
|
||||
</a>
|
||||
</li>
|
||||
{{/key-value-header}}
|
||||
{{/p.top}}
|
||||
{{#p.levelLeft}}
|
||||
<h1 class="title is-3">
|
||||
{{model.id}}
|
||||
<span class="tag is-outlined is-inverted has-text-grey-dark is-font-mono">
|
||||
{{or options.displayName (capitalize model.type)}}
|
||||
</span>
|
||||
{{#if (eq model.options.version 2)}}
|
||||
<span class="has-text-grey-dark has-text-weight-normal is-size-6">
|
||||
Version 2
|
||||
</span>
|
||||
{{/if}}
|
||||
</h1>
|
||||
{{/p.levelLeft}}
|
||||
{{#p.levelRight}}
|
||||
{{#unless (or isCertTab isConfigure)}}
|
||||
<div class="control">
|
||||
{{#secret-link
|
||||
mode="create"
|
||||
secret=(or baseKey.id '')
|
||||
queryParams=(query-params initialKey='')
|
||||
class="button has-icon-right is-ghost is-compact"
|
||||
data-test-secret-create=true
|
||||
}}
|
||||
{{options.create}}
|
||||
{{i-con glyph="chevron-right" size=11}}
|
||||
{{/secret-link}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{#if (or (eq model.type "aws") (eq model.type "ssh") (eq model.type "pki"))}}
|
||||
<div class="control">
|
||||
<a href={{href-to
|
||||
"vault.cluster.settings.configure-secret-backend"
|
||||
model.id
|
||||
}}
|
||||
class="button has-icon-right is-ghost is-compact"
|
||||
data-test-secret-backend-configure=true
|
||||
>
|
||||
Configure {{i-con glyph="chevron-right" size=11}}
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/p.levelRight}}
|
||||
{{/page-header}}
|
||||
{{#if options.tabs}}
|
||||
<div class="box is-bottomless is-marginless is-fullwidth is-paddingless">
|
||||
<nav class="tabs sub-nav">
|
||||
<ul>
|
||||
{{#each options.tabs as |oTab|}}
|
||||
{{#if oTab.tab}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab=oTab.tab) tagName="li" activeClass="is-active" data-test-tab=oTab.label}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab=oTab.tab)}}
|
||||
{{oTab.label}}
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{else}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab='') tagName="li" activeClass="is-active" data-test-tab=oTab.label}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab='')}}
|
||||
{{oTab.label}}
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.configuration' tagName="li" activeClass="is-active"}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.configuration' }}
|
||||
Configuration
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{{else}}
|
||||
{{!-- if there are no tabs in the options, we'll hardcode them here --}}
|
||||
<div class="box is-bottomless is-marginless is-fullwidth is-paddingless">
|
||||
<nav class="tabs sub-nav">
|
||||
<ul>
|
||||
{{#if (contains model.type (supported-secret-backends))}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' tagName="li" activeClass="is-active" current-when="vault.cluster.secrets.backend.list-root vault.cluster.secrets.backend.list"}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root'}}
|
||||
{{capitalize (pluralize options.item)}}
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.configuration' tagName="li" activeClass="is-active"}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.configuration' }}
|
||||
Configuration
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/with}}
|
||||
@@ -0,0 +1,19 @@
|
||||
{{secret-list-header model=model isConfigure=true backendCrumb=(hash label=model.id text=model.id path="vault.cluster.secrets.backend.list-root" model=model.id)}}
|
||||
|
||||
<div class="box is-fullwidth is-sideless is-paddingless is-marginless">
|
||||
{{#each model.attrs as |attr|}}
|
||||
{{#if (eq attr.type "object")}}
|
||||
{{info-table-row
|
||||
alwaysRender=true
|
||||
label=(or attr.options.label (to-label attr.name))
|
||||
value=(stringify (get model attr.name))
|
||||
}}
|
||||
{{else}}
|
||||
{{info-table-row
|
||||
alwaysRender=(not-eq attr.name 'options.version')
|
||||
label=(or attr.options.label (to-label attr.name))
|
||||
value=(get model attr.name)
|
||||
}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
@@ -1,79 +1,6 @@
|
||||
{{secret-list-header isCertTab=(eq tab "certs") model=backendModel baseKey=baseKey backendCrumb=backendCrumb}}
|
||||
|
||||
{{#with (options-for-backend backendType tab) as |options|}}
|
||||
<header class="page-header">
|
||||
{{key-value-header
|
||||
baseKey=baseKey
|
||||
path="vault.cluster.secrets.backend.list"
|
||||
root=backendCrumb
|
||||
}}
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<h1 class="title is-3">
|
||||
{{backend}}
|
||||
<span class="tag is-outlined is-inverted has-text-grey-dark is-font-mono">
|
||||
{{or options.displayName (capitalize backendType)}}
|
||||
</span>
|
||||
{{#if (eq backendModel.options.version 2)}}
|
||||
<span class="has-text-grey-dark has-text-weight-normal is-size-6">
|
||||
Version 2
|
||||
</span>
|
||||
{{/if}}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="level-right field is-grouped">
|
||||
{{#if (not-eq tab "certs")}}
|
||||
<div class="control">
|
||||
{{#secret-link
|
||||
mode="create"
|
||||
secret=(or baseKey.id '')
|
||||
queryParams=(query-params initialKey='')
|
||||
class="button has-icon-right is-ghost is-compact"
|
||||
data-test-secret-create=true
|
||||
}}
|
||||
{{options.create}}
|
||||
{{i-con glyph="chevron-right" size=11}}
|
||||
{{/secret-link}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (or (eq backendType "aws") (eq backendType "ssh") (eq backendType "pki"))}}
|
||||
<div class="control">
|
||||
<a href={{href-to
|
||||
"vault.cluster.settings.configure-secret-backend"
|
||||
backend
|
||||
}}
|
||||
class="button has-icon-right is-ghost is-compact"
|
||||
data-test-secret-backend-configure=true
|
||||
>
|
||||
Configure
|
||||
{{i-con glyph="chevron-right" size=11}}
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{{#if options.tabs}}
|
||||
<div class="box is-bottomless is-marginless is-fullwidth is-paddingless">
|
||||
<nav class="tabs sub-nav">
|
||||
<ul>
|
||||
{{#each options.tabs as |oTab|}}
|
||||
{{#if oTab.tab}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab=oTab.tab) tagName="li" activeClass="is-active" data-test-tab=oTab.label}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab=oTab.tab)}}
|
||||
{{oTab.label}}
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{else}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab='') tagName="li" activeClass="is-active" data-test-tab=oTab.label}}
|
||||
{{#link-to 'vault.cluster.secrets.backend.list-root' (query-params tab='')}}
|
||||
{{oTab.label}}
|
||||
{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
@@ -90,17 +17,15 @@
|
||||
mode=(if (eq tab 'certs') 'secrets-cert' 'secrets')
|
||||
}}
|
||||
{{#if filterFocused}}
|
||||
|
||||
|
||||
{{#if filterMatchesKey}}
|
||||
{{#unless filterIsFolder}}
|
||||
<p class="help has-text-grey is-size-8">
|
||||
<p class="input-hint">
|
||||
<kbd>Enter</kbd> to view {{filter}}
|
||||
</p>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{#if firstPartialMatch}}
|
||||
<p class="help has-text-grey is-size-8">
|
||||
<p class="input-hint">
|
||||
<kbd>Tab</kbd> to autocomplete
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
{{#linked-block
|
||||
"vault.cluster.secrets.backend.list-root"
|
||||
backend.id
|
||||
class=(concat
|
||||
'box is-sideless is-marginless has-pointer '
|
||||
(if (get this (concat backend.accessor '-open')) 'has-background-white-bis')
|
||||
)
|
||||
data-test-secret-backend-link=backend.id
|
||||
class="box is-sideless is-marginless has-pointer"
|
||||
data-test-secret-backend-row=backend.id
|
||||
}}
|
||||
<div class="level is-mobile">
|
||||
<div class="level-left">
|
||||
@@ -53,25 +50,35 @@
|
||||
</div>
|
||||
<div class="level-right is-flex is-paddingless is-marginless">
|
||||
<div class="level-item">
|
||||
<button class="button is-more-icon is-ghost" data-test-secret-backend-detail=true type="button" {{action (toggle (concat backend.accessor '-open') this)}}>
|
||||
{{i-con glyph="more" size=16 aria-label=(concat backend.path ' details')}}
|
||||
</button>
|
||||
{{#popup-menu name="engine-menu"}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
<a href="{{href-to 'vault.cluster.secrets.backend.configuration' backend.id}}">
|
||||
View Configuration
|
||||
</a>
|
||||
</li>
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled=true type="button" class="link button is-loading is-transparent"></button>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
{{/popup-menu}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if (get this (concat backend.accessor '-open'))}}
|
||||
{{partial "partials/backend-details"}}
|
||||
{{/if}}
|
||||
{{/linked-block}}
|
||||
{{/each}}
|
||||
{{#each unsupportedBackends as |backend|}}
|
||||
<div class="box is-sideless is-marginless has-background-transition {{if (get this (concat backend.accessor '-open')) 'has-background-white-bis'}}"
|
||||
<div class="box is-sideless is-marginless"
|
||||
data-test-secret-backend-row={{backend.id}}
|
||||
>
|
||||
<div class="level is-mobile">
|
||||
<div class="level-left">
|
||||
<div>
|
||||
<div class="has-text-weight-semibold">
|
||||
<div data-test-secret-path class="has-text-weight-semibold">
|
||||
{{i-con glyph="folder" size=14 class="has-text-grey-light"}} {{backend.path}}
|
||||
</div>
|
||||
<span class="tag">
|
||||
@@ -90,14 +97,19 @@
|
||||
</div>
|
||||
<div class="level-right is-flex is-paddingless is-marginless">
|
||||
<div class="level-item">
|
||||
<button class="button is-more-icon is-ghost" data-test-secret-backend-detail=true type="button" {{action (toggle (concat backend.accessor '-open') this)}}>
|
||||
{{i-con glyph="more" size=16 aria-label=(concat backend.path ' details')}}
|
||||
</button>
|
||||
{{#popup-menu name="engine-menu"}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
<a href="{{href-to 'vault.cluster.secrets.backend.configuration' backend.id}}" data-test-engine-config>
|
||||
View Configuration
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{/popup-menu}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if (get this (concat backend.accessor '-open'))}}
|
||||
{{partial "partials/backend-details"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
@@ -42,11 +42,12 @@ export const expandAttributeMeta = function(modelClass, attributeNames, namePref
|
||||
let attributeMap = map || new Map();
|
||||
modelClass.eachAttribute((name, meta) => {
|
||||
let fieldName = namePrefix ? namePrefix + name : name;
|
||||
if (meta.isFragment) {
|
||||
let maybeFragment = Ember.get(modelClass, fieldName);
|
||||
if (meta.isFragment && maybeFragment) {
|
||||
// pass the fragment and all fields that start with
|
||||
// the fragment name down to get extracted from the Fragment
|
||||
expandAttributeMeta(
|
||||
Ember.get(modelClass, fieldName),
|
||||
maybeFragment,
|
||||
fields.filter(f => f.startsWith(fieldName)),
|
||||
fieldName + '.',
|
||||
attributeMap
|
||||
@@ -60,13 +61,15 @@ export const expandAttributeMeta = function(modelClass, attributeNames, namePref
|
||||
// so we'll replace each key in `fields` with the expanded meta
|
||||
fields = fields.map(field => {
|
||||
let meta = attributeMap.get(field);
|
||||
const { type, options } = meta;
|
||||
if (meta) {
|
||||
var { type, options } = meta;
|
||||
}
|
||||
return {
|
||||
// using field name here because it is the full path,
|
||||
// name on the attribute meta will be relative to the fragment it's on
|
||||
name: field,
|
||||
type,
|
||||
options,
|
||||
type: type,
|
||||
options: options,
|
||||
};
|
||||
});
|
||||
return fields;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { test } from 'qunit';
|
||||
import moduleForAcceptance from 'vault/tests/helpers/module-for-acceptance';
|
||||
import backendListPage from 'vault/tests/pages/secrets/backends';
|
||||
|
||||
moduleForAcceptance('Acceptance | settings', {
|
||||
beforeEach() {
|
||||
@@ -36,14 +37,19 @@ test('settings', function(assert) {
|
||||
find('[data-test-flash-message]').text().trim(),
|
||||
`Successfully mounted '${type}' at '${path}'!`
|
||||
);
|
||||
let row = backendListPage.rows().findByPath(path);
|
||||
row.menu();
|
||||
});
|
||||
|
||||
andThen(() => {
|
||||
backendListPage.configLink();
|
||||
});
|
||||
|
||||
//show mount details
|
||||
click(`[data-test-secret-backend-row="${path}"] [data-test-secret-backend-detail]`);
|
||||
andThen(() => {
|
||||
assert.ok(
|
||||
find('[data-test-secret-backend-details="default-ttl"]').text().match(/100/),
|
||||
'displays the input ttl'
|
||||
currentURL(),
|
||||
'/vault/secrets/${path}/configuration',
|
||||
'navigates to the config page'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { test } from 'qunit';
|
||||
import moduleForAcceptance from 'vault/tests/helpers/module-for-acceptance';
|
||||
import page from 'vault/tests/pages/settings/mount-secret-backend';
|
||||
import listPage from 'vault/tests/pages/secrets/backends';
|
||||
import configPage from 'vault/tests/pages/secrets/backend/configuration';
|
||||
|
||||
moduleForAcceptance('Acceptance | settings/mount-secret-backend', {
|
||||
beforeEach() {
|
||||
@@ -30,13 +30,9 @@ test('it sets the ttl corrects when mounting', function(assert) {
|
||||
.maxTTLUnit('h')
|
||||
.submit();
|
||||
|
||||
listPage.visit();
|
||||
configPage.visit({backend: path});
|
||||
andThen(() => {
|
||||
listPage.links().findByPath(path).toggleDetails();
|
||||
});
|
||||
andThen(() => {
|
||||
const details = listPage.links().findByPath(path);
|
||||
assert.equal(details.defaultTTL, defaultTTLSeconds, 'shows the proper TTL');
|
||||
assert.equal(details.maxTTL, maxTTLSeconds, 'shows the proper max TTL');
|
||||
assert.equal(configPage.defaultTTL, defaultTTLSeconds, 'shows the proper TTL');
|
||||
assert.equal(configPage.maxTTL, maxTTLSeconds, 'shows the proper max TTL');
|
||||
});
|
||||
});
|
||||
|
||||
7
ui/tests/pages/secrets/backend/configuration.js
Normal file
7
ui/tests/pages/secrets/backend/configuration.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { create, visitable, text } from 'ember-cli-page-object';
|
||||
|
||||
export default create({
|
||||
visit: visitable('/vault/secrets/:backend/configuration'),
|
||||
defaultTTL: text('[data-test-row-value="Default Lease TTL"]'),
|
||||
maxTTL: text('[data-test-row-value="Max Lease TTL"]'),
|
||||
});
|
||||
@@ -1,17 +1,16 @@
|
||||
import { create, visitable, collection, text, clickable } from 'ember-cli-page-object';
|
||||
import { create, visitable, collection, clickable, text } from 'ember-cli-page-object';
|
||||
|
||||
export default create({
|
||||
visit: visitable('/vault/secrets'),
|
||||
links: collection({
|
||||
itemScope: '[data-test-secret-backend-link]',
|
||||
rows: collection({
|
||||
itemScope: '[data-test-secret-backend-row]',
|
||||
item: {
|
||||
path: text('[data-test-secret-path]'),
|
||||
toggleDetails: clickable('[data-test-secret-backend-detail]'),
|
||||
defaultTTL: text('[data-test-secret-backend-details="default-ttl"]'),
|
||||
maxTTL: text('[data-test-secret-backend-details="max-ttl"]'),
|
||||
menu: clickable('[data-test-popup-menu-trigger]'),
|
||||
},
|
||||
findByPath(path) {
|
||||
return this.toArray().findBy('path', path + '/');
|
||||
},
|
||||
}),
|
||||
configLink: clickable('[data-test-engine-config]'),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user