UI/update UI deps (#11447)

This commit is contained in:
Chelsea Shaw 2021-04-26 11:23:57 -05:00 committed by GitHub
parent 5a4151873c
commit 1810edf428
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 3391 additions and 3687 deletions

3
changelog/11447.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
ui: Update ember to latest LTS and upgrade UI dependencies
```

View File

@ -1,90 +1,6 @@
## Module Report
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/components/auth-jwt.js` at line 9
```js
/* eslint-disable ember/no-ember-testing-in-module-scope */
const WAIT_TIME = Ember.testing ? 0 : 500;
const ERROR_WINDOW_CLOSED =
'The provider window was closed before authentication was complete. Please click Sign In to try again.';
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/components/auth-jwt.js` at line 117
```js
exchangeOIDC: task(function*(event, oidcWindow) {
// in non-incognito mode we need to use a timeout because it takes time before oidcState is written to local storage.
let oidcState = Ember.testing
? event.storageArea.getItem('oidcState')
: (yield timeout(1000).then(() => event.storageArea.getItem('oidcState')));
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/routes/vault.js` at line 7
```js
import Ember from 'ember';
/* eslint-disable ember/no-ember-testing-in-module-scope */
const SPLASH_DELAY = Ember.testing ? 0 : 300;
export default Route.extend({
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/services/auth.js` at line 267
```js
checkShouldRenew: task(function*() {
while (true) {
if (Ember.testing) {
return;
}
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `lib/core/addon/components/ttl-form.js` at line 82
```js
this.set('time', parsedTime);
this.handleChange();
if (Ember.testing) {
return;
}
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/routes/vault/cluster.js` at line 78
```js
// when testing, the polling loop causes promises to never settle so acceptance tests hang
// to get around that, we just disable the poll in tests
if (Ember.testing) {
return;
}
```
### Unknown Global
**Global**: `Ember.onerror`
**Location**: `tests/helpers/wait-for-error.js` at line 5
@ -222,3 +138,73 @@ export default function waitForError(opts) {
return logout.visit();
});
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/components/auth-jwt.js` at line 9
```js
/* eslint-disable ember/no-ember-testing-in-module-scope */
const WAIT_TIME = Ember.testing ? 0 : 500;
const ERROR_WINDOW_CLOSED =
'The provider window was closed before authentication was complete. Please click Sign In to try again.';
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/components/auth-jwt.js` at line 119
```js
exchangeOIDC: task(function*(event, oidcWindow) {
// in non-incognito mode we need to use a timeout because it takes time before oidcState is written to local storage.
let oidcState = Ember.testing
? event.storageArea.getItem('oidcState')
: yield timeout(1000).then(() => event.storageArea.getItem('oidcState'));
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/routes/vault.js` at line 7
```js
import Ember from 'ember';
/* eslint-disable ember/no-ember-testing-in-module-scope */
const SPLASH_DELAY = Ember.testing ? 0 : 300;
export default Route.extend({
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/services/auth.js` at line 267
```js
checkShouldRenew: task(function*() {
while (true) {
if (Ember.testing) {
return;
}
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `lib/core/addon/components/ttl-form.js` at line 82
```js
this.set('time', parsedTime);
this.handleChange();
if (Ember.testing) {
return;
}
```

View File

@ -1,6 +1,6 @@
import AdapterError from '@ember-data/adapter/error';
import { assign } from '@ember/polyfills';
import { get, set } from '@ember/object';
import { set } from '@ember/object';
import ApplicationAdapter from './application';
import { encodePath } from 'vault/utils/path-encoding-helpers';
@ -16,7 +16,7 @@ export default ApplicationAdapter.extend({
},
findAll(store, type, sinceToken, snapshotRecordArray) {
let isUnauthenticated = get(snapshotRecordArray || {}, 'adapterOptions.unauthenticated');
let isUnauthenticated = snapshotRecordArray?.adapterOptions?.unauthenticated;
if (isUnauthenticated) {
let url = `/${this.urlPrefix()}/internal/ui/mounts`;
return this.ajax(url, 'GET', {

View File

@ -1,6 +1,5 @@
import ApplicationAdapter from './application';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import { encodePath } from 'vault/utils/path-encoding-helpers';
export default ApplicationAdapter.extend({
@ -10,7 +9,7 @@ export default ApplicationAdapter.extend({
let [path, role] = JSON.parse(id);
path = encodePath(path);
let namespace = get(snapshot, 'adapterOptions.namespace');
let namespace = snapshot?.adapterOptions.namespace;
let url = `/v1/auth/${path}/oidc/auth_url`;
let redirect_uri = `${window.location.origin}${this.router.urlFor('vault.cluster.oidc-callback', {
auth_path: path,

View File

@ -4,7 +4,7 @@ import { match, alias, or } from '@ember/object/computed';
import { assign } from '@ember/polyfills';
import { dasherize } from '@ember/string';
import Component from '@ember/component';
import { get, computed } from '@ember/object';
import { computed } from '@ember/object';
import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends';
import { task } from 'ember-concurrency';
const BACKENDS = supportedAuthBackends();
@ -101,7 +101,7 @@ export default Component.extend(DEFAULTS, {
let firstMethod = this.methodsToShow.firstObject;
if (!firstMethod) return;
// prefer backends with a path over those with a type
return get(firstMethod, 'path') || get(firstMethod, 'type');
return firstMethod.path || firstMethod.type;
},
resetDefaults() {
@ -152,9 +152,7 @@ export default Component.extend(DEFAULTS, {
}),
methodsToShow: computed('methods', function() {
let methods = this.methods || [];
let shownMethods = methods.filter(m =>
BACKENDS.find(b => get(b, 'type').toLowerCase() === get(m, 'type').toLowerCase())
);
let shownMethods = methods.filter(m => BACKENDS.find(b => b.type.toLowerCase() === m.type.toLowerCase()));
return shownMethods.length ? shownMethods : BACKENDS;
}),
@ -254,16 +252,16 @@ export default Component.extend(DEFAULTS, {
});
let backend = this.selectedAuthBackend || {};
let backendMeta = BACKENDS.find(
b => (get(b, 'type') || '').toLowerCase() === (get(backend, 'type') || '').toLowerCase()
b => (b.type || '').toLowerCase() === (backend.type || '').toLowerCase()
);
let attributes = get(backendMeta || {}, 'formAttributes') || [];
let attributes = (backendMeta || {}).formAttributes || [];
data = assign(data, this.getProperties(...attributes));
if (passedData) {
data = assign(data, passedData);
}
if (this.customPath || get(backend, 'id')) {
data.path = this.customPath || get(backend, 'id');
if (this.customPath || backend.id) {
data.path = this.customPath || backend.id;
}
return this.authenticate.unlinked().perform(backend.type, data);
},

View File

@ -1,7 +1,7 @@
import { inject as service } from '@ember/service';
import { alias, or } from '@ember/object/computed';
import Component from '@ember/component';
import { computed, get } from '@ember/object';
import { computed } from '@ember/object';
import { task } from 'ember-concurrency';
export default Component.extend({
@ -38,8 +38,8 @@ export default Component.extend({
if (this.currentUserIsRequesting) {
return 'You';
}
if (entity && get(entity, 'name')) {
return get(entity, 'name');
if (entity && entity.name) {
return entity.name;
}
return 'Someone';
}),

View File

@ -15,7 +15,7 @@
* @param {number} [defaultSpan=12] - setting for default time between start and end input dates
* @param {number} [retentionMonths=24] - setting for the retention months, which informs valid dates to query by
*/
import { computed } from '@ember/object';
import { set, computed } from '@ember/object';
import { inject as service } from '@ember/service';
import Component from '@ember/component';
import {
@ -140,8 +140,8 @@ export default Component.extend({
this.queryStart = format(initialStart, 'MM-yyyy');
}
this.start = format(initialStart, 'MM/yyyy');
this.end = format(initialEnd, 'MM/yyyy');
set(this, 'start', format(initialStart, 'MM/yyyy'));
set(this, 'end', format(initialEnd, 'MM/yyyy'));
},
actions: {

View File

@ -3,7 +3,7 @@ import { or } from '@ember/object/computed';
import { isBlank } from '@ember/utils';
import { task, waitForEvent } from 'ember-concurrency';
import Component from '@ember/component';
import { set, get } from '@ember/object';
import { set } from '@ember/object';
import FocusOnInsertMixin from 'vault/mixins/focus-on-insert';
import keys from 'vault/lib/keycodes';
@ -68,7 +68,7 @@ export default Component.extend(FocusOnInsertMixin, {
persist(method, successCallback) {
const model = this.model;
return model[method]().then(() => {
if (!get(model, 'isError')) {
if (!model.isError) {
if (this.wizard.featureState === 'role') {
this.wizard.transitionFeatureMachine('role', 'CONTINUE', this.backendType);
}

View File

@ -3,7 +3,7 @@ import { or } from '@ember/object/computed';
import { isBlank } from '@ember/utils';
import Component from '@ember/component';
import { task, waitForEvent } from 'ember-concurrency';
import { set, get } from '@ember/object';
import { set } from '@ember/object';
import FocusOnInsertMixin from 'vault/mixins/focus-on-insert';
import keys from 'vault/lib/keycodes';
@ -54,7 +54,7 @@ export default Component.extend(FocusOnInsertMixin, {
persistKey(method, successCallback) {
const key = this.key;
return key[method]().then(() => {
if (!get(key, 'isError')) {
if (!key.isError) {
if (this.wizard.featureState === 'secret') {
this.wizard.transitionFeatureMachine('secret', 'CONTINUE');
} else {

View File

@ -67,7 +67,7 @@ export default Component.extend(TRANSIT_PARAMS, {
this._super(...arguments);
// TODO figure out why get is needed here Ember Upgrade
// eslint-disable-next-line ember/no-get
if (get(this, 'selectedAction')) {
if (this.selectedAction) {
return;
}
// eslint-disable-next-line ember/no-get
@ -102,8 +102,8 @@ export default Component.extend(TRANSIT_PARAMS, {
if (!model) {
return null;
}
const backend = get(model, 'backend') || get(model, 'id');
const id = get(model, 'id');
const backend = model.backend || model.id;
const id = model.id;
return {
backend,

View File

@ -1,6 +1,6 @@
import { inject as service } from '@ember/service';
import Controller from '@ember/controller';
import { set, get } from '@ember/object';
import { set } from '@ember/object';
export default Controller.extend({
store: service(),
@ -35,7 +35,7 @@ export default Controller.extend({
model.unloadRecord();
const newModel = this.store.createRecord('ssh-sign', {
role: roleModel,
id: `${get(roleModel, 'backend')}-${get(roleModel, 'name')}`,
id: `${roleModel.backend}-${roleModel.name}`,
});
this.set('model', newModel);
},

View File

@ -1,5 +1,4 @@
import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import Mixin from '@ember/object/mixin';
import RSVP from 'rsvp';
const INIT = 'vault.cluster.init';
@ -55,22 +54,23 @@ export default Mixin.create({
},
hasKeyData() {
return !!get(this.controllerFor(INIT), 'keyData');
/* eslint-disable-next-line ember/no-controller-access-in-routes */
return !!this.controllerFor(INIT).keyData;
},
targetRouteName(transition) {
const cluster = this.clusterModel();
const isAuthed = this.authToken();
if (get(cluster, 'needsInit')) {
if (cluster.needsInit) {
return INIT;
}
if (this.hasKeyData() && this.routeName !== UNSEAL && this.routeName !== AUTH) {
return INIT;
}
if (get(cluster, 'sealed')) {
if (cluster.sealed) {
return UNSEAL;
}
if (get(cluster, 'dr.isSecondary')) {
if (cluster?.dr?.isSecondary) {
if (transition && transition.targetName === DR_REPLICATION_SECONDARY_DETAILS) {
return DR_REPLICATION_SECONDARY_DETAILS;
}
@ -87,9 +87,9 @@ export default Mixin.create({
return AUTH;
}
if (
(!get(cluster, 'needsInit') && this.routeName === INIT) ||
(!get(cluster, 'sealed') && this.routeName === UNSEAL) ||
(!get(cluster, 'dr.isSecondary') && this.routeName === DR_REPLICATION_SECONDARY) ||
(!cluster.needsInit && this.routeName === INIT) ||
(!cluster.sealed && this.routeName === UNSEAL) ||
(!cluster?.dr?.isSecondary && this.routeName === DR_REPLICATION_SECONDARY) ||
(isAuthed && this.routeName === AUTH)
) {
return CLUSTER;

View File

@ -7,6 +7,7 @@ export default Mixin.create({
modelPath: 'model',
unloadModel() {
let { modelPath } = this;
/* eslint-disable-next-line ember/no-controller-access-in-routes */
let model = this.controller.get(modelPath);
if (!model || !model.unloadRecord) {
return;

View File

@ -1,5 +1,4 @@
import Mixin from '@ember/object/mixin';
import { get } from '@ember/object';
// this mixin relies on `unload-model-route` also being used
export default Mixin.create({
@ -9,7 +8,7 @@ export default Mixin.create({
if (!model) {
return true;
}
if (get(model, 'hasDirtyAttributes')) {
if (model.hasDirtyAttributes) {
if (
window.confirm(
'You have unsaved changes. Navigating away will discard these changes. Are you sure you want to discard your changes?'

View File

@ -1,6 +1,6 @@
import Model, { attr } from '@ember-data/model';
import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { alias, or } from '@ember/object/computed';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs';
@ -203,10 +203,10 @@ export default Model.extend({
canEdit: alias('editConnectionPath.canUpdate'),
canDelete: alias('editConnectionPath.canDelete'),
resetConnectionPath: lazyCapabilities(apiPath`${'backend'}/reset/${'id'}`, 'backend', 'id'),
canReset: computed.or('resetConnectionPath.canUpdate', 'resetConnectionPath.canCreate'),
canReset: or('resetConnectionPath.canUpdate', 'resetConnectionPath.canCreate'),
rotateRootPath: lazyCapabilities(apiPath`${'backend'}/rotate-root/${'id'}`, 'backend', 'id'),
canRotateRoot: computed.or('rotateRootPath.canUpdate', 'rotateRootPath.canCreate'),
canRotateRoot: or('rotateRootPath.canUpdate', 'rotateRootPath.canCreate'),
rolePath: lazyCapabilities(apiPath`${'backend'}/role/*`, 'backend'),
staticRolePath: lazyCapabilities(apiPath`${'backend'}/static-role/*`, 'backend'),
canAddRole: computed.or('rolePath.canCreate', 'staticRolePath.canCreate'),
canAddRole: or('rolePath.canCreate', 'staticRolePath.canCreate'),
});

View File

@ -1,9 +1,8 @@
import Model, { attr } from '@ember-data/model';
import { alias } from '@ember/object/computed';
import { computed } from '@ember/object';
import fieldToAttrs from 'vault/utils/field-to-attrs';
import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
import { expandAttributeMeta } from 'vault/utils/field-to-attrs';
// these arrays define the order in which the fields will be displayed
// see

View File

@ -1,5 +1,4 @@
import Model from '@ember-data/model';
import { attr } from '@ember-data/model';
import Model, { attr } from '@ember-data/model';
import { computed } from '@ember/object';
import { apiPath } from 'vault/macros/lazy-capabilities';
import attachCapabilities from 'vault/lib/attach-capabilities';

View File

@ -48,6 +48,7 @@ export default Route.extend({
// if we have queryParams, update the namespace so that the observer can fire on the controller
if (queryParams) {
/* eslint-disable-next-line ember/no-controller-access-in-routes */
this.controllerFor('vault.cluster').set('namespaceQueryParam', queryParams.namespace || '');
}

View File

@ -75,6 +75,7 @@ export default Route.extend(ModelBoundaryRoute, ClusterRoute, {
}
yield timeout(POLL_INTERVAL_MS);
try {
/* eslint-disable-next-line ember/no-controller-access-in-routes */
yield this.controller.model.reload();
yield this.transitionToTargetRoute();
} catch (e) {

View File

@ -41,6 +41,7 @@ export default Route.extend({
// reload to make sure we have the newest info
if (this.currentModel) {
next(() => {
/* eslint-disable-next-line ember/no-controller-access-in-routes */
this.controller.get('model').reload();
});
}

View File

@ -82,6 +82,7 @@ export default Route.extend({
const { prefix } = this.paramsFor(this.routeName);
set(error, 'keyId', prefix);
/* eslint-disable-next-line ember/no-controller-access-in-routes */
const hasModel = this.controllerFor(this.routeName).get('hasModel');
// only swallow the error if we have a previous model
if (hasModel && error.httpStatus === 404) {

View File

@ -190,6 +190,7 @@ export default Route.extend({
let secret = this.secretParam();
let backend = this.enginePathParam();
let is404 = error.httpStatus === 404;
/* eslint-disable-next-line ember/no-controller-access-in-routes */
let hasModel = this.controllerFor(this.routeName).get('hasModel');
// this will occur if we've deleted something,

View File

@ -263,6 +263,7 @@ export default Route.extend(UnloadModelRoute, {
let secret = this.secretParam();
let backend = this.enginePathParam();
const preferAdvancedEdit =
/* eslint-disable-next-line ember/no-controller-access-in-routes */
this.controllerFor('vault.cluster.secrets.backend').get('preferAdvancedEdit') || false;
const backendType = this.backendType();
model.secret.setProperties({ backend });
@ -301,6 +302,7 @@ export default Route.extend(UnloadModelRoute, {
},
willTransition(transition) {
/* eslint-disable-next-line ember/no-controller-access-in-routes */
let { mode, model } = this.controller;
let version = model.get('selectedVersion');
let changed = model.changedAttributes();

View File

@ -1,11 +1,10 @@
import Route from '@ember/routing/route';
import { get } from '@ember/object';
import { tabsForAuthSection } from 'vault/helpers/tabs-for-auth-section';
export default Route.extend({
beforeModel() {
const model = this.modelFor('vault.cluster.settings.auth.configure');
const section = get(tabsForAuthSection([model]), 'firstObject.routeParams.lastObject');
const section = tabsForAuthSection([model]).firstObject.routeParams.lastObject;
return this.transitionTo('vault.cluster.settings.auth.configure.section', section);
},
});

View File

@ -29,6 +29,7 @@ export default Route.extend({
if (this.wizard.currentMachine === 'tools') {
this.wizard.transitionFeatureMachine(this.wizard.featureState, params.selected_action.toUpperCase());
}
/* eslint-disable-next-line ember/no-controller-access-in-routes */
this.controller.setProperties(params);
return true;
},

View File

@ -1,5 +1,4 @@
import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
import { get } from '@ember/object';
import ApplicationSerializer from './application';
export default ApplicationSerializer.extend(EmbeddedRecordsMixin, {
@ -9,7 +8,7 @@ export default ApplicationSerializer.extend(EmbeddedRecordsMixin, {
},
normalizeResponse(store, primaryModelClass, payload) {
let entity = get(payload, 'data.request_entity');
let entity = payload?.data?.request_entity;
if (Array.isArray(payload.data.authorizations)) {
for (let authorization of payload.data.authorizations) {
authorization.id = authorization.entity_id;

View File

@ -191,7 +191,7 @@ export default Service.extend({
}
if (!data.displayName) {
data.displayName = get(this.getTokenData(tokenName) || {}, 'displayName');
data.displayName = (this.getTokenData(tokenName) || {}).displayName;
}
tokens.addObject(tokenName);
this.set('tokens', tokens);

View File

@ -1,4 +1,3 @@
import { get } from '@ember/object';
import Service, { inject as service } from '@ember/service';
import RSVP from 'rsvp';
import ControlGroupError from 'vault/lib/control-group-error';
@ -83,7 +82,7 @@ export default Service.extend({
},
checkForControlGroup(callbackArgs, response, wasWrapTTLRequested) {
let creationPath = response && get(response, 'wrap_info.creation_path');
let creationPath = response && response?.wrap_info?.creation_path;
if (
this.version.isOSS ||
wasWrapTTLRequested ||

View File

@ -131,8 +131,8 @@ export default Store.extend({
lastPage,
nextPage: clamp(currentPage + 1, 1, lastPage),
prevPage: clamp(currentPage - 1, 1, lastPage),
total: get(dataset, 'length') || 0,
filteredTotal: get(data, 'length') || 0,
total: dataset.length || 0,
filteredTotal: data.length || 0,
};
return response;

View File

@ -1,12 +1,12 @@
<PageHeader as |p|>
<p.top>
{{key-value-header
baseKey=(hash display=model.id id=model.idForNav)
path="vault.cluster.secrets.backend.list"
mode=mode
root=root
showCurrent=true
}}
<KeyValueHeader
@baseKey={{hash display=model.id id=model.idForNav}}
@path="vault.cluster.secrets.backend.list"
@mode={{mode}}
@root={{root}}
@showCurrent={{true}}
/>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
@ -51,7 +51,7 @@
{{#if (or (eq mode 'edit') (eq mode 'create'))}}
<form onsubmit={{action "createOrUpdate" mode}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<MessageError @model={{model}} />
<NamespaceReminder @mode={{mode}} @noun="transform alphabet" />
{{#each model.attrs as |attr|}}
{{#if (and (eq attr.name 'name') (eq mode 'edit')) }}
@ -94,36 +94,26 @@
Save
{{/if}}
</button>
{{#secret-link
mode=(if (eq mode "create") "list" "show")
class="button"
secret=(concat model.idPrefix model.id)
}}
<SecretLink @mode={{if (eq mode "create") "list" "show"}} @class="button" @secret={{concat model.idPrefix model.id}}>
Cancel
{{/secret-link}}
</SecretLink>
</div>
</div>
</form>
{{else}}
{{#if model.displayErrors}}
<div class="has-top-margin-s">
{{message-error model=model}}
<MessageError @model={{model}} />
</div>
{{/if}}
<div class="box is-fullwidth is-sideless is-paddingless is-marginless">
{{#each model.attrs as |attr|}}
{{#if (eq attr.type "object")}}
{{info-table-row label=(capitalize (or attr.options.label (humanize (dasherize attr.name)))) value=(stringify (get model attr.name))}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{stringify (get model attr.name)}} />
{{else if (eq attr.type "array")}}
{{info-table-row
label=(capitalize (or attr.options.label (humanize (dasherize attr.name))))
value=(get model attr.name)
type=attr.type
isLink=(eq attr.name 'transformations')
viewAll="transformations"
}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}} @type={{attr.type}} @isLink={{eq attr.name "transformations"}} @viewAll="transformations" />
{{else}}
{{info-table-row label=(capitalize (or attr.options.label (humanize (dasherize attr.name)))) value=(get model attr.name)}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}} />
{{/if}}
{{/each}}
</div>

View File

@ -1,7 +1,7 @@
{{#if (eq mode "edit")}}
<form onsubmit={{action "onSaveChanges"}} data-test-pricing-metrics-config-form>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model errorMessage=error}}
<MessageError @model={{model}} @errorMessage={{error}} />
{{#each model.configAttrs as |attr|}}
<FormField
data-test-field
@ -20,12 +20,11 @@
>
Save
</button>
{{#link-to
"vault.cluster.metrics.config"
class="button"
}}
<LinkTo
@route="vault.cluster.metrics.config"
class="button">
Cancel
{{/link-to}}
</LinkTo>
</div>
</div>
</form>

View File

@ -3,29 +3,29 @@
<div class="field is-narrow">
<label for="start" class="is-label">From</label>
<div class="control">
{{input
type="string"
value=start
name="start"
class=(concat 'input' (unless startDate ' has-error'))
autocomplete="off"
spellcheck="false"
<Input
@type="string"
@value={{start}}
@name="start"
class={{concat "input" (unless startDate " has-error")}}
@autocomplete="off"
@spellcheck="false"
data-test-start-input="true"
}}
/>
</div>
</div>
<div class="field is-narrow">
<label for="end" class="is-label">Through</label>
<div class="control">
{{input
type="string"
value=end
name="end"
class=(concat 'input' (unless endDate ' has-error'))
autocomplete="off"
spellcheck="false"
<Input
@type="string"
@value={{end}}
@name="end"
class={{concat "input" (unless endDate " has-error")}}
@autocomplete="off"
@spellcheck="false"
data-test-end-input="true"
}}
/>
</div>
</div>
<button disabled={{error}} type="submit" class="button">Query</button>

View File

@ -1,12 +1,12 @@
<PageHeader as |p|>
<p.top>
{{key-value-header
baseKey=(hash display=model.id id=model.idForNav)
path="vault.cluster.secrets.backend.list"
mode=mode
root=root
showCurrent=true
}}
<KeyValueHeader
@baseKey={{hash display=model.id id=model.idForNav}}
@path="vault.cluster.secrets.backend.list"
@mode={{mode}}
@root={{root}}
@showCurrent={{true}}
/>
</p.top>
<p.levelLeft>
<h1 class="title is-3" data-test-secret-header="true">
@ -51,7 +51,7 @@
{{#if (or (eq mode 'edit') (eq mode 'create'))}}
<form onsubmit={{action "createOrUpdate" mode}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<MessageError @model={{model}} />
<NamespaceReminder @mode={{mode}} @noun="transform template" />
{{#each model.attrs as |attr|}}
{{#if (and (eq attr.name 'name') (eq mode 'edit')) }}
@ -94,35 +94,26 @@
Save
{{/if}}
</button>
{{#secret-link
mode=(if (eq mode "create") "list" "show")
class="button"
secret=(concat model.idPrefix model.id)
}}
<SecretLink @mode={{if (eq mode "create") "list" "show"}} @class="button" @secret={{concat model.idPrefix model.id}}>
Cancel
{{/secret-link}}
</SecretLink>
</div>
</div>
</form>
{{else}}
{{#if model.displayErrors}}
<div class="has-top-margin-s">
{{message-error model=model}}
<MessageError @model={{model}} />
</div>
{{/if}}
<div class="box is-fullwidth is-sideless is-paddingless is-marginless">
{{#each model.attrs as |attr|}}
{{#if (eq attr.type "object")}}
{{info-table-row label=(capitalize (or attr.options.label (humanize (dasherize attr.name)))) value=(stringify (get model attr.name))}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{stringify (get model attr.name)}} />
{{else if (eq attr.type "array")}}
{{info-table-row
label=(capitalize (or attr.options.label (humanize (dasherize attr.name))))
value=(get model attr.name)
type=attr.type
viewAll=attr.name
}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}} @type={{attr.type}} @viewAll={{attr.name}} />
{{else}}
{{info-table-row label=(capitalize (or attr.options.label (humanize (dasherize attr.name)))) value=(get model attr.name)}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}} />
{{/if}}
{{/each}}
</div>

View File

@ -9,30 +9,16 @@
<div class="tabs-container box is-bottomless is-marginless is-fullwidth is-paddingless">
<nav class="tabs">
<ul>
{{#link-to
"vault.cluster.metrics.index"
tagName="li"
activeClass="is-active"
}}
{{#link-to
"vault.cluster.metrics.index"
data-test-configuration-tab=false
}}
<LinkTo @route="vault.cluster.metrics.index" @tagName="li" @activeClass="is-active">
<LinkTo @route="vault.cluster.metrics.index" data-test-configuration-tab={{false}}>
Vault usage
{{/link-to}}
{{/link-to}}
{{#link-to
"vault.cluster.metrics.config"
tagName="li"
activeClass="is-active"
}}
{{#link-to
"vault.cluster.metrics.config"
data-test-configuration-tab=true
}}
</LinkTo>
</LinkTo>
<LinkTo @route="vault.cluster.metrics.config" @tagName="li" @activeClass="is-active">
<LinkTo @route="vault.cluster.metrics.config" data-test-configuration-tab={{true}}>
Configuration
{{/link-to}}
{{/link-to}}
</LinkTo>
</LinkTo>
</ul>
</nav>
</div>
@ -40,9 +26,9 @@
<Toolbar>
<ToolbarActions>
{{#if model.configPath.canUpdate}}
{{#link-to 'vault.cluster.metrics.edit' class="toolbar-link"}}
<LinkTo @route="vault.cluster.metrics.edit" class="toolbar-link">
Edit configuration
{{/link-to}}
</LinkTo>
{{/if}}
</ToolbarActions>
</Toolbar>

View File

@ -9,31 +9,17 @@
<div class="tabs-container box is-bottomless is-marginless is-fullwidth is-paddingless" data-test-pricing-metrics>
<nav class="tabs">
<ul>
{{#link-to
"vault.cluster.metrics.index"
tagName="li"
activeClass="is-active"
}}
{{#link-to
"vault.cluster.metrics.index"
data-test-usage-tab=true
}}
<LinkTo @route="vault.cluster.metrics.index" @tagName="li" @activeClass="is-active">
<LinkTo @route="vault.cluster.metrics.index" data-test-usage-tab={{true}}>
Vault usage
{{/link-to}}
{{/link-to}}
</LinkTo>
</LinkTo>
{{#if model.config.configPath.canRead}}
{{#link-to
"vault.cluster.metrics.config"
tagName="li"
activeClass="is-active"
}}
{{#link-to
"vault.cluster.metrics.config"
data-test-configuration-tab=true
}}
<LinkTo @route="vault.cluster.metrics.config" @tagName="li" @activeClass="is-active">
<LinkTo @route="vault.cluster.metrics.config" data-test-configuration-tab={{true}}>
Configuration
{{/link-to}}
{{/link-to}}
</LinkTo>
</LinkTo>
{{/if}}
</ul>
</nav>
@ -44,7 +30,7 @@
<EmptyState @title="No data is being received" @message="We haven't yet gathered enough data to display here. We collect it at the end of each month, so your data will be available on the first of next month. It will include the current namespace and all its children." />
{{else}}
<EmptyState @title="No data is being received" @message='Tracking is disabled, and no data is being collected. To turn it on, edit the configuration.'>
<p>{{#link-to 'vault.cluster.metrics.config'}}Go to configuration{{/link-to}}</p>
<p><LinkTo @route="vault.cluster.metrics.config">Go to configuration</LinkTo></p>
</EmptyState>
{{/if}}
{{else}}
@ -55,7 +41,7 @@
@type="warning"
@title="Tracking is disabled"
>
This feature is currently disabled and data is not being collected. {{#link-to 'vault.cluster.metrics.edit'}}Edit the configuration{{/link-to}} to enable tracking again.
This feature is currently disabled and data is not being collected. <LinkTo @route="vault.cluster.metrics.edit">Edit the configuration</LinkTo> to enable tracking again.
</AlertBanner>
{{/if}}
<p class="has-bottom-margin-s">The active clients metric contributes to billing. It is collected at the end of each month alongside unique entities and direct active tokens. The data below includes the current namespace and all its children.</p>

View File

@ -3,7 +3,7 @@
"packages": [
{
"name": "ember-cli",
"version": "3.20.2",
"version": "3.22.0",
"blueprints": [
{
"name": "app",

View File

@ -1,5 +1,4 @@
import Mixin from '@ember/object/mixin';
import { get } from '@ember/object';
export default Mixin.create({
queryParams: {
@ -16,7 +15,7 @@ export default Mixin.create({
this._super(...arguments);
controller.setProperties({
filter: pageFilter || '',
page: get(resolvedModel || {}, 'meta.currentPage') || 1,
page: resolvedModel?.meta?.currentPage || 1,
});
},

View File

@ -14,7 +14,6 @@
"ember-cli-babel": "*",
"ember-cli-clipboard": "*",
"ember-cli-htmlbars": "*",
"ember-cli-htmlbars-inline-precompile": "*",
"ember-cli-string-helpers": "*",
"ember-composable-helpers": "*",
"ember-concurrency": "*",

View File

@ -41,9 +41,9 @@
"devDependencies": {
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
"@babel/plugin-transform-block-scoping": "^7.12.1",
"@ember/optional-features": "^1.3.0",
"@glimmer/component": "^1.0.1",
"@glimmer/tracking": "^1.0.0",
"@ember/optional-features": "^2.0.0",
"@glimmer/component": "^1.0.2",
"@glimmer/tracking": "^1.0.2",
"@hashicorp/structure-icons": "^1.3.0",
"@storybook/ember-cli-storybook": "^0.3.0",
"Duration.js": "icholy/Duration.js#golang_compatible",
@ -71,7 +71,7 @@
"ember-auto-import": "^1.7.0",
"ember-basic-dropdown": "^1.0.0",
"ember-basic-dropdown-hover": "^0.6.0",
"ember-cli": "~3.20.2",
"ember-cli": "~3.22.0",
"ember-cli-autoprefixer": "^0.8.1",
"ember-cli-babel": "^7.23.0",
"ember-cli-browserstack": "^0.0.7",
@ -81,20 +81,19 @@
"ember-cli-deprecation-workflow": "^1.0.1",
"ember-cli-element-closest-polyfill": "^0.0.1",
"ember-cli-flash": "^1.7.2",
"ember-cli-htmlbars": "^5.2.0",
"ember-cli-htmlbars": "^5.3.1",
"ember-cli-inject-live-reload": "^2.0.2",
"ember-cli-mirage": "^1.1.8",
"ember-cli-page-object": "^1.17.0",
"ember-cli-pretender": "^3.1.1",
"ember-cli-sass": "^10.0.1",
"ember-cli-sri": "meirish/ember-cli-sri#rooturl",
"ember-cli-string-helpers": "^4.0.0",
"ember-cli-uglify": "^3.0.0",
"ember-cli-terser": "^4.0.0",
"ember-composable-helpers": "^4.3.0",
"ember-concurrency": "^1.3.0",
"ember-concurrency-test-waiter": "^0.3.2",
"ember-copy": "^1.0.0",
"ember-data": "~3.20.0",
"ember-data": "~3.22.0",
"ember-data-model-fragments": "5.0.0-beta.0",
"ember-engines": "^0.8.3",
"ember-export-application-global": "^2.0.1",
@ -108,7 +107,7 @@
"ember-promise-helpers": "^1.0.9",
"ember-qunit": "^4.6.0",
"ember-radio-button": "^2.0.1",
"ember-resolver": "^8.0.0",
"ember-resolver": "^8.0.2",
"ember-responsive": "^3.0.0-beta.3",
"ember-router-helpers": "^0.2.0",
"ember-service-worker": "meirish/ember-service-worker#configurable-scope",
@ -122,7 +121,7 @@
"escape-string-regexp": "^2.0.0",
"eslint": "^7.12.1",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-ember": "^8.9.1",
"eslint-plugin-ember": "^9.3.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.1.0",
"filesize": "^4.2.1",
@ -132,9 +131,10 @@
"loader.js": "^4.7.0",
"node-sass": "^4.10.0",
"normalize.css": "4.1.1",
"pretender": "^3.4.3",
"prettier": "~1.18.2",
"prettier-eslint-cli": "^5.0.0",
"qunit-dom": "^1.2.0",
"qunit-dom": "^1.5.0",
"route-recognizer": "^0.3.4",
"sass": "^1.29.0",
"sass-svg-uri": "^1.0.0",

View File

@ -200,13 +200,13 @@ module('Acceptance | Enterprise | control groups', function(hooks) {
}
};
test('it allows the full flow to work with a saved token', async function(assert) {
await workflow(assert, this, true);
test('it allows the full flow to work without a saved token', async function(assert) {
await workflow(assert, this);
await settled();
});
test('it allows the full flow to work without a saved token', async function(assert) {
await workflow(assert, this);
test('it allows the full flow to work with a saved token', async function(assert) {
await workflow(assert, this, true);
await settled();
});

View File

@ -119,6 +119,23 @@ module('Acceptance | Enterprise | KMIP secrets', function(hooks) {
assert.notOk(scopesPage.isEmpty, 'configuration page no longer renders empty state');
});
test('it can revoke from the credentials show page', async function(assert) {
let { path, scope, role, serial } = await generateCreds();
await settled();
await credentialsPage.visitDetail({ backend: path, scope, role, serial });
await settled();
assert.dom('[data-test-confirm-action-trigger]').exists('delete button exists');
await credentialsPage.delete().confirmDelete();
await settled();
assert.equal(
currentURL(),
`/vault/secrets/${path}/kmip/scopes/${scope}/roles/${role}/credentials`,
'redirects to the credentials list'
);
assert.ok(credentialsPage.isEmpty, 'renders an empty credentials page');
});
test('it can create a scope', async function(assert) {
let path = await mount(this);
await scopesPage.visit({ backend: path });
@ -267,19 +284,4 @@ module('Acceptance | Enterprise | KMIP secrets', function(hooks) {
assert.equal(credentialsPage.listItemLinks.length, 0, 'renders no credentials');
assert.ok(credentialsPage.isEmpty, 'renders empty');
});
test('it can revoke from the credentials show page', async function(assert) {
let { path, scope, role, serial } = await generateCreds();
await credentialsPage.visitDetail({ backend: path, scope, role, serial });
await settled();
await credentialsPage.delete().confirmDelete();
await settled();
assert.equal(
currentURL(),
`/vault/secrets/${path}/kmip/scopes/${scope}/roles/${role}/credentials`,
'redirects to the credentials list'
);
assert.ok(credentialsPage.isEmpty, 'renders an empty credentials page');
});
});

View File

@ -12,7 +12,7 @@ module('Integration | Component | form-error', function(hooks) {
await render(hbs`{{form-error}}`);
assert.equal(this.element.textContent.trim(), '');
assert.dom(this.element).hasText('');
// Template block usage:
await render(hbs`
@ -21,6 +21,6 @@ module('Integration | Component | form-error', function(hooks) {
{{/form-error}}
`);
assert.equal(this.element.textContent.trim(), 'template block text');
assert.dom(this.element).hasText('template block text');
});
});

View File

@ -1,7 +1,7 @@
import EmberObject from '@ember/object';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, findAll, click } from '@ember/test-helpers';
import { render, click } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | transform-list-item', function(hooks) {
@ -49,7 +49,7 @@ module('Integration | Component | transform-list-item', function(hooks) {
assert.dom('[data-test-secret-link="template/foo"]').exists('shows clickable list item');
await click('button.popup-menu-trigger');
assert.equal(findAll('.popup-menu-content li').length, 1, 'has one option');
assert.dom('.popup-menu-content li').exists({ count: 1 }, 'has one option');
});
test('it has details and edit menu item if read & edit capabilities', async function(assert) {
@ -72,7 +72,7 @@ module('Integration | Component | transform-list-item', function(hooks) {
assert.dom('[data-test-secret-link="alphabet/foo"]').exists('shows clickable list item');
await click('button.popup-menu-trigger');
assert.equal(findAll('.popup-menu-content li').length, 2, 'has both options');
assert.dom('.popup-menu-content li').exists({ count: 2 }, 'has both options');
});
test('it is not clickable if built-in template with all capabilities', async function(assert) {

View File

@ -11,7 +11,7 @@ module('Integration | Component | transform-role-edit', function(hooks) {
await render(hbs`{{transform-role-edit}}`);
assert.equal(this.element.textContent.trim(), '');
assert.dom(this.element).hasText('');
// Template block usage:
await render(hbs`
@ -20,6 +20,6 @@ module('Integration | Component | transform-role-edit', function(hooks) {
{{/transform-role-edit}}
`);
assert.equal(this.element.textContent.trim(), 'template block text');
assert.dom(this.element).hasText('template block text');
});
});

View File

@ -23,7 +23,7 @@ module('Integration | Helper | is-empty-value', function(hooks) {
await render(template);
assert.equal(this.element.textContent.trim(), 'Empty');
assert.dom(this.element).hasText('Empty');
});
test('it is truthy if the value evaluated is an empty string', async function(assert) {
@ -31,7 +31,7 @@ module('Integration | Helper | is-empty-value', function(hooks) {
await render(template);
assert.equal(this.element.textContent.trim(), 'Empty');
assert.dom(this.element).hasText('Empty');
});
test('it is truthy if the value evaluated is an empty object', async function(assert) {
@ -39,13 +39,13 @@ module('Integration | Helper | is-empty-value', function(hooks) {
await render(template);
assert.equal(this.element.textContent.trim(), 'Empty');
assert.dom(this.element).hasText('Empty');
});
test('it is falsy if the value evaluated is not an empty object', async function(assert) {
this.set('inputValue', nonEmptyObject);
await render(template);
assert.equal(this.element.textContent.trim(), 'Full');
assert.dom(this.element).hasText('Full');
});
});

View File

@ -3,7 +3,6 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import attachCapabilities from 'vault/lib/attach-capabilities';
import apiPath from 'vault/utils/api-path';
import { get } from '@ember/object';
let MODEL_TYPE = 'test-form-model';
@ -20,13 +19,13 @@ module('Unit | lib | attach capabilities', function(hooks) {
updatePath: apiPath`update/{'id'}`,
deletePath: apiPath`delete/{'id'}`,
});
let relationship = get(mc, 'relationshipsByName').get('updatePath');
let relationship = mc.relationshipsByName.get('updatePath');
assert.equal(relationship.key, 'updatePath', 'has updatePath relationship');
assert.equal(relationship.kind, 'belongsTo', 'kind of relationship is belongsTo');
assert.equal(relationship.type, 'capabilities', 'updatePath is a related capabilities model');
relationship = get(mc, 'relationshipsByName').get('deletePath');
relationship = mc.relationshipsByName.get('deletePath');
assert.equal(relationship.key, 'deletePath', 'has deletePath relationship');
assert.equal(relationship.kind, 'belongsTo', 'kind of relationship is belongsTo');
assert.equal(relationship.type, 'capabilities', 'deletePath is a related capabilities model');

File diff suppressed because it is too large Load Diff