UI - no jquery (#6768)

* add no-jquery rule and move event listeners to ember-concurrency tasks

* remove unnecessary onchange and handleKeyDown actions

* add element.closest polyfill and convert linked-block to use native dom apis

* update pretender, fetch, page-object, add optional-features, remove ember/jquery

* turn off jquery inclusion

* remove jQuery.isPlainObject usage

* violatedDirective isn't always formatted the same

* use fetch and the ember-fetch adapter mixin

* move to fetch and lowercase headers for pretender

* display non-ember-data errors

* use new async fn test style and lowercase headers in auth service test

* setContext is not necessary with the new style tests and ember-cli-page-object - it actually triggers jquery usage

* update ember-fetch, ember-cli-pretender

* wait for permissions check

* lowercase header name in auth test

* refactor transit tests to one test per key type

* simplify pollCluster helper

* stop flakey tests by prefering the native fetch

* avoid uncaught TransitionAborted error by navigating directly to unseal

* unset model on controller after unloading it because controllers are singletons

* update yarn.lock
This commit is contained in:
Matthew Irish 2019-06-20 08:37:27 -05:00 committed by GitHub
parent 122134b207
commit 757afb4de9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 525 additions and 401 deletions

View File

@ -13,6 +13,7 @@ module.exports = {
rules: {
'no-unused-vars': ['error', { ignoreRestSiblings: true }],
'prettier/prettier': 'error',
'ember/no-jquery': 'error',
},
globals: {
TextEncoderLite: true,

View File

@ -3,13 +3,14 @@ import { assign } from '@ember/polyfills';
import { set } from '@ember/object';
import RSVP from 'rsvp';
import DS from 'ember-data';
import AdapterFetch from 'ember-fetch/mixins/adapter-fetch';
import fetch from 'fetch';
import config from '../config/environment';
const { APP } = config;
const { POLLING_URLS, NAMESPACE_ROOT_URLS } = APP;
export default DS.RESTAdapter.extend({
export default DS.RESTAdapter.extend(AdapterFetch, {
auth: service(),
namespaceService: service('namespace'),
controlGroup: service(),

View File

@ -175,15 +175,17 @@ export default Component.extend(DEFAULTS, {
handleError(e, prefixMessage = true) {
this.set('loading', false);
if (!e.errors) {
return e;
let errors;
if (e.errors) {
errors = e.errors.map(error => {
if (error.detail) {
return error.detail;
}
return error;
});
} else {
errors = [e];
}
let errors = e.errors.map(error => {
if (error.detail) {
return error.detail;
}
return error;
});
let message = prefixMessage ? 'Authentication failed: ' : '';
this.set('error', `${message}${errors.join('.')}`);
},

View File

@ -15,12 +15,12 @@ let LinkedBlockComponent = Component.extend({
encode: false,
click(event) {
const $target = this.$(event.target);
const $target = event.target;
const isAnchorOrButton =
$target.is('a') ||
$target.is('button') ||
$target.closest('button', event.currentTarget).length > 0 ||
$target.closest('a', event.currentTarget).length > 0;
$target.tagName === 'A' ||
$target.tagName === 'BUTTON' ||
$target.closest('button') ||
$target.closest('a');
if (!isAnchorOrButton) {
let params = this.get('params');
if (this.encode) {

View File

@ -1,7 +1,7 @@
import { inject as service } from '@ember/service';
import { or } from '@ember/object/computed';
import { isBlank } from '@ember/utils';
import $ from 'jquery';
import { task, waitForEvent } from 'ember-concurrency';
import Component from '@ember/component';
import { set, get } from '@ember/object';
import FocusOnInsertMixin from 'vault/mixins/focus-on-insert';
@ -42,20 +42,22 @@ export default Component.extend(FocusOnInsertMixin, {
}
},
didInsertElement() {
this._super(...arguments);
$(document).on('keyup.keyEdit', this.onEscape.bind(this));
},
willDestroyElement() {
this._super(...arguments);
const model = this.get('model');
if (get(model, 'isError')) {
model.rollbackAttributes();
if (this.model && this.model.isError) {
this.model.rollbackAttributes();
}
$(document).off('keyup.keyEdit');
},
waitForKeyUp: task(function*() {
while (true) {
let event = yield waitForEvent(document.body, 'keyup');
this.onEscape(event);
}
})
.on('didInsertElement')
.cancelOn('willDestroyElement'),
transitionToRoute() {
this.get('router').transitionTo(...arguments);
},
@ -84,18 +86,6 @@ export default Component.extend(FocusOnInsertMixin, {
},
actions: {
handleKeyDown(_, e) {
e.stopPropagation();
if (!(e.keyCode === keys.ENTER && e.metaKey)) {
return;
}
let $form = this.$('form');
if ($form.length) {
$form.submit();
}
$form = null;
},
createOrUpdate(type, event) {
event.preventDefault();
@ -112,10 +102,6 @@ export default Component.extend(FocusOnInsertMixin, {
});
},
handleChange() {
this.hasDataChanges();
},
setValue(key, event) {
set(get(this, 'model'), key, event.target.checked);
},

View File

@ -95,7 +95,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
updatePath: maybeQueryRecord(
'capabilities',
context => {
if (context.mode === 'create') {
if (!context.model || context.mode === 'create') {
return;
}
let backend = context.isV2 ? context.get('model.engine.id') : context.model.backend;
@ -116,7 +116,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
v2UpdatePath: maybeQueryRecord(
'capabilities',
context => {
if (context.mode === 'create' || context.isV2 === false) {
if (!context.model || context.mode === 'create' || context.isV2 === false) {
return;
}
let backend = context.get('model.engine.id');
@ -137,7 +137,9 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
buttonDisabled: or('requestInFlight', 'model.isFolder', 'model.flagsIsInvalid', 'hasLintError', 'error'),
modelForData: computed('isV2', 'model', function() {
return this.isV2 ? this.model.belongsTo('selectedVersion').value() : this.model;
let { model } = this;
if (!model) return null;
return this.isV2 ? model.belongsTo('selectedVersion').value() : model;
}),
basicModeDisabled: computed('secretDataIsAdvanced', 'showAdvancedMode', function() {
@ -160,6 +162,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
'model.{failedServerRead,selectedVersion.failedServerRead}',
'isV2',
function() {
if (!this.model) return;
// if the version couldn't be read from the server
if (this.isV2 && this.model.selectedVersion.failedServerRead) {
return true;

View File

@ -1,9 +1,10 @@
import { inject as service } from '@ember/service';
import { or } from '@ember/object/computed';
import { isBlank } from '@ember/utils';
import $ from 'jquery';
import Component from '@ember/component';
import { task, waitForEvent } from 'ember-concurrency';
import { set, get } from '@ember/object';
import FocusOnInsertMixin from 'vault/mixins/focus-on-insert';
import keys from 'vault/lib/keycodes';
@ -19,24 +20,22 @@ export default Component.extend(FocusOnInsertMixin, {
key: null,
requestInFlight: or('key.isLoading', 'key.isReloading', 'key.isSaving'),
init() {
this._super(...arguments);
},
didInsertElement() {
this._super(...arguments);
$(document).on('keyup.keyEdit', this.onEscape.bind(this));
},
willDestroyElement() {
this._super(...arguments);
const key = this.get('key');
if (get(key, 'isError')) {
key.rollbackAttributes();
if (this.key && this.key.isError) {
this.key.rollbackAttributes();
}
$(document).off('keyup.keyEdit');
},
waitForKeyUp: task(function*() {
while (true) {
let event = yield waitForEvent(document.body, 'keyup');
this.onEscape(event);
}
})
.on('didInsertElement')
.cancelOn('willDestroyElement'),
transitionToRoute() {
this.get('router').transitionTo(...arguments);
},
@ -69,18 +68,6 @@ export default Component.extend(FocusOnInsertMixin, {
},
actions: {
handleKeyDown(_, e) {
e.stopPropagation();
if (!(e.keyCode === keys.ENTER && e.metaKey)) {
return;
}
let $form = this.$('form');
if ($form.length) {
$form.submit();
}
$form = null;
},
createOrUpdateKey(type, event) {
event.preventDefault();
@ -101,10 +88,6 @@ export default Component.extend(FocusOnInsertMixin, {
);
},
handleChange() {
this.hasDataChanges();
},
setValueOnKey(key, event) {
set(get(this, 'key'), key, event.target.checked);
},

View File

@ -12,7 +12,7 @@ export default Controller.extend({
.then(() => {
this.model.cluster.get('leaderNode').set('sealed', true);
this.get('auth').deleteCurrentToken();
return this.transitionToRoute('vault.cluster');
return this.transitionToRoute('vault.cluster.unseal');
});
},
},

View File

@ -5,12 +5,15 @@ import Mixin from '@ember/object/mixin';
export default Mixin.create({
modelPath: 'model',
unloadModel() {
const model = this.controller.get(this.get('modelPath'));
let { modelPath } = this;
let model = this.controller.get(modelPath);
if (!model || !model.unloadRecord) {
return;
}
this.store.unloadRecord(model);
model.destroy();
// it's important to unset the model on the controller since controllers are singletons
this.controller.set(modelPath, null);
},
actions: {

View File

@ -52,14 +52,14 @@ export default Route.extend(ModelBoundaryRoute, ClusterRoute, {
}
},
beforeModel() {
async beforeModel() {
const params = this.paramsFor(this.routeName);
this.clearNonGlobalModels();
this.get('namespaceService').setNamespace(params.namespaceQueryParam);
const id = this.getClusterId(params);
if (id) {
this.get('auth').setCluster(id);
this.get('permissions').getPaths.perform();
await this.get('permissions').getPaths.perform();
return this.get('version').fetchFeatures();
} else {
return reject({ httpStatus: 404, message: 'not found', path: params.cluster_name });

View File

@ -1,9 +1,10 @@
import Ember from 'ember';
import { resolve } from 'rsvp';
import { resolve, reject } from 'rsvp';
import { assign } from '@ember/polyfills';
import $ from 'jquery';
import { isArray } from '@ember/array';
import { computed, get } from '@ember/object';
import fetch from 'fetch';
import { getOwner } from '@ember/application';
import Service, { inject as service } from '@ember/service';
import getStorage from '../lib/token-storage';
@ -86,7 +87,18 @@ export default Service.extend({
if (namespace) {
defaults.headers['X-Vault-Namespace'] = namespace;
}
return $.ajax(assign(defaults, options));
let opts = assign(defaults, options);
return fetch(url, {
method: opts.method || 'GET',
headers: opts.headers || {},
}).then(response => {
if (response.status >= 200 && response.status < 300) {
return resolve(response.json());
} else {
return reject();
}
});
},
renewCurrentToken() {

View File

@ -1,6 +1,5 @@
/*eslint-disable no-constant-condition*/
import { computed } from '@ember/object';
import { filterBy } from '@ember/object/computed';
import Service from '@ember/service';
import { task, waitForEvent } from 'ember-concurrency';
@ -9,7 +8,9 @@ export default Service.extend({
events: computed(function() {
return [];
}),
connectionViolations: filterBy('events', 'violatedDirective', 'connect-src'),
connectionViolations: computed('events.[].violatedDirective', function() {
return this.get('events').filter(e => e.violatedDirective.startsWith('connect-src'));
}),
attach() {
this.monitor.perform();

View File

@ -1,4 +1,4 @@
<form onsubmit={{action "createOrUpdate" "create"}} onchange={{action "handleChange"}}>
<form onsubmit={{action "createOrUpdate" "create"}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<NamespaceReminder @mode={{mode}} @noun="AWS role" />

View File

@ -1,4 +1,4 @@
<form onsubmit={{action "createOrUpdate" "create"}} onchange={{action "handleChange"}}>
<form onsubmit={{action "createOrUpdate" "create"}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<NamespaceReminder @mode={{mode}} @noun="PKI role" />

View File

@ -1,28 +1,30 @@
<form onsubmit={{action "createOrUpdate" "create"}} onchange={{action "handleChange"}}>
<form onsubmit={{action "createOrUpdate" "create"}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<NamespaceReminder @mode={{mode}} @noun="SSH role" />
{{#with (if (eq model.keyType 'otp') 3 4) as |numRequired|}}
{{#each (take numRequired model.attrsForKeyType) as |attr|}}
{{#unless (and (eq mode 'edit') (eq attr.name 'name'))}}
{{partial "partials/form-field-from-model"}}
{{/unless}}
{{/each}}
{{toggle-button
toggleAttr="showOptions"
toggleTarget=this
openLabel="Hide options"
closedLabel="More options"
data-test-toggle-more="true"
}}
{{#if showOptions}}
<div class="box is-marginless">
{{#each (drop numRequired model.attrsForKeyType) as |attr|}}
{{#if model.attrsForKeyType}}
{{#with (if (eq model.keyType 'otp') 3 4) as |numRequired|}}
{{#each (take numRequired model.attrsForKeyType) as |attr|}}
{{#unless (and (eq mode 'edit') (eq attr.name 'name'))}}
{{partial "partials/form-field-from-model"}}
{{/each}}
</div>
{{/if}}
{{/with}}
{{/unless}}
{{/each}}
{{toggle-button
toggleAttr="showOptions"
toggleTarget=this
openLabel="Hide options"
closedLabel="More options"
data-test-toggle-more="true"
}}
{{#if showOptions}}
<div class="box is-marginless">
{{#each (drop numRequired model.attrsForKeyType) as |attr|}}
{{partial "partials/form-field-from-model"}}
{{/each}}
</div>
{{/if}}
{{/with}}
{{/if}}
</div>
<div class="field is-grouped-split box is-fullwidth is-bottomless">
<div class="control">

View File

@ -1,4 +1,4 @@
<form onsubmit={{action "createOrUpdateKey" "create"}} onchange={{action "handleChange"}}>
<form onsubmit={{action "createOrUpdateKey" "create"}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=key}}
<NamespaceReminder @mode="create" @noun="transit key" />

View File

@ -1,4 +1,4 @@
<form onsubmit={{action "createOrUpdateKey" "create"}} onchange={{action "handleChange"}}>
<form onsubmit={{action "createOrUpdateKey" "create"}}>
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=key}}
<NamespaceReminder @mode="edit" @noun="transit key" />

View File

@ -84,21 +84,23 @@
<div class="box is-sideless is-fullwidth is-marginless">
{{message-error model=model}}
<NamespaceReminder @mode="sign" @noun="SSH key" />
{{#each (take 1 model.attrs) as |attr|}}
{{partial "partials/form-field-from-model"}}
{{/each}}
{{toggle-button
toggleAttr="showOptions"
toggleTarget=this
openLabel="Hide options"
closedLabel="More options"
}}
{{#if showOptions}}
<div class="box is-marginless">
{{#each (drop 1 model.attrs) as |attr|}}
{{partial "partials/form-field-from-model"}}
{{/each}}
</div>
{{#if model.attrs}}
{{#each (take 1 model.attrs) as |attr|}}
{{partial "partials/form-field-from-model"}}
{{/each}}
{{toggle-button
toggleAttr="showOptions"
toggleTarget=this
openLabel="Hide options"
closedLabel="More options"
}}
{{#if showOptions}}
<div class="box is-marginless">
{{#each (drop 1 model.attrs) as |attr|}}
{{partial "partials/form-field-from-model"}}
{{/each}}
</div>
{{/if}}
{{/if}}
</div>
<div class="field is-grouped box is-fullwidth is-bottomless">

View File

@ -1,18 +1,18 @@
import $ from 'jquery';
import DS from 'ember-data';
import { typeOf } from '@ember/utils';
/*
DS.attr('object')
*/
export default DS.Transform.extend({
deserialize: function(value) {
if (!$.isPlainObject(value)) {
if (typeOf(value) !== 'object') {
return {};
} else {
return value;
}
},
serialize: function(value) {
if (!$.isPlainObject(value)) {
if (typeOf(value) !== 'object') {
return {};
} else {
return value;

View File

@ -1,3 +1,3 @@
{
"jquery-integration": true
"jquery-integration": false
}

View File

@ -60,6 +60,10 @@ module.exports = function(defaults) {
'ember-test-selectors': {
strip: isProd,
},
// https://github.com/ember-cli/ember-fetch/issues/204
'ember-fetch': {
preferNative: true,
},
});
app.import('vendor/string-includes.js');

View File

@ -40,8 +40,7 @@
}
},
"devDependencies": {
"@ember/jquery": "^0.5.2",
"@ember/optional-features": "^0.6.3",
"@ember/optional-features": "^0.7.0",
"@hashicorp/structure-icons": "^1.3.0",
"Duration.js": "icholy/Duration.js#golang_compatible",
"autosize": "^4.0.0",
@ -74,12 +73,14 @@
"ember-cli-content-security-policy": "^1.0.0",
"ember-cli-dependency-checker": "^3.0.0",
"ember-cli-deprecation-workflow": "^1.0.1",
"ember-cli-element-closest-polyfill": "^0.0.1",
"ember-cli-flash": "1.7.1",
"ember-cli-htmlbars": "^3.0.0",
"ember-cli-htmlbars-inline-precompile": "^1.0.3",
"ember-cli-inject-live-reload": "^1.8.2",
"ember-cli-page-object": "^1.15.3",
"ember-cli-pretender": "^1.0.1",
"ember-cli-pretender": "^3.1.1",
"ember-cli-qunit": "^4.3.2",
"ember-cli-sass": "^9.0.0",
"ember-cli-sri": "meirish/ember-cli-sri#rooturl",
"ember-cli-string-helpers": "^1.5.0",
@ -94,7 +95,7 @@
"ember-data-model-fragments": "^3.3.0",
"ember-engines": "^0.7.0",
"ember-export-application-global": "^2.0.0",
"ember-fetch": "^6.1.0",
"ember-fetch": "^6.5.1",
"ember-inflector": "^3.0.0",
"ember-link-action": "^0.1.2",
"ember-load-initializers": "^1.1.0",

View File

@ -73,7 +73,7 @@ module('Acceptance | auth', function(hooks) {
let body = JSON.parse(lastRequest.requestBody);
if (backend.type === 'token') {
assert.ok(
Object.keys(lastRequest.requestHeaders).includes('X-Vault-Token'),
Object.keys(lastRequest.requestHeaders).includes('x-vault-token'),
'token uses vault token header'
);
} else if (backend.type === 'github') {

View File

@ -5,82 +5,81 @@ import { encodeString } from 'vault/utils/b64';
import authPage from 'vault/tests/pages/auth';
import enablePage from 'vault/tests/pages/settings/mount-secret-backend';
let generateTransitKeys = async () => {
const ts = new Date().getTime();
const keys = [
{
name: `aes-${ts}`,
type: 'aes256-gcm96',
exportable: true,
supportsEncryption: true,
},
{
name: `aes-convergent-${ts}`,
type: 'aes256-gcm96',
convergent: true,
supportsEncryption: true,
},
{
name: `chacha-${ts}`,
type: 'chacha20-poly1305',
exportable: true,
supportsEncryption: true,
},
{
name: `chacha-convergent-${ts}`,
type: 'chacha20-poly1305',
convergent: true,
supportsEncryption: true,
},
{
name: `ecdsa-${ts}`,
type: 'ecdsa-p256',
exportable: true,
supportsSigning: true,
},
{
name: `ed25519-${ts}`,
type: 'ed25519',
derived: true,
supportsSigning: true,
},
{
name: `rsa-2048-${ts}`,
type: `rsa-2048`,
supportsSigning: true,
supportsEncryption: true,
},
{
name: `rsa-4096-${ts}`,
type: `rsa-4096`,
supportsSigning: true,
supportsEncryption: true,
},
];
const keyTypes = [
{
name: ts => `aes-${ts}`,
type: 'aes256-gcm96',
exportable: true,
supportsEncryption: true,
},
{
name: ts => `aes-convergent-${ts}`,
type: 'aes256-gcm96',
convergent: true,
supportsEncryption: true,
},
{
name: ts => `chacha-${ts}`,
type: 'chacha20-poly1305',
exportable: true,
supportsEncryption: true,
},
{
name: ts => `chacha-convergent-${ts}`,
type: 'chacha20-poly1305',
convergent: true,
supportsEncryption: true,
},
{
name: ts => `ecdsa-${ts}`,
type: 'ecdsa-p256',
exportable: true,
supportsSigning: true,
},
{
name: ts => `ed25519-${ts}`,
type: 'ed25519',
derived: true,
supportsSigning: true,
},
{
name: ts => `rsa-2048-${ts}`,
type: `rsa-2048`,
supportsSigning: true,
supportsEncryption: true,
},
{
name: ts => `rsa-4096-${ts}`,
type: `rsa-4096`,
supportsSigning: true,
supportsEncryption: true,
},
];
for (let key of keys) {
await click('[data-test-secret-create]');
await fillIn('[data-test-transit-key-name]', key.name);
await fillIn('[data-test-transit-key-type]', key.type);
if (key.exportable) {
await click('[data-test-transit-key-exportable]');
}
if (key.derived) {
await click('[data-test-transit-key-derived]');
}
if (key.convergent) {
await click('[data-test-transit-key-convergent-encryption]');
}
await click('[data-test-transit-key-create]');
// link back to the list
await click('[data-test-secret-root-link]');
let generateTransitKey = async function(key, now) {
let name = key.name(now);
await click('[data-test-secret-create]');
await fillIn('[data-test-transit-key-name]', name);
await fillIn('[data-test-transit-key-type]', key.type);
if (key.exportable) {
await click('[data-test-transit-key-exportable]');
}
if (key.derived) {
await click('[data-test-transit-key-derived]');
}
if (key.convergent) {
await click('[data-test-transit-key-convergent-encryption]');
}
await click('[data-test-transit-key-create]');
await settled();
return keys;
// link back to the list
await click('[data-test-secret-root-link]');
await settled();
return name;
};
const testEncryption = async (assert, keyName) => {
const testConvergentEncryption = async function(assert, keyName) {
const tests = [
// raw bytes for plaintext and context
{
@ -204,14 +203,17 @@ const testEncryption = async (assert, keyName) => {
await click('[data-test-transit-b64-toggle="context"]');
}
await click('[data-test-button-encrypt]');
await settled();
if (testCase.assertAfterEncrypt) {
testCase.assertAfterEncrypt(keyName);
}
await click('[data-test-transit-action-link="decrypt"]');
await settled();
if (testCase.assertBeforeDecrypt) {
testCase.assertBeforeDecrypt(keyName);
}
await click('[data-test-button-decrypt]');
await settled();
if (testCase.assertAfterDecrypt) {
if (testCase.decodeAfterDecrypt) {
@ -225,56 +227,58 @@ const testEncryption = async (assert, keyName) => {
};
module('Acceptance | transit', function(hooks) {
setupApplicationTest(hooks);
let path;
let now;
hooks.beforeEach(async function() {
await authPage.login();
const now = new Date().getTime();
hooks.transitPath = `transit-${now}`;
now = new Date().getTime();
path = `transit-${now}`;
await enablePage.enable('transit', hooks.transitPath);
// create a bunch of different kinds of keys
hooks.transitKeys = await generateTransitKeys();
await enablePage.enable('transit', path);
await settled();
});
test('transit backend', async function(assert) {
assert.expect(47);
for (let [index, key] of hooks.transitKeys.entries()) {
await visit(`vault/secrets/${hooks.transitPath}/show/${key.name}`);
if (index === 0) {
await click('[data-test-transit-link="versions"]');
assert
.dom('[data-test-transit-key-version-row]')
.exists({ count: 1 }, `${key.name}: only one key version`);
await click('[data-test-transit-key-rotate] button');
await click('[data-test-confirm-button]');
assert
.dom('[data-test-transit-key-version-row]')
.exists({ count: 2 }, `${key.name}: two key versions after rotate`);
}
for (let key of keyTypes) {
test(`transit backend: ${key.type}`, async function(assert) {
let name = await generateTransitKey(key, now);
await visit(`vault/secrets/${path}/show/${name}`);
await settled();
await click('[data-test-transit-link="versions"]');
// wait for capabilities
await settled();
assert.dom('[data-test-transit-key-version-row]').exists({ count: 1 }, `${name}: only one key version`);
await click('[data-test-confirm-action-trigger');
await click('[data-test-confirm-button]');
// wait for rotate call
await settled();
assert
.dom('[data-test-transit-key-version-row]')
.exists({ count: 2 }, `${name}: two key versions after rotate`);
await click('[data-test-transit-key-actions-link]');
await settled();
assert.ok(
currentURL().startsWith(`/vault/secrets/${hooks.transitPath}/actions/${key.name}`),
`${key.name}: navigates to tranist actions`
currentURL().startsWith(`/vault/secrets/${path}/actions/${name}`),
`${name}: navigates to tranist actions`
);
assert.ok(
find('[data-test-transit-key-version-select]'),
`${name}: the rotated key allows you to select versions`
);
if (index === 0) {
assert.ok(
find('[data-test-transit-key-version-select]'),
`${key.name}: the rotated key allows you to select versions`
);
}
if (key.exportable) {
assert.ok(
find('[data-test-transit-action-link="export"]'),
`${key.name}: exportable key has a link to export action`
`${name}: exportable key has a link to export action`
);
} else {
assert
.dom('[data-test-transit-action-link="export"]')
.doesNotExist(`${key.name}: non-exportable key does not link to export action`);
.doesNotExist(`${name}: non-exportable key does not link to export action`);
}
if (key.convergent && key.supportsEncryption) {
await testEncryption(assert, key.name);
await testConvergentEncryption(assert, name);
}
}
});
await settled();
});
}
});

View File

@ -1,13 +1,8 @@
import { run } from '@ember/runloop';
import { registerAsyncHelper } from '@ember/test';
export function pollCluster(owner) {
const clusterRoute = owner.lookup('route:vault/cluster');
const store = owner.lookup('service:store');
return run(() => {
return clusterRoute.controller.model.reload();
return store.peekAll('cluster').firstObject.reload();
});
}
registerAsyncHelper('pollCluster', function(app) {
pollCluster(app.__container__);
});

View File

@ -31,12 +31,6 @@ module('Integration | Component | auth-config-form options', function(hooks) {
this.owner.lookup('service:flash-messages').registerTypes(['success']);
this.owner.register('service:router', routerService);
this.router = this.owner.lookup('service:router');
component.setContext(this);
});
hooks.afterEach(function() {
component.removeContext();
});
test('it submits data correctly', async function(assert) {

View File

@ -1,12 +1,12 @@
import { later, run } from '@ember/runloop';
import EmberObject from '@ember/object';
import { resolve } from 'rsvp';
import $ from 'jquery';
import Service from '@ember/service';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, settled } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import fetch from 'fetch';
import sinon from 'sinon';
import Pretender from 'pretender';
import { create } from 'ember-cli-page-object';
@ -15,8 +15,8 @@ import authForm from '../../pages/components/auth-form';
const component = create(authForm);
const authService = Service.extend({
authenticate() {
return $.getJSON('http://localhost:2000');
async authenticate() {
return fetch('http://localhost:2000');
},
setLastFetch() {},
});
@ -204,7 +204,7 @@ module('Integration | Component | auth form', function(hooks) {
this.post('/v1/sys/wrapping/unwrap', () => {
return [
200,
{ 'Content-Type': 'application/json' },
{ 'content-type': 'application/json' },
JSON.stringify({
auth: {
client_token: '12345',
@ -222,7 +222,7 @@ module('Integration | Component | auth form', function(hooks) {
await settled();
assert.equal(server.handledRequests[0].url, '/v1/sys/wrapping/unwrap', 'makes call to unwrap the token');
assert.equal(
server.handledRequests[0].requestHeaders['X-Vault-Token'],
server.handledRequests[0].requestHeaders['x-vault-token'],
wrappedToken,
'uses passed wrapped token for the unwrap'
);

View File

@ -29,7 +29,6 @@ module('Integration | Component | config pki ca', function(hooks) {
hooks.beforeEach(function() {
this.server = apiStub();
component.setContext(this);
this.owner.lookup('service:flash-messages').registerTypes(['success']);
this.owner.register('service:store', storeStub);
this.storeService = this.owner.lookup('service:store');
@ -37,7 +36,6 @@ module('Integration | Component | config pki ca', function(hooks) {
hooks.afterEach(function() {
this.server.shutdown();
component.removeContext();
});
const config = function(pem) {

View File

@ -12,14 +12,9 @@ module('Integration | Component | config pki', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
this.owner.lookup('service:flash-messages').registerTypes(['success']);
});
hooks.afterEach(function() {
component.removeContext();
});
const config = function(saveFn) {
return {
save: saveFn,

View File

@ -10,14 +10,6 @@ const component = create(uiPanel);
module('Integration | Component | console/ui panel', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
});
hooks.afterEach(function() {
component.removeContext();
});
test('it renders', async function(assert) {
await render(hbs`{{console/ui-panel}}`);
assert.ok(component.hasInput);

View File

@ -41,14 +41,9 @@ module('Integration | Component | control group success', function(hooks) {
this.owner.register('service:router', routerService);
this.owner.register('service:store', storeService);
this.router = this.owner.lookup('service:router');
component.setContext(this);
});
});
hooks.afterEach(function() {
component.removeContext();
});
const MODEL = {
approved: false,
requestPath: 'foo/bar',

View File

@ -25,17 +25,12 @@ module('Integration | Component | control group', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
this.owner.register('service:auth', authService);
this.owner.register('service:control-group', controlGroupService);
this.controlGroup = this.owner.lookup('service:controlGroup');
this.auth = this.owner.lookup('service:auth');
});
hooks.afterEach(function() {
component.removeContext();
});
const setup = (modelData = {}, authData = {}) => {
let modelDefaults = {
approved: false,

View File

@ -37,14 +37,9 @@ module('Integration | Component | edit form', function(hooks) {
run(() => {
this.owner.unregister('service:flash-messages');
this.owner.register('service:flash-messages', flash);
component.setContext(this);
});
});
hooks.afterEach(function() {
component.removeContext();
});
test('it renders', async function(assert) {
let model = createModel();
this.set('model', model);

View File

@ -9,14 +9,6 @@ const component = create(copyButton);
module('Integration | Component | hover copy button', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
});
hooks.afterEach(function() {
component.removeContext();
});
// ember-cli-clipboard helpers don't like the new style
skip('it shows success message in tooltip', async function(assert) {
this.set('copyValue', 'foo');

View File

@ -14,14 +14,9 @@ module('Integration | Component | identity/item details', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
this.owner.lookup('service:flash-messages').registerTypes(['success']);
});
hooks.afterEach(function() {
component.removeContext();
});
test('it renders the disabled warning', async function(assert) {
let model = EmberObject.create({
save() {

View File

@ -12,14 +12,6 @@ const component = create(kvObjectEditor);
module('Integration | Component | kv object editor', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
});
hooks.afterEach(function() {
component.removeContext();
});
test('it renders with no initial value', async function(assert) {
let spy = sinon.spy();
this.set('onChange', spy);

View File

@ -10,14 +10,6 @@ const component = create(maskedInput);
module('Integration | Component | masked input', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
});
hooks.afterEach(function() {
component.removeContext();
});
const hasClass = (classString = '', classToFind) => {
return classString.split(' ').includes(classToFind);
};

View File

@ -16,13 +16,11 @@ module('Integration | Component | mount backend form', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
this.owner.lookup('service:flash-messages').registerTypes(['success', 'danger']);
this.server = apiStub();
});
hooks.afterEach(function() {
component.removeContext();
this.server.shutdown();
});

View File

@ -10,14 +10,6 @@ const component = create(navHeader);
module('Integration | Component | nav header', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
});
hooks.afterEach(function() {
component.removeContext();
});
test('it renders', async function(assert) {
await render(hbs`
{{#nav-header as |h|}}

View File

@ -10,14 +10,6 @@ const component = create(radialProgress);
module('Integration | Component | radial progress', function(hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function() {
component.setContext(this);
});
hooks.afterEach(function() {
component.removeContext();
});
test('it renders', async function(assert) {
// We have to manually round the circumference, strokeDash, and strokeDashOffset because
// ie11 truncates decimals differently than other browsers.

View File

@ -129,8 +129,8 @@ module('Integration | Service | auth', function(hooks) {
this.server = new Pretender(function() {
this.get('/v1/auth/token/lookup-self', function(request) {
let resp = copy(ROOT_TOKEN_RESPONSE, true);
resp.id = request.requestHeaders['X-Vault-Token'];
resp.data.id = request.requestHeaders['X-Vault-Token'];
resp.id = request.requestHeaders['x-vault-token'];
resp.data.id = request.requestHeaders['x-vault-token'];
return [200, {}, resp];
});
this.post('/v1/auth/userpass/login/:username', function(request) {
@ -205,8 +205,7 @@ module('Integration | Service | auth', function(hooks) {
});
});
test('token authentication: root token in ember development environment', function(assert) {
let done = assert.async();
test('token authentication: root token in ember development environment', async function(assert) {
let self = this;
let service = this.owner.factoryFor('service:auth').create({
storage(tokenName) {
@ -222,30 +221,26 @@ module('Integration | Service | auth', function(hooks) {
},
environment: () => 'development',
});
run(() => {
service.authenticate({ clusterId: '1', backend: 'token', data: { token: 'test' } }).then(() => {
const clusterTokenName = service.get('currentTokenName');
const clusterToken = service.get('currentToken');
const authData = service.get('authData');
await service.authenticate({ clusterId: '1', backend: 'token', data: { token: 'test' } });
const clusterTokenName = service.get('currentTokenName');
const clusterToken = service.get('currentToken');
const authData = service.get('authData');
const expectedTokenName = `${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`;
assert.equal('test', clusterToken, 'token is saved properly');
assert.equal(
`${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`,
clusterTokenName,
'token name is saved properly'
);
assert.equal('token', authData.backend.type, 'backend is saved properly');
assert.equal(
ROOT_TOKEN_RESPONSE.data.display_name,
authData.displayName,
'displayName is saved properly'
);
assert.ok(this.store.keys().includes(expectedTokenName), 'root token is stored in the store');
assert.equal(this.memStore.keys().length, 0, 'mem storage is empty');
done();
});
});
const expectedTokenName = `${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`;
assert.equal('test', clusterToken, 'token is saved properly');
assert.equal(
`${TOKEN_PREFIX}${ROOT_PREFIX}${TOKEN_SEPARATOR}1`,
clusterTokenName,
'token name is saved properly'
);
assert.equal('token', authData.backend.type, 'backend is saved properly');
assert.equal(
ROOT_TOKEN_RESPONSE.data.display_name,
authData.displayName,
'displayName is saved properly'
);
assert.ok(this.store.keys().includes(expectedTokenName), 'root token is stored in the store');
assert.equal(this.memStore.keys().length, 0, 'mem storage is empty');
});
test('github authentication', function(assert) {
@ -313,8 +308,8 @@ module('Integration | Service | auth', function(hooks) {
this.server.map(function() {
this.get('/v1/auth/token/lookup-self', function(request) {
let resp = copy(tokenResp, true);
resp.id = request.requestHeaders['X-Vault-Token'];
resp.data.id = request.requestHeaders['X-Vault-Token'];
resp.id = request.requestHeaders['x-vault-token'];
resp.data.id = request.requestHeaders['x-vault-token'];
return [200, {}, resp];
});
});

View File

@ -1158,20 +1158,10 @@
lodash "^4.17.11"
to-fast-properties "^2.0.0"
"@ember/jquery@^0.5.2":
version "0.5.2"
resolved "https://registry.yarnpkg.com/@ember/jquery/-/jquery-0.5.2.tgz#fe312c03ada0022fa092d23f7cd7e2eb0374b53a"
integrity sha1-/jEsA62gAi+gktI/fNfi6wN0tTo=
dependencies:
broccoli-funnel "^2.0.1"
ember-cli-babel "^6.6.0"
jquery "^3.3.1"
resolve "^1.7.1"
"@ember/optional-features@^0.6.3":
version "0.6.4"
resolved "https://registry.yarnpkg.com/@ember/optional-features/-/optional-features-0.6.4.tgz#8199f853c1781234fcb1f05090cddd0b822bff69"
integrity sha512-nKmKxMk+Q/BGE8cmfq8KTHnYHVgrU3GHhy/eZ/OTj/fUvzXZhxaEVFOfAXssiOzV3FOQDJjznpbua2TEtHaQRw==
"@ember/optional-features@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@ember/optional-features/-/optional-features-0.7.0.tgz#f65a858007020ddfb8342f586112750c32abd2d9"
integrity sha512-qLXvL/Kq/COb43oQmCrKx7Fy8k1XJDI2RlgbCnZHH26AGVgJT/sZugx1A2AIxKdamtl/Mi+rQSjGIuscSjqjDw==
dependencies:
chalk "^2.3.0"
co "^4.6.0"
@ -1190,6 +1180,16 @@
ember-cli-babel "^6.16.0"
ember-compatibility-helpers "^1.0.0"
"@ember/test-helpers@^0.7.26":
version "0.7.27"
resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-0.7.27.tgz#c622cabd0cbb95b34efc1e1b6274ab5a14edc138"
integrity sha512-AQESk0FTFxRY6GyZ8PharR4SC7Fju0rXqNkfNYIntAjzefZ8xEqEM4iXDj5h7gAvfx/8dA69AQ9+p7ubc+KvJg==
dependencies:
broccoli-funnel "^2.0.1"
ember-assign-polyfill "~2.4.0"
ember-cli-babel "^6.12.0"
ember-cli-htmlbars-inline-precompile "^1.0.0"
"@ember/test-helpers@^1.3.1", "@ember/test-helpers@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-1.5.0.tgz#a480181c412778294e317c256d04ca52e63c813a"
@ -1985,6 +1985,11 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
"@types/symlink-or-copy@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz#4151a81b4052c80bc2becbae09f3a9ec010a9c7a"
integrity sha512-Lja2xYuuf2B3knEsga8ShbOdsfNOtzT73GyJmZyY7eGl2+ajOqrs8yM5ze0fsSoYwvA6bw7/Qr7OZ7PEEmYwWg==
"@types/tmp@^0.0.33":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
@ -2290,6 +2295,11 @@
"@webassemblyjs/wast-parser" "1.8.5"
"@xtuc/long" "4.2.2"
"@xg-wang/whatwg-fetch@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@xg-wang/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#f7b222c012a238e7d6e89ed3d72a1e0edb58453d"
integrity sha512-ULtqA6L75RLzTNW68IiOja0XYv4Ebc3OGMzfia1xxSEMpD0mk/pMvkQX0vbCFyQmKc5xGp80Ms2WiSlXLh8hbA==
"@xtuc/ieee754@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@ -2330,6 +2340,11 @@ abortcontroller-polyfill@^1.1.9:
resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.1.9.tgz#9fefe359fda2e9e0932dc85e6106453ac393b2da"
integrity sha512-omvG7zOHIs3BphdH62Kh3xy8nlftAsTyp7PDa9EmC3Jz9pa6sZFYk7UhNgu9Y4sIBhj6jF0RgeFZYvPnsP5sBw==
abortcontroller-polyfill@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.3.0.tgz#de69af32ae926c210b7efbcc29bf644ee4838b00"
integrity sha512-lbWQgf+eRvku3va8poBlDBO12FigTQr9Zb7NIjXrePrhxWVKdCP2wbDl1tLDaYa18PWTom3UEWwdH13S46I+yA==
accepts@~1.3.4, accepts@~1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
@ -4499,7 +4514,7 @@ broccoli-kitchen-sink-helpers@^0.3.1:
glob "^5.0.10"
mkdirp "^0.5.1"
broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.1.0, broccoli-merge-trees@^1.1.1, broccoli-merge-trees@^1.2.1:
broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.1.0, broccoli-merge-trees@^1.1.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-1.2.4.tgz#a001519bb5067f06589d91afa2942445a2d0fdb5"
integrity sha1-oAFRm7UGfwZYnZGvopQkRaLQ/bU=
@ -4607,6 +4622,25 @@ broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.2.0:
symlink-or-copy "^1.0.1"
walk-sync "^0.3.1"
broccoli-persistent-filter@^2.1.1:
version "2.2.3"
resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-2.2.3.tgz#63dbd7ff05b6d7dcfdefd75238e1097370ac7467"
integrity sha512-WSq6S9lC78LZ2T6L8s+NueEDuWdVSDiwjH8XbHo4ocL7V5fZLXupxvnPWtoH2Jp20j6/nvznTkgKJC4g70JVdA==
dependencies:
async-disk-cache "^1.2.1"
async-promise-queue "^1.0.3"
broccoli-plugin "^1.0.0"
fs-tree-diff "^2.0.0"
hash-for-dep "^1.5.0"
heimdalljs "^0.2.1"
heimdalljs-logger "^0.1.7"
mkdirp "^0.5.1"
promise-map-series "^0.2.1"
rimraf "^2.6.1"
rsvp "^4.7.0"
symlink-or-copy "^1.0.1"
walk-sync "^1.0.0"
broccoli-persistent-filter@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-2.2.2.tgz#e0180e75ede5dd05d4c702f24f6c049e93fba915"
@ -4736,6 +4770,26 @@ broccoli-stew@^2.0.0:
symlink-or-copy "^1.2.0"
walk-sync "^0.3.0"
broccoli-stew@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-2.1.0.tgz#ba73add17fda3b9b01d8cfb343a8b613b7136a0a"
integrity sha512-tgCkuTWYl4uf7k7ib2D79KFEj2hCgnTUNPMnrCoAha0/4bywcNccmaZVWtL9Ex37yX5h5eAbnM/ak2ULoMwSSw==
dependencies:
broccoli-debug "^0.6.5"
broccoli-funnel "^2.0.0"
broccoli-merge-trees "^3.0.1"
broccoli-persistent-filter "^2.1.1"
broccoli-plugin "^1.3.1"
chalk "^2.4.1"
debug "^3.1.0"
ensure-posix-path "^1.0.1"
fs-extra "^6.0.1"
minimatch "^3.0.4"
resolve "^1.8.1"
rsvp "^4.8.4"
symlink-or-copy "^1.2.0"
walk-sync "^0.3.3"
broccoli-string-replace@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/broccoli-string-replace/-/broccoli-string-replace-0.1.2.tgz#1ed92f85680af8d503023925e754e4e33676b91f"
@ -4919,6 +4973,15 @@ browserslist@^3.2.6:
caniuse-lite "^1.0.30000844"
electron-to-chromium "^1.3.47"
browserslist@^4.0.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.0.tgz#5274028c26f4d933d5b1323307c1d1da5084c9ff"
integrity sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg==
dependencies:
caniuse-lite "^1.0.30000967"
electron-to-chromium "^1.3.133"
node-releases "^1.1.19"
browserslist@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.2.1.tgz#257a24c879d1cd4016348eee5c25de683260b21d"
@ -5135,6 +5198,13 @@ calculate-cache-key-for-tree@^1.1.0:
dependencies:
json-stable-stringify "^1.0.1"
calculate-cache-key-for-tree@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/calculate-cache-key-for-tree/-/calculate-cache-key-for-tree-2.0.0.tgz#7ac57f149a4188eacb0a45b210689215d3fef8d6"
integrity sha512-Quw8a6y8CPmRd6eU+mwypktYCwUcf8yVFIRbNZ6tPQEckX9yd+EBVEPC/GSZZrMWH9e7Vz4pT7XhpmyApRByLQ==
dependencies:
json-stable-stringify "^1.0.1"
call-limit@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.0.tgz#6fd61b03f3da42a2cd0ec2b60f02bd0e71991fea"
@ -5238,6 +5308,21 @@ can-symlink@^1.0.0:
dependencies:
tmp "0.0.28"
caniuse-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==
dependencies:
browserslist "^4.0.0"
caniuse-lite "^1.0.0"
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000967:
version "1.0.30000969"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000969.tgz#7664f571f2072657bde70b00a1fc1ba41f1942a9"
integrity sha512-Kus0yxkoAJgVc0bax7S4gLSlFifCa7MnSZL9p9VuS/HIKEL4seaqh28KIQAAO50cD/rJ5CiJkJFapkdDAlhFxQ==
caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000844:
version "1.0.30000885"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz#e889e9f8e7e50e769f2a49634c932b8aee622984"
@ -6997,6 +7082,11 @@ electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.113:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9"
integrity sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==
electron-to-chromium@^1.3.133:
version "1.3.135"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.135.tgz#f5799b95f2bcd8de17cde47d63392d83a4477041"
integrity sha512-xXLNstRdVsisPF3pL3H9TVZo2XkMILfqtD6RiWIUmDK2sFX1Bjwqmd8LBp0Kuo2FgKO63JXPoEVGm8WyYdwP0Q==
electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.47:
version "1.3.64"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.64.tgz#39f5a93bf84ab7e10cfbb7522ccfc3f1feb756cf"
@ -7012,6 +7102,11 @@ elegant-spinner@^1.0.1:
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=
element-closest@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/element-closest/-/element-closest-2.0.2.tgz#72a740a107453382e28df9ce5dbb5a8df0f966ec"
integrity sha1-cqdAoQdFM4LijfnOXbtajfD5Zuw=
elliptic@^6.0.0:
version "6.4.1"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a"
@ -7071,6 +7166,14 @@ ember-assign-polyfill@^2.5.0, ember-assign-polyfill@^2.6.0:
ember-cli-babel "^6.16.0"
ember-cli-version-checker "^2.0.0"
ember-assign-polyfill@~2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/ember-assign-polyfill/-/ember-assign-polyfill-2.4.0.tgz#acb00466f7d674b3e6b030acfe255b3b1f6472e1"
integrity sha512-0SnGQb9CenRqbZdIa1KFsEjT+1ijGWfAbCSaDbg5uVa5l6HPdppuTzOXK6sfEQMsd2nbrp27QWFy7W5VX6l4Ag==
dependencies:
ember-cli-babel "^6.6.0"
ember-cli-version-checker "^2.0.0"
ember-auto-import@^1.2.3:
version "1.2.13"
resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.2.13.tgz#8f6f5d1c64e173f9093dd0c5031dc1d446b7cff1"
@ -7336,6 +7439,17 @@ ember-cli-deprecation-workflow@^1.0.1:
broccoli-plugin "^1.3.1"
ember-debug-handlers-polyfill "^1.1.1"
ember-cli-element-closest-polyfill@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/ember-cli-element-closest-polyfill/-/ember-cli-element-closest-polyfill-0.0.1.tgz#cc4d09120acc8a655e77a288ce929d4691d2c80a"
integrity sha512-LBYICCsG1WIhsieUoZndW5LQyuz7DtnXYgGrH9APuwR7qYsEdXJt5Uv6Pvu211GY2EnuNtJ7V24ZhFGCFu1dQg==
dependencies:
broccoli-funnel "^2.0.1"
caniuse-api "^3.0.0"
element-closest "^2.0.2"
ember-cli-babel "^6.16.0"
fastboot-transform "^0.1.3"
ember-cli-flash@1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/ember-cli-flash/-/ember-cli-flash-1.7.1.tgz#0b9d2464d80144df0c65e928b6fc006259ef6a58"
@ -7350,6 +7464,17 @@ ember-cli-get-component-path-option@^1.0.0:
resolved "https://registry.yarnpkg.com/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz#0d7b595559e2f9050abed804f1d8eff1b08bc771"
integrity sha1-DXtZVVni+QUKvtgE8djv8bCLx3E=
ember-cli-htmlbars-inline-precompile@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars-inline-precompile/-/ember-cli-htmlbars-inline-precompile-1.0.5.tgz#312e050c9e3dd301c55fb399fd706296cd0b1d6a"
integrity sha512-/CNEqPxroIcbY6qejrt704ZaghHLCntZKYLizFfJ2esirXoJx6fuYKBY1YyJ8GOgjfbHHKjBZuK4vFFJpkGqkQ==
dependencies:
babel-plugin-htmlbars-inline-precompile "^0.2.5"
ember-cli-version-checker "^2.1.2"
hash-for-dep "^1.2.3"
heimdalljs-logger "^0.1.9"
silent-error "^1.1.0"
ember-cli-htmlbars-inline-precompile@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars-inline-precompile/-/ember-cli-htmlbars-inline-precompile-1.0.3.tgz#332ff96c06fc522965162f1090d78a615379c3c2"
@ -7486,15 +7611,27 @@ ember-cli-preprocess-registry@^3.1.2:
process-relative-require "^1.0.0"
silent-error "^1.0.0"
ember-cli-pretender@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ember-cli-pretender/-/ember-cli-pretender-1.0.1.tgz#35540babddef6f2778e91c627d190c73505103cd"
integrity sha1-NVQLq93vbyd46RxifRkMc1BRA80=
ember-cli-pretender@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/ember-cli-pretender/-/ember-cli-pretender-3.1.1.tgz#289c41683de266fec8bfaf5b7b7f6026aaefc8cf"
integrity sha512-RGGj9la0138bgHUxyaGDHCZydmdpW+BFN9v0vMBzNPeXsaexCZotaFTIZDCNcKWPx8jtRHR8AXf318VRGXLJsw==
dependencies:
broccoli-funnel "^1.1.0"
broccoli-merge-trees "^1.2.1"
pretender "^1.4.2"
resolve "^1.2.0"
abortcontroller-polyfill "^1.1.9"
broccoli-funnel "^2.0.1"
broccoli-merge-trees "^3.0.0"
ember-cli-babel "^6.6.0"
fake-xml-http-request "^2.0.0"
pretender "^2.1.0"
route-recognizer "^0.3.3"
whatwg-fetch "^3.0.0"
ember-cli-qunit@^4.3.2:
version "4.4.0"
resolved "https://registry.yarnpkg.com/ember-cli-qunit/-/ember-cli-qunit-4.4.0.tgz#0edd7d651001d0d7ea200b9236a4733a5b7420f1"
integrity sha512-+gkx380AV4WXYjQeIuQi675STL9K12fHFtxs8B9u3EFbw45vJKrnYR4Vph3FujxhE/1pr/Je8kZEPAuezZAVLw==
dependencies:
ember-cli-babel "^6.11.0"
ember-qunit "^3.5.0"
ember-cli-sass@^9.0.0:
version "9.0.0"
@ -7827,18 +7964,20 @@ ember-export-application-global@^2.0.0:
dependencies:
ember-cli-babel "^6.0.0-beta.7"
ember-fetch@^6.1.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/ember-fetch/-/ember-fetch-6.2.0.tgz#88988e1fb94f44722a1cbb9416310711e65f6706"
integrity sha512-Rc/QgsfPOldT55WSnlN4z7TqKsE1YqGnjAwB7I8myjgEulIu00t0wx4zLjznEz5ng6VeRupXW6WaGE/B/0BYUA==
ember-fetch@^6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/ember-fetch/-/ember-fetch-6.5.1.tgz#6512153b9b85042744ed5a7934c8edb4a5b02dd0"
integrity sha512-ZA90lbTFZHhQCQKQNA6/3TdtiF1wBoT8nC7EI1pmkUZ49XDBP7i2eddUodR6qWRn8jK/D7IavQy3tx5fJBx7mw==
dependencies:
abortcontroller-polyfill "^1.1.9"
abortcontroller-polyfill "^1.3.0"
broccoli-concat "^3.2.2"
broccoli-debug "^0.6.5"
broccoli-merge-trees "^3.0.0"
broccoli-rollup "^2.1.1"
broccoli-stew "^2.0.0"
broccoli-stew "^2.1.0"
broccoli-templater "^2.0.1"
calculate-cache-key-for-tree "^2.0.0"
caniuse-api "^3.0.0"
ember-cli-babel "^6.8.2"
node-fetch "^2.3.0"
whatwg-fetch "^3.0.0"
@ -7916,6 +8055,19 @@ ember-power-select@^2.0.0:
ember-text-measurer "^0.5.0"
ember-truth-helpers "^2.1.0"
ember-qunit@^3.5.0:
version "3.5.3"
resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-3.5.3.tgz#bfd0bff8298c78c77e870cca43fe0826e78a0d09"
integrity sha512-FmXsI1bGsZ5th25x4KEle2fLCVURTptsQODfBt+Pg8tk9rX7y79cqny91PrhtkhE+giZ8p029tnq94SdpJ4ojg==
dependencies:
"@ember/test-helpers" "^0.7.26"
broccoli-funnel "^2.0.1"
broccoli-merge-trees "^2.0.0"
common-tags "^1.4.0"
ember-cli-babel "^6.8.2"
ember-cli-test-loader "^2.2.0"
qunit "~2.6.0"
ember-qunit@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-4.4.1.tgz#3654cadf9fa7e2287fe7b61fc7f19c3eb06222b5"
@ -8653,6 +8805,11 @@ exenv@^1.2.0:
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=
exists-stat@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/exists-stat/-/exists-stat-1.0.0.tgz#0660e3525a2e89d9e446129440c272edfa24b529"
integrity sha1-BmDjUlouidnkRhKUQMJy7foktSk=
exists-sync@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/exists-sync/-/exists-sync-0.0.4.tgz#9744c2c428cc03b01060db454d4b12f0ef3c8879"
@ -8816,10 +8973,10 @@ extsprintf@^1.2.0:
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fake-xml-http-request@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-1.6.0.tgz#bd0ac79ae3e2660098282048a12c730a6f64d550"
integrity sha512-99XPwwSg89BfzPuv4XCpZxn3EbauMCgAQCxq9MzrvS6DFD73OON6AnUTicL4A0HZtYMBwCZBWVnRqGjZDgQkTg==
fake-xml-http-request@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-2.0.0.tgz#41a92f0ca539477700cb1dafd2df251d55dac8ff"
integrity sha512-UjNnynb6eLAB0lyh2PlTEkjRJORnNsVF1hbzU+PQv89/cyBV9GDRCy7JAcLQgeCLYT+3kaumWWZKEJvbaK74eQ==
fast-deep-equal@^1.0.0:
version "1.1.0"
@ -8891,6 +9048,14 @@ fastboot-transform@0.1.1:
dependencies:
broccoli-stew "^1.5.0"
fastboot-transform@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/fastboot-transform/-/fastboot-transform-0.1.3.tgz#7dea0b117594afd8772baa6c9b0919644e7f7dcd"
integrity sha512-6otygPIJw1ARp1jJb+6KVO56iKBjhO+5x59RSC9qiZTbZRrv+HZAuP00KD3s+nWMvcFDemtdkugki9DNFTTwCQ==
dependencies:
broccoli-stew "^1.5.0"
convert-source-map "^1.5.1"
fault@^1.0.1, fault@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa"
@ -9154,7 +9319,7 @@ find-yarn-workspace-root@^1.1.0:
fs-extra "^4.0.3"
micromatch "^3.1.4"
findup-sync@^2.0.0:
findup-sync@2.0.0, findup-sync@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
@ -9432,6 +9597,17 @@ fs-tree-diff@^1.0.2:
path-posix "^1.0.0"
symlink-or-copy "^1.1.8"
fs-tree-diff@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz#343e4745ab435ec39ebac5f9059ad919cd034afa"
integrity sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A==
dependencies:
"@types/symlink-or-copy" "^1.2.0"
heimdalljs-logger "^0.1.7"
object-assign "^4.1.0"
path-posix "^1.0.0"
symlink-or-copy "^1.1.8"
fs-updater@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/fs-updater/-/fs-updater-1.0.4.tgz#2329980f99ae9176e9a0e84f7637538a182ce63b"
@ -12310,7 +12486,7 @@ lodash.union@~4.6.0:
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
lodash.uniq@^4.2.0, lodash.uniq@~4.5.0:
lodash.uniq@^4.2.0, lodash.uniq@^4.5.0, lodash.uniq@~4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
@ -13337,6 +13513,13 @@ node-releases@^1.0.0-alpha.14:
dependencies:
semver "^5.3.0"
node-releases@^1.1.19:
version "1.1.19"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.19.tgz#c492d1e381fea0350b338b646c27867e88e91b3d"
integrity sha512-SH/B4WwovHbulIALsQllAVwqZZD1kPmKCqrhGfR29dXjLAVZMHvBjD3S6nL9D/J9QkmZ1R92/0wCMDKXUUvyyA==
dependencies:
semver "^5.3.0"
node-releases@^1.1.3, node-releases@^1.1.8:
version "1.1.9"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.9.tgz#70d0985ec4bf7de9f08fc481f5dae111889ca482"
@ -14556,12 +14739,13 @@ preserve@^0.2.0:
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
pretender@^1.4.2:
version "1.6.1"
resolved "https://registry.yarnpkg.com/pretender/-/pretender-1.6.1.tgz#77d1e42ac8c6b298f5cd43534a87645df035db8c"
integrity sha1-d9HkKsjGspj1zUNTSodkXfA124w=
pretender@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/pretender/-/pretender-2.1.1.tgz#5085f0a1272c31d5b57c488386f69e6ca207cb35"
integrity sha512-IkidsJzaroAanw3I43tKCFm2xCpurkQr9aPXv5/jpN+LfCwDaeI8rngVWtQZTx4qqbhc5zJspnLHJ4N/25KvDQ==
dependencies:
fake-xml-http-request "^1.6.0"
"@xg-wang/whatwg-fetch" "^3.0.0"
fake-xml-http-request "^2.0.0"
route-recognizer "^0.3.3"
prettier-eslint-cli@^4.7.1:
@ -14952,6 +15136,19 @@ qunit@^2.9.2:
node-watch "0.6.0"
resolve "1.9.0"
qunit@~2.6.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/qunit/-/qunit-2.6.2.tgz#551210c5cf857258a4fe39a7fe15d9e14dfef22c"
integrity sha512-PHbKulmd4rrDhFto7iHicIstDTX7oMRvAcI7loHstvU8J7AOGwzcchONmy+EG4KU8HDk0K90o7vO0GhlYyKlOg==
dependencies:
commander "2.12.2"
exists-stat "1.0.0"
findup-sync "2.0.0"
js-reporters "1.2.1"
resolve "1.5.0"
sane "^2.5.2"
walk-sync "0.3.2"
qw@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4"
@ -15909,6 +16106,13 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
resolve@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
integrity sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==
dependencies:
path-parse "^1.0.5"
resolve@1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06"
@ -15916,7 +16120,7 @@ resolve@1.9.0:
dependencies:
path-parse "^1.0.6"
resolve@^1.1.3, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.7.1, resolve@^1.8.1:
resolve@^1.1.3, resolve@^1.1.7, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.7.1, resolve@^1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==
@ -16144,7 +16348,7 @@ samsam@~1.1:
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621"
integrity sha1-n1CHQZtNCR8jJXHn+lLpCw9VJiE=
sane@^2.4.1:
sane@^2.4.1, sane@^2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o=
@ -18376,6 +18580,14 @@ walk-back@^3.0.0:
resolved "https://registry.yarnpkg.com/walk-back/-/walk-back-3.0.1.tgz#0c0012694725604960d6c2f75aaf1a1e7d455d35"
integrity sha512-umiNB2qLO731Sxbp6cfZ9pwURJzTnftxE4Gc7hq8n/ehkuXC//s9F65IEIJA2ZytQZ1ZOsm/Fju4IWx0bivkUQ==
walk-sync@0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.2.tgz#4827280afc42d0e035367c4a4e31eeac0d136f75"
integrity sha512-FMB5VqpLqOCcqrzA9okZFc0wq0Qbmdm396qJxvQZhDpyu0W95G9JCmp74tx7iyYnyOcBtUuKJsgIKAqjozvmmQ==
dependencies:
ensure-posix-path "^1.0.0"
matcher-collection "^1.0.0"
walk-sync@^0.2.5, walk-sync@^0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.2.7.tgz#b49be4ee6867657aeb736978b56a29d10fa39969"