diff --git a/ui/app/components/auth-form.js b/ui/app/components/auth-form.js index aadc85ab46..fc8596404d 100644 --- a/ui/app/components/auth-form.js +++ b/ui/app/components/auth-form.js @@ -198,7 +198,7 @@ export default Component.extend(DEFAULTS, { let transition = this.router.transitionTo(targetRoute, { queryParams: { namespace } }); // returning this w/then because if we keep it // in the task, it will get cancelled when the component in un-rendered - return transition.followRedirects().then(() => { + yield transition.followRedirects().then(() => { if (isRoot) { this.flashMessages.warning( 'You have logged in with a root token. As a security precaution, this root token will not be stored by your browser and you will need to re-authenticate after the window is closed or refreshed.' diff --git a/ui/app/components/auth-jwt.js b/ui/app/components/auth-jwt.js index 97564ef15d..acaeb98ae0 100644 --- a/ui/app/components/auth-jwt.js +++ b/ui/app/components/auth-jwt.js @@ -1,7 +1,7 @@ import Ember from 'ember'; import { inject as service } from '@ember/service'; import Component from './outer-html'; -import { next, later } from '@ember/runloop'; +import { later } from '@ember/runloop'; import { task, timeout, waitForEvent } from 'ember-concurrency'; import { computed } from '@ember/object'; @@ -27,18 +27,16 @@ export default Component.extend({ onNamespace() {}, didReceiveAttrs() { - next(() => { - let { oldSelectedAuthPath, selectedAuthPath } = this; - let shouldDebounce = !oldSelectedAuthPath && !selectedAuthPath; - if (oldSelectedAuthPath !== selectedAuthPath) { - this.set('role', null); - this.onRoleName(this.roleName); - this.fetchRole.perform(null, { debounce: false }); - } else if (shouldDebounce) { - this.fetchRole.perform(this.roleName); - } - this.set('oldSelectedAuthPath', selectedAuthPath); - }); + let { oldSelectedAuthPath, selectedAuthPath } = this; + let shouldDebounce = !oldSelectedAuthPath && !selectedAuthPath; + if (oldSelectedAuthPath !== selectedAuthPath) { + this.set('role', null); + this.onRoleName(this.roleName); + this.fetchRole.perform(null, { debounce: false }); + } else if (shouldDebounce) { + this.fetchRole.perform(this.roleName); + } + this.set('oldSelectedAuthPath', selectedAuthPath); }, // OIDC roles in the JWT/OIDC backend are those with an authUrl, @@ -68,7 +66,9 @@ export default Component.extend({ } } this.set('role', role); - }).restartable(), + }) + .restartable() + .withTestWaiter(), handleOIDCError(err) { this.onLoading(false); diff --git a/ui/app/components/pgp-file.js b/ui/app/components/pgp-file.js index a8e1d1c550..caf5d835cb 100644 --- a/ui/app/components/pgp-file.js +++ b/ui/app/components/pgp-file.js @@ -1,5 +1,6 @@ import Component from '@ember/component'; import { set } from '@ember/object'; +import { task } from 'ember-concurrency'; const BASE_64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gi; export default Component.extend({ @@ -34,12 +35,12 @@ export default Component.extend({ readFile(file) { const reader = new FileReader(); - reader.onload = () => this.setPGPKey(reader.result, file.name); + reader.onload = () => this.setPGPKey.perform(reader.result, file.name); // this gives us a base64-encoded string which is important in the onload reader.readAsDataURL(file); }, - setPGPKey(dataURL, filename) { + setPGPKey: task(function*(dataURL, filename) { const b64File = dataURL.split(',')[1].trim(); const decoded = atob(b64File).trim(); @@ -48,8 +49,8 @@ export default Component.extend({ // If after decoding it's not b64, we want // the original as it was only encoded when we used `readAsDataURL`. const fileData = decoded.match(BASE_64_REGEX) ? decoded : b64File; - this.get('onChange')(this.get('index'), { value: fileData, fileName: filename }); - }, + yield this.get('onChange')(this.get('index'), { value: fileData, fileName: filename }); + }).withTestWaiter(), actions: { pickedFile(e) { diff --git a/ui/app/components/secret-link.js b/ui/app/components/secret-link.js index 0b2b12d0aa..c755e9501e 100644 --- a/ui/app/components/secret-link.js +++ b/ui/app/components/secret-link.js @@ -21,6 +21,8 @@ export function linkParams({ mode, secret, queryParams }) { export default Component.extend({ tagName: '', + // so that ember-test-selectors doesn't log a warning + supportsDataTestProperties: true, mode: 'list', secret: null, diff --git a/ui/app/components/wizard-content.js b/ui/app/components/wizard-content.js index bf2e036212..6a929b5dbf 100644 --- a/ui/app/components/wizard-content.js +++ b/ui/app/components/wizard-content.js @@ -2,6 +2,7 @@ import { inject as service } from '@ember/service'; import Component from '@ember/component'; import { computed } from '@ember/object'; import { FEATURE_MACHINE_STEPS, INIT_STEPS } from 'vault/helpers/wizard-constants'; +import { htmlSafe } from '@ember/template'; export default Component.extend({ wizard: service(), @@ -66,25 +67,25 @@ export default Component.extend({ let bar = []; if (this.currentTutorialProgress) { bar.push({ - style: `width:${this.currentTutorialProgress.percentage}%;`, + style: htmlSafe(`width:${this.currentTutorialProgress.percentage}%;`), completed: false, showIcon: true, }); } else { if (this.currentFeatureProgress) { this.completedFeatures.forEach(feature => { - bar.push({ style: 'width:100%;', completed: true, feature: feature, showIcon: true }); + bar.push({ style: htmlSafe('width:100%;'), completed: true, feature: feature, showIcon: true }); }); this.wizard.featureList.forEach(feature => { if (feature === this.currentMachine) { bar.push({ - style: `width:${this.currentFeatureProgress.percentage}%;`, + style: htmlSafe(`width:${this.currentFeatureProgress.percentage}%;`), completed: this.currentFeatureProgress.percentage == 100 ? true : false, feature: feature, showIcon: true, }); } else { - bar.push({ style: 'width:0%;', completed: false, feature: feature, showIcon: true }); + bar.push({ style: htmlSafe('width:0%;'), completed: false, feature: feature, showIcon: true }); } }); } diff --git a/ui/app/components/wizard/features-selection.js b/ui/app/components/wizard/features-selection.js index bb5919d283..f57d7f751c 100644 --- a/ui/app/components/wizard/features-selection.js +++ b/ui/app/components/wizard/features-selection.js @@ -2,6 +2,7 @@ import { inject as service } from '@ember/service'; import Component from '@ember/component'; import { computed } from '@ember/object'; import { FEATURE_MACHINE_TIME } from 'vault/helpers/wizard-constants'; +import { htmlSafe } from '@ember/template'; export default Component.extend({ wizard: service(), @@ -48,10 +49,10 @@ export default Component.extend({ }), selectProgress: computed('selectedFeatures', function() { let bar = this.selectedFeatures.map(feature => { - return { style: 'width:0%;', completed: false, showIcon: true, feature: feature }; + return { style: htmlSafe('width:0%;'), completed: false, showIcon: true, feature: feature }; }); if (bar.length === 0) { - bar = [{ style: 'width:0%;', showIcon: false }]; + bar = [{ style: htmlSafe('width:0%;'), showIcon: false }]; } return bar; }), diff --git a/ui/app/routes/loading.js b/ui/app/routes/loading.js index a327169ddb..06fbc703ba 100644 --- a/ui/app/routes/loading.js +++ b/ui/app/routes/loading.js @@ -2,7 +2,7 @@ import Route from '@ember/routing/route'; export default Route.extend({ renderTemplate() { - let { targetName } = this.router.currentState.routerJs.activeTransition; + let { targetName } = this._router.currentState.routerJs.activeTransition; let isCallback = targetName === 'vault.cluster.oidc-callback' || targetName === 'vault.cluster.oidc-callback-namespace'; if (isCallback) { diff --git a/ui/app/serializers/identity/entity.js b/ui/app/serializers/identity/entity.js index 4ff22baac6..6060bb03e7 100644 --- a/ui/app/serializers/identity/entity.js +++ b/ui/app/serializers/identity/entity.js @@ -2,6 +2,8 @@ import DS from 'ember-data'; import IdentitySerializer from './_base'; export default IdentitySerializer.extend(DS.EmbeddedRecordsMixin, { + // we don't need to serialize relationships here + serializeHasMany() {}, attrs: { aliases: { embedded: 'always' }, }, diff --git a/ui/app/services/auth.js b/ui/app/services/auth.js index 87a4286e50..6bc8694346 100644 --- a/ui/app/services/auth.js +++ b/ui/app/services/auth.js @@ -304,21 +304,14 @@ export default Service.extend({ }); }, - authenticate(/*{clusterId, backend, data}*/) { + async authenticate(/*{clusterId, backend, data}*/) { const [options] = arguments; const adapter = this.clusterAdapter(); - return adapter.authenticate(options).then(resp => { - return this.persistAuthData(options, resp.auth || resp.data, this.get('namespace.path')).then( - authData => { - return this.get('permissions') - .getPaths.perform() - .then(() => { - return authData; - }); - } - ); - }); + let resp = await adapter.authenticate(options); + let authData = await this.persistAuthData(options, resp.auth || resp.data, this.get('namespace.path')); + await this.get('permissions').getPaths.perform(); + return authData; }, deleteCurrentToken() { diff --git a/ui/app/templates/components/pgp-file.hbs b/ui/app/templates/components/pgp-file.hbs index 8526d9e37f..51aafd84ac 100644 --- a/ui/app/templates/components/pgp-file.hbs +++ b/ui/app/templates/components/pgp-file.hbs @@ -1,6 +1,6 @@
-