Ember Upgrade to 3.24 (#13443)

* Update browserslist

* Add browserslistrc

* ember-cli-update --to 3.26, fix conflicts

* Run codemodes that start with ember-*

* More codemods - before cp*

* More codemods (curly data-test-*)

* WIP ember-basic-dropdown template errors

* updates ember-basic-dropdown and related deps to fix build issues

* updates basic dropdown instances to new version API

* updates more deps -- ember-template-lint is working again

* runs no-implicit-this codemod

* creates and runs no-quoteless-attributes codemod

* runs angle brackets codemod

* updates lint:hbs globs to only touch hbs files

* removes yield only templates

* creates and runs deprecated args transform

* supresses lint error for invokeAction on LinkTo component

* resolves remaining ambiguous path lint errors

* resolves simple-unless lint errors

* adds warnings for deprecated tagName arg on LinkTo components

* adds warnings for remaining curly component invocation

* updates global template lint rules

* resolves remaining template lint errors

* disables some ember specfic lint rules that target pre octane patterns

* js lint fix run

* resolves remaining js lint errors

* fixes test run

* adds npm-run-all dep

* fixes test attribute issues

* fixes console acceptance tests

* fixes tests

* adds yield only wizard/tutorial-active template

* fixes more tests

* attempts to fix more flaky tests

* removes commented out settled in transit test

* updates deprecations workflow and adds initializer to filter by version

* updates flaky policies acl old test

* updates to flaky transit test

* bumps ember deps down to LTS version

* runs linters after main merge

* fixes client count tests after bad merge conflict fixes

* fixes client count history test

* more updates to lint config

* another round of hbs lint fixes after extending stylistic rule

* updates lint-staged commands

* removes indent eslint rule since it seems to break things

* fixes bad attribute in transform-edit-form template

* test fixes

* fixes enterprise tests

* adds changelog

* removes deprecated ember-concurrency-test-waiters dep and adds @ember/test-waiters

* flaky test fix

Co-authored-by: hashishaw <cshaw@hashicorp.com>
This commit is contained in:
Jordan Reimer 2021-12-16 20:44:29 -07:00 committed by GitHub
parent 5e316537f2
commit 5c2a08de6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1093 changed files with 14704 additions and 12316 deletions

3
changelog/13443.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:change
ui: Upgrade Ember to version 3.24
```

3
ui/.browserslistrc Normal file
View File

@ -0,0 +1,3 @@
defaults
not IE 11
maintained node versions

View File

@ -16,6 +16,8 @@
# misc # misc
/coverage/ /coverage/
!.*
.eslintcache
# ember-try # ember-try
/.node_modules.ember-try/ /.node_modules.ember-try/

View File

@ -12,21 +12,28 @@ module.exports = {
legacyDecorators: true, legacyDecorators: true,
}, },
}, },
plugins: ['ember', 'prettier'], plugins: ['ember'],
extends: ['eslint:recommended', 'plugin:ember/recommended', 'prettier'], extends: ['eslint:recommended', 'plugin:ember/recommended', 'plugin:prettier/recommended'],
env: { env: {
browser: true, browser: true,
es6: true,
}, },
rules: { rules: {
// TODO revisit once figure out how to replace, added during upgrade to 3.20 'no-console': 'warn',
'ember/no-new-mixins': 'off', 'ember/no-mixins': 'warn',
'ember/no-mixins': 'off', 'ember/no-new-mixins': 'off', // should be warn but then every line of the mixin is green
// need to be fully glimmerized before these rules can be turned on
'ember/no-classic-classes': 'off',
'ember/no-classic-components': 'off',
'ember/no-actions-hash': 'off',
'ember/require-tagless-components': 'off',
'ember/no-component-lifecycle-hooks': 'off',
}, },
overrides: [ overrides: [
// node files // node files
{ {
files: [ files: [
'.eslintrc.js',
'.prettierrc.js',
'.template-lintrc.js', '.template-lintrc.js',
'ember-cli-build.js', 'ember-cli-build.js',
'testem.js', 'testem.js',
@ -34,10 +41,10 @@ module.exports = {
'config/**/*.js', 'config/**/*.js',
'lib/*/index.js', 'lib/*/index.js',
'scripts/start-vault.js', 'scripts/start-vault.js',
'server/**/*.js',
], ],
parserOptions: { parserOptions: {
sourceType: 'script', sourceType: 'script',
ecmaVersion: 2018,
}, },
env: { env: {
browser: false, browser: false,

1
ui/.gitignore vendored
View File

@ -11,6 +11,7 @@
# misc # misc
/.sass-cache /.sass-cache
/.eslintcache
/connect.lock /connect.lock
/coverage/ /coverage/
/libpeerconnection.log /libpeerconnection.log

21
ui/.prettierignore Normal file
View File

@ -0,0 +1,21 @@
# unconventional js
/blueprints/*/files/
/vendor/
# compiled output
/dist/
/tmp/
# dependencies
/bower_components/
/node_modules/
# misc
/coverage/
!.*
.eslintcache
# ember-try
/.node_modules.ember-try/
/bower.json.ember-try
/package.json.ember-try

View File

@ -1,5 +0,0 @@
{
"singleQuote": true,
"trailingComma": "es5",
"printWidth": 110
}

16
ui/.prettierrc.js Normal file
View File

@ -0,0 +1,16 @@
'use strict';
module.exports = {
singleQuote: true,
trailingComma: 'es5',
printWidth: 110,
overrides: [
{
files: '*.hbs',
options: {
singleQuote: false,
printWidth: 125,
},
},
],
};

View File

@ -7,8 +7,8 @@ function loadStories() {
// automatically import all files ending in *.stories.js // automatically import all files ending in *.stories.js
const appStories = require.context('../stories', true, /.stories.js$/); const appStories = require.context('../stories', true, /.stories.js$/);
const addonAndRepoStories = require.context('../lib', true, /.stories.js$/); const addonAndRepoStories = require.context('../lib', true, /.stories.js$/);
appStories.keys().forEach(filename => appStories(filename)); appStories.keys().forEach((filename) => appStories(filename));
addonAndRepoStories.keys().forEach(filename => addonAndRepoStories(filename)); addonAndRepoStories.keys().forEach((filename) => addonAndRepoStories(filename));
} }
addParameters({ addParameters({
@ -16,7 +16,7 @@ addParameters({
options: { theme }, options: { theme },
}); });
addDecorator(storyFn => { addDecorator((storyFn) => {
const { template, context } = storyFn(); const { template, context } = storyFn();
// flight icon sprite must be inserted into dom for icon lookup via use element // flight icon sprite must be inserted into dom for icon lookup via use element

View File

@ -1,27 +1,17 @@
'use strict'; 'use strict';
module.exports = { module.exports = {
extends: 'recommended', extends: ['octane', 'stylistic'],
rules: { rules: {
// should definitely move to template only 'no-bare-strings': 'off',
// glimmer components for this one 'no-action': 'off',
'no-partial': false, 'no-duplicate-landmark-elements': 'warn',
'no-implicit-this': {
// these need to be looked into, but allow: ['supported-auth-backends'],
// may be a bigger change
'no-invalid-interactive': false,
'simple-unless': false,
'self-closing-void-elements': false,
'no-unnecessary-concat': false,
'no-quoteless-attributes': false,
'no-nested-interactive': false,
// not sure we'll ever want these on,
// would be nice but if prettier isn't doing
// it for us, then not sure it's worth it
'attribute-indentation': false,
'block-indentation': false,
quotes: false,
}, },
'require-input-label': 'off',
'no-down-event-binding': 'warn',
'self-closing-void-elements': 'off',
},
ignore: ['lib/story-md', 'tests/**'],
}; };

View File

@ -1,6 +1,90 @@
## Module Report ## Module Report
### Unknown Global ### 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-form.js` at line 252
```js
delayAuthMessageReminder: task(function*() {
if (Ember.testing) {
this.showLoading = true;
yield timeout(0);
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/routes/vault/cluster/logout.js` at line 30
```js
this.flashMessages.clearMessages();
this.permissions.reset();
if (Ember.testing) {
// Don't redirect on the test
this.replaceWith('vault.cluster.auth', { queryParams: { with: authType } });
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/components/mount-backend-form.js` at line 100
```js
capabilities = yield this.store.findRecord('capabilities', `${path}/config`);
} catch (err) {
if (Ember.testing) {
//captures mount-backend-form component test
yield mountModel.save();
```
### Unknown Global
**Global**: `Ember.testing`
**Location**: `app/components/oidc-consent-block.js` at line 47
```js
let { redirect, ...params } = this.args;
let redirectUrl = this.buildUrl(redirect, params);
if (Ember.testing) {
this.args.testRedirect(redirectUrl.toString());
} else {
```
### 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.onerror` **Global**: `Ember.onerror`
**Location**: `tests/helpers/wait-for-error.js` at line 5 **Location**: `tests/helpers/wait-for-error.js` at line 5
@ -143,34 +227,6 @@ export default function waitForError(opts) {
**Global**: `Ember.testing` **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 **Location**: `app/routes/vault.js` at line 7
```js ```js
@ -185,7 +241,7 @@ export default Route.extend({
**Global**: `Ember.testing` **Global**: `Ember.testing`
**Location**: `app/services/auth.js` at line 267 **Location**: `app/services/auth.js` at line 268
```js ```js
checkShouldRenew: task(function*() { checkShouldRenew: task(function*() {
@ -194,17 +250,3 @@ export default Route.extend({
return; 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

@ -111,9 +111,8 @@ To run the tests locally in a browser other than IE11, swap out `launch_in_ci: [
### Linting ### Linting
- `yarn lint:hbs` * `yarn lint`
- `yarn lint:js` * `yarn lint:fix`
- `yarn lint:js -- --fix`
### Building Vault UI into a Vault Binary ### Building Vault UI into a Vault Binary

View File

@ -41,7 +41,7 @@ export default RESTAdapter.extend({
headers['X-Vault-Wrap-TTL'] = options.wrapTTL; headers['X-Vault-Wrap-TTL'] = options.wrapTTL;
} }
let namespace = typeof options.namespace === 'undefined' ? this.namespaceService.path : options.namespace; let namespace = typeof options.namespace === 'undefined' ? this.namespaceService.path : options.namespace;
if (namespace && !NAMESPACE_ROOT_URLS.some(str => url.includes(str))) { if (namespace && !NAMESPACE_ROOT_URLS.some((str) => url.includes(str))) {
headers['X-Vault-Namespace'] = namespace; headers['X-Vault-Namespace'] = namespace;
} }
options.headers = assign(options.headers || {}, headers); options.headers = assign(options.headers || {}, headers);
@ -49,7 +49,7 @@ export default RESTAdapter.extend({
_preRequest(url, options) { _preRequest(url, options) {
this.addHeaders(url, options); this.addHeaders(url, options);
const isPolling = POLLING_URLS.some(str => url.includes(str)); const isPolling = POLLING_URLS.some((str) => url.includes(str));
if (!isPolling) { if (!isPolling) {
this.auth.setLastFetch(Date.now()); this.auth.setLastFetch(Date.now());
} }
@ -86,7 +86,7 @@ export default RESTAdapter.extend({
const [resp] = args; const [resp] = args;
if (resp && resp.warnings) { if (resp && resp.warnings) {
let flash = this.flashMessages; let flash = this.flashMessages;
resp.warnings.forEach(message => { resp.warnings.forEach((message) => {
flash.info(message); flash.info(message);
}); });
} }
@ -102,7 +102,7 @@ export default RESTAdapter.extend({
headers: opts.headers || {}, headers: opts.headers || {},
body: opts.body, body: opts.body,
signal: opts.signal, signal: opts.signal,
}).then(response => { }).then((response) => {
if (response.status >= 200 && response.status < 300) { if (response.status >= 200 && response.status < 300) {
return RSVP.resolve(response); return RSVP.resolve(response);
} else { } else {

View File

@ -22,7 +22,7 @@ export default ApplicationAdapter.extend({
return this.ajax(url, 'GET', { return this.ajax(url, 'GET', {
unauthenticated: true, unauthenticated: true,
}) })
.then(result => { .then((result) => {
return { return {
data: result.data.auth, data: result.data.auth,
}; };
@ -33,7 +33,7 @@ export default ApplicationAdapter.extend({
}; };
}); });
} }
return this.ajax(this.url(), 'GET').catch(e => { return this.ajax(this.url(), 'GET').catch((e) => {
if (e instanceof AdapterError) { if (e instanceof AdapterError) {
set(e, 'policyPath', 'sys/auth'); set(e, 'policyPath', 'sys/auth');
} }

View File

@ -22,7 +22,7 @@ export default ApplicationAdapter.extend({
let role = snapshot.attr('role'); let role = snapshot.attr('role');
let url = `/v1/${role.backend}/creds/${role.name}`; let url = `/v1/${role.backend}/creds/${role.name}`;
return this.ajax(url, method, options).then(response => { return this.ajax(url, method, options).then((response) => {
response.id = snapshot.id; response.id = snapshot.id;
response.modelName = type.modelName; response.modelName = type.modelName;
store.pushPayload(type.modelName, response); store.pushPayload(type.modelName, response);

View File

@ -8,7 +8,7 @@ export default ApplicationAdapter.extend({
}, },
findRecord(store, type, id) { findRecord(store, type, id) {
return this.ajax(this.buildURL(type), 'POST', { data: { paths: [id] } }).catch(e => { return this.ajax(this.buildURL(type), 'POST', { data: { paths: [id] } }).catch((e) => {
if (e instanceof AdapterError) { if (e instanceof AdapterError) {
set(e, 'policyPath', 'sys/capabilities-self'); set(e, 'policyPath', 'sys/capabilities-self');
} }
@ -21,7 +21,7 @@ export default ApplicationAdapter.extend({
if (!id) { if (!id) {
return; return;
} }
return this.findRecord(store, type, id).then(resp => { return this.findRecord(store, type, id).then((resp) => {
resp.path = id; resp.path = id;
return resp; return resp;
}); });

View File

@ -11,7 +11,7 @@ export default Application.extend({
query = null; query = null;
} }
// API accepts start and end as query params // API accepts start and end as query params
return this.ajax(url, 'GET', { data: query }).then(resp => { return this.ajax(url, 'GET', { data: query }).then((resp) => {
let response = resp || {}; let response = resp || {};
// if the response is a 204 it has no request id // if the response is a 204 it has no request id
response.id = response.request_id || 'no-data'; response.id = response.request_id || 'no-data';

View File

@ -2,7 +2,7 @@ import Application from '../application';
export default Application.extend({ export default Application.extend({
queryRecord() { queryRecord() {
return this.ajax(this.urlForQuery(), 'GET').then(resp => { return this.ajax(this.urlForQuery(), 'GET').then((resp) => {
resp.id = resp.request_id; resp.id = resp.request_id;
return resp; return resp;
}); });

View File

@ -40,10 +40,10 @@ export default ApplicationAdapter.extend({
findRecord(store, type, id, snapshot) { findRecord(store, type, id, snapshot) {
let fetches = { let fetches = {
health: this.health(), health: this.health(),
sealStatus: this.sealStatus().catch(e => e), sealStatus: this.sealStatus().catch((e) => e),
}; };
if (this.version.isEnterprise && this.namespaceService.inRootNamespace) { if (this.version.isEnterprise && this.namespaceService.inRootNamespace) {
fetches.replicationStatus = this.replicationStatus().catch(e => e); fetches.replicationStatus = this.replicationStatus().catch((e) => e);
} }
return hash(fetches).then(({ health, sealStatus, replicationStatus }) => { return hash(fetches).then(({ health, sealStatus, replicationStatus }) => {
let ret = { let ret = {

View File

@ -11,7 +11,7 @@ export default ApplicationAdapter.extend({
data: { data: {
accessor: id, accessor: id,
}, },
}).then(response => { }).then((response) => {
response.id = id; response.id = id;
return response; return response;
}); });

View File

@ -24,7 +24,7 @@ export default ApplicationAdapter.extend({
}, },
fetchByQuery(store, query) { fetchByQuery(store, query) {
const { backend, id } = query; const { backend, id } = query;
return this.ajax(this.urlFor(backend, id), 'GET', this.optionsForQuery(id)).then(resp => { return this.ajax(this.urlFor(backend, id), 'GET', this.optionsForQuery(id)).then((resp) => {
resp.backend = backend; resp.backend = backend;
if (id) { if (id) {
resp.id = id; resp.id = id;

View File

@ -9,14 +9,14 @@ export default ApplicationAdapter.extend({
return this.ajax( return this.ajax(
`${this.buildURL()}/${encodeURIComponent(backend)}/static-creds/${encodeURIComponent(secret)}`, `${this.buildURL()}/${encodeURIComponent(backend)}/static-creds/${encodeURIComponent(secret)}`,
'GET' 'GET'
).then(resp => ({ ...resp, roleType: 'static' })); ).then((resp) => ({ ...resp, roleType: 'static' }));
}, },
_dynamicCreds(backend, secret) { _dynamicCreds(backend, secret) {
return this.ajax( return this.ajax(
`${this.buildURL()}/${encodeURIComponent(backend)}/creds/${encodeURIComponent(secret)}`, `${this.buildURL()}/${encodeURIComponent(backend)}/creds/${encodeURIComponent(secret)}`,
'GET' 'GET'
).then(resp => ({ ...resp, roleType: 'dynamic' })); ).then((resp) => ({ ...resp, roleType: 'dynamic' }));
}, },
fetchByQuery(store, query) { fetchByQuery(store, query) {

View File

@ -25,7 +25,7 @@ export default ApplicationAdapter.extend({
}, },
staticRoles(backend, id) { staticRoles(backend, id) {
return this.ajax(this.urlFor(backend, id, 'static'), 'GET', this.optionsForQuery(id)).then(resp => { return this.ajax(this.urlFor(backend, id, 'static'), 'GET', this.optionsForQuery(id)).then((resp) => {
if (id) { if (id) {
return { return {
...resp, ...resp,
@ -39,7 +39,7 @@ export default ApplicationAdapter.extend({
}, },
dynamicRoles(backend, id) { dynamicRoles(backend, id) {
return this.ajax(this.urlFor(backend, id), 'GET', this.optionsForQuery(id)).then(resp => { return this.ajax(this.urlFor(backend, id), 'GET', this.optionsForQuery(id)).then((resp) => {
if (id) { if (id) {
return { return {
...resp, ...resp,

View File

@ -6,14 +6,14 @@ export default ApplicationAdapter.extend({
namespace: 'v1', namespace: 'v1',
urlForItem() {}, urlForItem() {},
dynamicApiPath: '', dynamicApiPath: '',
getDynamicApiPath: task(function*(id) { getDynamicApiPath: task(function* (id) {
// TODO: remove yield at some point. // TODO: remove yield at some point.
let result = yield this.store.peekRecord('auth-method', id); let result = yield this.store.peekRecord('auth-method', id);
this.dynamicApiPath = result.apiPath; this.dynamicApiPath = result.apiPath;
return; return;
}), }),
fetchByQuery: task(function*(store, query, isList) { fetchByQuery: task(function* (store, query, isList) {
const { id } = query; const { id } = query;
let data = {}; let data = {};
if (isList) { if (isList) {
@ -21,7 +21,7 @@ export default ApplicationAdapter.extend({
yield this.getDynamicApiPath.perform(id); yield this.getDynamicApiPath.perform(id);
} }
return this.ajax(this.urlForItem(id, isList, this.dynamicApiPath), 'GET', { data }).then(resp => { return this.ajax(this.urlForItem(id, isList, this.dynamicApiPath), 'GET', { data }).then((resp) => {
const data = { const data = {
id, id,
method: id, method: id,

View File

@ -3,7 +3,7 @@ import IdentityAdapter from './base';
export default IdentityAdapter.extend({ export default IdentityAdapter.extend({
lookup(store, data) { lookup(store, data) {
let url = `/${this.urlPrefix()}/identity/lookup/entity`; let url = `/${this.urlPrefix()}/identity/lookup/entity`;
return this.ajax(url, 'POST', { data }).then(response => { return this.ajax(url, 'POST', { data }).then((response) => {
// unsuccessful lookup is a 204 // unsuccessful lookup is a 204
if (!response) return; if (!response) return;
let modelName = 'identity/entity'; let modelName = 'identity/entity';

View File

@ -3,7 +3,7 @@ import IdentityAdapter from './base';
export default IdentityAdapter.extend({ export default IdentityAdapter.extend({
lookup(store, data) { lookup(store, data) {
let url = `/${this.urlPrefix()}/identity/lookup/group`; let url = `/${this.urlPrefix()}/identity/lookup/group`;
return this.ajax(url, 'POST', { data }).then(response => { return this.ajax(url, 'POST', { data }).then((response) => {
// unsuccessful lookup is a 204 // unsuccessful lookup is a 204
if (!response) return; if (!response) return;
let modelName = 'identity/group'; let modelName = 'identity/group';

View File

@ -38,7 +38,7 @@ export default ApplicationAdapter.extend({
}, },
query(store, type, query) { query(store, type, query) {
return this.ajax(this.urlForQuery(query, type.modelName), 'GET').then(resp => { return this.ajax(this.urlForQuery(query, type.modelName), 'GET').then((resp) => {
// remove pagination query items here // remove pagination query items here
const { ...modelAttrs } = query; const { ...modelAttrs } = query;
resp._requestQuery = modelAttrs; resp._requestQuery = modelAttrs;
@ -49,7 +49,7 @@ export default ApplicationAdapter.extend({
queryRecord(store, type, query) { queryRecord(store, type, query) {
let id = query.id; let id = query.id;
delete query.id; delete query.id;
return this.ajax(this._url(type.modelName, query, id), 'GET').then(resp => { return this.ajax(this._url(type.modelName, query, id), 'GET').then((resp) => {
resp.id = id; resp.id = id;
resp = { ...resp, ...query }; resp = { ...resp, ...query };
return resp; return resp;

View File

@ -8,7 +8,7 @@ export default BaseAdapter.extend({
role: snapshot.record.role, role: snapshot.record.role,
}); });
url = `${url}/generate`; url = `${url}/generate`;
return this.ajax(url, 'POST', { data: snapshot.serialize() }).then(model => { return this.ajax(url, 'POST', { data: snapshot.serialize() }).then((model) => {
model.data.id = model.data.serial_number; model.data.id = model.data.serial_number;
return model; return model;
}); });

View File

@ -48,7 +48,7 @@ export default ApplicationAdapter.extend({
data: { data: {
list: true, list: true,
}, },
}).then(resp => { }).then((resp) => {
if (prefix) { if (prefix) {
resp.prefix = prefix; resp.prefix = prefix;
} }

View File

@ -6,7 +6,7 @@ export default ApplicationAdapter.extend({
}, },
findRecord(store, type, id) { findRecord(store, type, id) {
return this.ajax(this.url(id), 'GET').then(resp => { return this.ajax(this.url(id), 'GET').then((resp) => {
resp.id = id; resp.id = id;
return resp; return resp;
}); });

View File

@ -34,7 +34,7 @@ export default ApplicationAdapter.extend({
data = serializer.serialize(snapshot, requestType); data = serializer.serialize(snapshot, requestType);
} }
return this.ajax(this.url(snapshot, action), 'POST', { data }).then(response => { return this.ajax(this.url(snapshot, action), 'POST', { data }).then((response) => {
// uploading CA, setting signed intermediate cert, and attempting to generate // uploading CA, setting signed intermediate cert, and attempting to generate
// a new CA if one exists, all return a 204 // a new CA if one exists, all return a 204
if (!response) { if (!response) {

View File

@ -23,7 +23,7 @@ export default Adapter.extend({
fetchByQuery(store, query) { fetchByQuery(store, query) {
const { backend, id } = query; const { backend, id } = query;
return this.ajax(this.urlFor(backend, id), 'GET', this.optionsForQuery(id)).then(resp => { return this.ajax(this.urlFor(backend, id), 'GET', this.optionsForQuery(id)).then((resp) => {
const data = { const data = {
backend, backend,
}; };
@ -53,7 +53,7 @@ export default Adapter.extend({
const data = { const data = {
serial_number: id, serial_number: id,
}; };
return this.ajax(`${this.buildURL()}/${backend}/revoke`, 'POST', { data }).then(resp => { return this.ajax(`${this.buildURL()}/${backend}/revoke`, 'POST', { data }).then((resp) => {
const data = { const data = {
id, id,
serial_number: id, serial_number: id,

View File

@ -31,7 +31,7 @@ export default ApplicationAdapter.extend({
} }
return data; return data;
}, {}); }, {});
return this.ajax(url, 'POST', { data }).then(resp => { return this.ajax(url, 'POST', { data }).then((resp) => {
let response = resp || {}; let response = resp || {};
response.id = `${snapshot.record.get('backend')}-${snapshot.adapterOptions.method}`; response.id = `${snapshot.record.get('backend')}-${snapshot.adapterOptions.method}`;
return response; return response;
@ -69,9 +69,11 @@ export default ApplicationAdapter.extend({
return hash({ return hash({
backend: backendPath, backend: backendPath,
id: this.id(backendPath), id: this.id(backendPath),
der: this.rawRequest(derURL, 'GET', { unauthenticated: true }).then(response => response.blob()), der: this.rawRequest(derURL, 'GET', { unauthenticated: true }).then((response) => response.blob()),
pem: this.rawRequest(pemURL, 'GET', { unauthenticated: true }).then(response => response.text()), pem: this.rawRequest(pemURL, 'GET', { unauthenticated: true }).then((response) => response.text()),
ca_chain: this.rawRequest(chainURL, 'GET', { unauthenticated: true }).then(response => response.text()), ca_chain: this.rawRequest(chainURL, 'GET', { unauthenticated: true }).then((response) =>
response.text()
),
}); });
}, },
@ -79,12 +81,12 @@ export default ApplicationAdapter.extend({
const url = `/v1/${backendPath}/config/urls`; const url = `/v1/${backendPath}/config/urls`;
const id = this.id(backendPath); const id = this.id(backendPath);
return this.ajax(url, 'GET') return this.ajax(url, 'GET')
.then(resp => { .then((resp) => {
resp.id = id; resp.id = id;
resp.backend = backendPath; resp.backend = backendPath;
return resp; return resp;
}) })
.catch(e => { .catch((e) => {
if (e.httpStatus === 404) { if (e.httpStatus === 404) {
return resolve({ id }); return resolve({ id });
} else { } else {
@ -97,12 +99,12 @@ export default ApplicationAdapter.extend({
const url = `/v1/${backendPath}/config/crl`; const url = `/v1/${backendPath}/config/crl`;
const id = this.id(backendPath); const id = this.id(backendPath);
return this.ajax(url, 'GET') return this.ajax(url, 'GET')
.then(resp => { .then((resp) => {
resp.id = id; resp.id = id;
resp.backend = backendPath; resp.backend = backendPath;
return resp; return resp;
}) })
.catch(e => { .catch((e) => {
if (e.httpStatus === 404) { if (e.httpStatus === 404) {
return { id }; return { id };
} else { } else {
@ -118,7 +120,7 @@ export default ApplicationAdapter.extend({
queryRecord(store, type, query) { queryRecord(store, type, query) {
const { backend, section } = query; const { backend, section } = query;
return this.fetchSection(backend, section).then(resp => { return this.fetchSection(backend, section).then((resp) => {
resp.backend = backend; resp.backend = backend;
return resp; return resp;
}); });

View File

@ -13,7 +13,7 @@ export default ApplicationAdapter.extend({
const data = serializer.serialize(snapshot, requestType); const data = serializer.serialize(snapshot, requestType);
const role = snapshot.attr('role'); const role = snapshot.attr('role');
return this.ajax(this.url(role, snapshot), 'POST', { data }).then(response => { return this.ajax(this.url(role, snapshot), 'POST', { data }).then((response) => {
response.id = snapshot.id; response.id = snapshot.id;
response.modelName = type.modelName; response.modelName = type.modelName;
store.pushPayload(type.modelName, response); store.pushPayload(type.modelName, response);

View File

@ -7,7 +7,7 @@ export default ApplicationAdapter.extend({
fetchStatus(mode) { fetchStatus(mode) {
let url = this.getStatusUrl(mode); let url = this.getStatusUrl(mode);
return this.ajax(url, 'GET', { unauthenticated: true }).then(resp => { return this.ajax(url, 'GET', { unauthenticated: true }).then((resp) => {
return resp.data; return resp.data;
}); });
}, },

View File

@ -49,7 +49,7 @@ export default ApplicationAdapter.extend({
fetchByQuery(store, query) { fetchByQuery(store, query) {
const { id, backend } = query; const { id, backend } = query;
return this.ajax(this.urlForRole(backend, id), 'GET', this.optionsForQuery(id)).then(resp => { return this.ajax(this.urlForRole(backend, id), 'GET', this.optionsForQuery(id)).then((resp) => {
const data = { const data = {
id, id,
name: id, name: id,

View File

@ -49,7 +49,7 @@ export default ApplicationAdapter.extend({
fetchByQuery(store, query) { fetchByQuery(store, query) {
const { id, backend } = query; const { id, backend } = query;
return this.ajax(this.urlForRole(backend, id), 'GET', this.optionsForQuery(id)).then(resp => { return this.ajax(this.urlForRole(backend, id), 'GET', this.optionsForQuery(id)).then((resp) => {
const data = { const data = {
id, id,
name: id, name: id,

View File

@ -58,7 +58,7 @@ export default ApplicationAdapter.extend({
zeroAddressAjax = this.findAllZeroAddress(store, query); zeroAddressAjax = this.findAllZeroAddress(store, query);
} }
return allSettled([queryAjax, zeroAddressAjax]).then(results => { return allSettled([queryAjax, zeroAddressAjax]).then((results) => {
// query result 404d, so throw the adapterError // query result 404d, so throw the adapterError
if (!results[0].value) { if (!results[0].value) {
throw results[0].reason; throw results[0].reason;
@ -70,7 +70,7 @@ export default ApplicationAdapter.extend({
data: {}, data: {},
}; };
results.forEach(result => { results.forEach((result) => {
if (result.value) { if (result.value) {
if (result.value.data.roles) { if (result.value.data.roles) {
resp.data = assign({}, resp.data, { zero_address_roles: result.value.data.roles }); resp.data = assign({}, resp.data, { zero_address_roles: result.value.data.roles });

View File

@ -100,7 +100,7 @@ export default ApplicationAdapter.extend({
queryRecord(store, type, query) { queryRecord(store, type, query) {
if (query.type === 'aws') { if (query.type === 'aws') {
return this.ajax(`/v1/${encodePath(query.backend)}/config/lease`, 'GET').then(resp => { return this.ajax(`/v1/${encodePath(query.backend)}/config/lease`, 'GET').then((resp) => {
resp.path = query.backend + '/'; resp.path = query.backend + '/';
return resp; return resp;
}); });
@ -135,11 +135,7 @@ export default ApplicationAdapter.extend({
saveZeroAddressConfig(store, type, snapshot) { saveZeroAddressConfig(store, type, snapshot) {
const path = encodePath(snapshot.id); const path = encodePath(snapshot.id);
const roles = store const roles = store.peekAll('role-ssh').filterBy('zeroAddress').mapBy('id').join(',');
.peekAll('role-ssh')
.filterBy('zeroAddress')
.mapBy('id')
.join(',');
const url = `/v1/${path}/config/zeroaddress`; const url = `/v1/${path}/config/zeroaddress`;
const data = { roles }; const data = { roles };
if (roles === '') { if (roles === '') {

View File

@ -26,7 +26,7 @@ export default ApplicationAdapter.extend({
}, },
findRecord() { findRecord() {
return this._super(...arguments).catch(errorOrModel => { return this._super(...arguments).catch((errorOrModel) => {
// if the response is a real 404 or if the secret is gated by a control group this will be an error, // if the response is a real 404 or if the secret is gated by a control group this will be an error,
// otherwise the response will be the body of a deleted / destroyed version // otherwise the response will be the body of a deleted / destroyed version
if (errorOrModel instanceof AdapterError) { if (errorOrModel instanceof AdapterError) {
@ -44,7 +44,7 @@ export default ApplicationAdapter.extend({
}, },
queryRecord(id, options) { queryRecord(id, options) {
return this.ajax(this.urlForQueryRecord(id), 'GET', options).then(resp => { return this.ajax(this.urlForQueryRecord(id), 'GET', options).then((resp) => {
if (options.wrapTTL) { if (options.wrapTTL) {
return resp; return resp;
} }
@ -56,10 +56,10 @@ export default ApplicationAdapter.extend({
querySecretDataByVersion(id) { querySecretDataByVersion(id) {
return this.ajax(this.urlForQueryRecord(id), 'GET') return this.ajax(this.urlForQueryRecord(id), 'GET')
.then(resp => { .then((resp) => {
return resp.data; return resp.data;
}) })
.catch(error => { .catch((error) => {
return error.data; return error.data;
}); });
}, },
@ -73,7 +73,7 @@ export default ApplicationAdapter.extend({
createRecord(store, modelName, snapshot) { createRecord(store, modelName, snapshot) {
let backend = snapshot.belongsTo('secret').belongsTo('engine').id; let backend = snapshot.belongsTo('secret').belongsTo('engine').id;
let path = snapshot.attr('path'); let path = snapshot.attr('path');
return this._super(...arguments).then(resp => { return this._super(...arguments).then((resp) => {
resp.id = JSON.stringify([backend, path, resp.version]); resp.id = JSON.stringify([backend, path, resp.version]);
return resp; return resp;
}); });

View File

@ -56,7 +56,7 @@ export default ApplicationAdapter.extend({
fetchByQuery(query, action) { fetchByQuery(query, action) {
const { id, backend, wrapTTL } = query; const { id, backend, wrapTTL } = query;
return this.ajax(this.urlForSecret(backend, id), 'GET', this.optionsForQuery(id, action, wrapTTL)).then( return this.ajax(this.urlForSecret(backend, id), 'GET', this.optionsForQuery(id, action, wrapTTL)).then(
resp => { (resp) => {
if (wrapTTL) { if (wrapTTL) {
return resp; return resp;
} }

View File

@ -15,7 +15,7 @@ export default ApplicationAdapter.extend({
const data = serializer.serialize(snapshot, requestType); const data = serializer.serialize(snapshot, requestType);
const role = snapshot.attr('role'); const role = snapshot.attr('role');
return this.ajax(this.url(role), 'POST', { data }).then(response => { return this.ajax(this.url(role), 'POST', { data }).then((response) => {
response.id = snapshot.id; response.id = snapshot.id;
response.modelName = type.modelName; response.modelName = type.modelName;
store.pushPayload(type.modelName, response); store.pushPayload(type.modelName, response);

View File

@ -52,7 +52,7 @@ export default ApplicationAdapter.extend({
const { id, backend } = query; const { id, backend } = query;
const queryAjax = this.ajax(this.urlForTransformations(backend, id), 'GET', this.optionsForQuery(id)); const queryAjax = this.ajax(this.urlForTransformations(backend, id), 'GET', this.optionsForQuery(id));
return allSettled([queryAjax]).then(results => { return allSettled([queryAjax]).then((results) => {
// query result 404d, so throw the adapterError // query result 404d, so throw the adapterError
if (!results[0].value) { if (!results[0].value) {
throw results[0].reason; throw results[0].reason;
@ -64,7 +64,7 @@ export default ApplicationAdapter.extend({
data: {}, data: {},
}; };
results.forEach(result => { results.forEach((result) => {
if (result.value) { if (result.value) {
let d = result.value.data; let d = result.value.data;
if (d.templates) { if (d.templates) {

View File

@ -41,7 +41,7 @@ export default ApplicationAdapter.extend({
fetchByQuery(query) { fetchByQuery(query) {
const { backend, modelName, id } = query; const { backend, modelName, id } = query;
return this.ajax(this.url(backend, modelName, id), 'GET').then(resp => { return this.ajax(this.url(backend, modelName, id), 'GET').then((resp) => {
return { return {
...resp, ...resp,
backend, backend,
@ -54,7 +54,7 @@ export default ApplicationAdapter.extend({
}, },
queryRecord(store, type, query) { queryRecord(store, type, query) {
return this.ajax(this.url(query.backend, type.modelName, query.id), 'GET').then(result => { return this.ajax(this.url(query.backend, type.modelName, query.id), 'GET').then((result) => {
// CBS TODO: Add name to response and unmap name <> id on models // CBS TODO: Add name to response and unmap name <> id on models
return { return {
id: query.id, id: query.id,

View File

@ -14,7 +14,7 @@ export default ApplicationAdapter.extend({
url = url + '/config'; url = url + '/config';
} }
return this.ajax(url, 'POST', { data }).then(resp => { return this.ajax(url, 'POST', { data }).then((resp) => {
let response = resp || {}; let response = resp || {};
response.id = name; response.id = name;
return response; return response;
@ -86,7 +86,7 @@ export default ApplicationAdapter.extend({
fetchByQuery(query) { fetchByQuery(query) {
const { id, backend } = query; const { id, backend } = query;
return this.ajax(this.urlForSecret(backend, id), 'GET', this.optionsForQuery(id)).then(resp => { return this.ajax(this.urlForSecret(backend, id), 'GET', this.optionsForQuery(id)).then((resp) => {
resp.id = id; resp.id = id;
resp.backend = backend; resp.backend = backend;
return resp; return resp;

View File

@ -2,9 +2,7 @@ import Application from '@ember/application';
import Resolver from 'ember-resolver'; import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers'; import loadInitializers from 'ember-load-initializers';
import config from 'vault/config/environment'; import config from 'vault/config/environment';
import defineModifier from 'ember-concurrency-test-waiter/define-modifier';
defineModifier();
export default class App extends Application { export default class App extends Application {
modulePrefix = config.modulePrefix; modulePrefix = config.modulePrefix;
podModulePrefix = config.podModulePrefix; podModulePrefix = config.podModulePrefix;

View File

@ -2,6 +2,7 @@ import AdapterError from '@ember-data/adapter/error';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import Component from '@ember/component'; import Component from '@ember/component';
import { task } from 'ember-concurrency'; import { task } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
/** /**
* @module AuthConfigForm/Config * @module AuthConfigForm/Config
@ -23,7 +24,8 @@ const AuthConfigBase = Component.extend({
flashMessages: service(), flashMessages: service(),
router: service(), router: service(),
wizard: service(), wizard: service(),
saveModel: task(function*() { saveModel: task(
waitFor(function* () {
try { try {
yield this.model.save(); yield this.model.save();
} catch (err) { } catch (err) {
@ -39,7 +41,8 @@ const AuthConfigBase = Component.extend({
} }
this.router.transitionTo('vault.cluster.access.methods').followRedirects(); this.router.transitionTo('vault.cluster.access.methods').followRedirects();
this.flashMessages.success('The configuration was saved successfully.'); this.flashMessages.success('The configuration was saved successfully.');
}).withTestWaiter(), })
),
}); });
AuthConfigBase.reopenClass({ AuthConfigBase.reopenClass({

View File

@ -2,6 +2,7 @@ import AdapterError from '@ember-data/adapter/error';
import AuthConfigComponent from './config'; import AuthConfigComponent from './config';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import { task } from 'ember-concurrency'; import { task } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
/** /**
* @module AuthConfigForm/Options * @module AuthConfigForm/Options
@ -19,7 +20,8 @@ import { task } from 'ember-concurrency';
export default AuthConfigComponent.extend({ export default AuthConfigComponent.extend({
router: service(), router: service(),
wizard: service(), wizard: service(),
saveModel: task(function*() { saveModel: task(
waitFor(function* () {
let data = this.model.config.serialize(); let data = this.model.config.serialize();
data.description = this.model.description; data.description = this.model.description;
@ -50,5 +52,6 @@ export default AuthConfigComponent.extend({
} }
this.router.transitionTo('vault.cluster.access.methods').followRedirects(); this.router.transitionTo('vault.cluster.access.methods').followRedirects();
this.flashMessages.success('The configuration was saved successfully.'); this.flashMessages.success('The configuration was saved successfully.');
}).withTestWaiter(), })
),
}); });

View File

@ -8,6 +8,8 @@ import Component from '@ember/component';
import { computed } from '@ember/object'; import { computed } from '@ember/object';
import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends'; import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends';
import { task, timeout } from 'ember-concurrency'; import { task, timeout } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
const BACKENDS = supportedAuthBackends(); const BACKENDS = supportedAuthBackends();
/** /**
@ -116,7 +118,7 @@ export default Component.extend(DEFAULTS, {
'methods.[]', 'methods.[]',
'selectedAuth', 'selectedAuth',
'selectedAuthIsPath', 'selectedAuthIsPath',
function() { function () {
let { wrappedToken, methods, selectedAuth, selectedAuthIsPath: keyIsPath } = this; let { wrappedToken, methods, selectedAuth, selectedAuthIsPath: keyIsPath } = this;
if (!methods && !wrappedToken) { if (!methods && !wrappedToken) {
return {}; return {};
@ -128,7 +130,7 @@ export default Component.extend(DEFAULTS, {
} }
), ),
providerName: computed('selectedAuthBackend.type', function() { providerName: computed('selectedAuthBackend.type', function () {
if (!this.selectedAuthBackend) { if (!this.selectedAuthBackend) {
return; return;
} }
@ -142,22 +144,25 @@ export default Component.extend(DEFAULTS, {
cspErrorText: `This is a standby Vault node but can't communicate with the active node via request forwarding. Sign in at the active node to use the Vault UI.`, cspErrorText: `This is a standby Vault node but can't communicate with the active node via request forwarding. Sign in at the active node to use the Vault UI.`,
allSupportedMethods: computed('methodsToShow', 'hasMethodsWithPath', function() { allSupportedMethods: computed('methodsToShow', 'hasMethodsWithPath', function () {
let hasMethodsWithPath = this.hasMethodsWithPath; let hasMethodsWithPath = this.hasMethodsWithPath;
let methodsToShow = this.methodsToShow; let methodsToShow = this.methodsToShow;
return hasMethodsWithPath ? methodsToShow.concat(BACKENDS) : methodsToShow; return hasMethodsWithPath ? methodsToShow.concat(BACKENDS) : methodsToShow;
}), }),
hasMethodsWithPath: computed('methodsToShow', function() { hasMethodsWithPath: computed('methodsToShow', function () {
return this.methodsToShow.isAny('path'); return this.methodsToShow.isAny('path');
}), }),
methodsToShow: computed('methods', function() { methodsToShow: computed('methods', function () {
let methods = this.methods || []; let methods = this.methods || [];
let shownMethods = methods.filter(m => BACKENDS.find(b => b.type.toLowerCase() === m.type.toLowerCase())); let shownMethods = methods.filter((m) =>
BACKENDS.find((b) => b.type.toLowerCase() === m.type.toLowerCase())
);
return shownMethods.length ? shownMethods : BACKENDS; return shownMethods.length ? shownMethods : BACKENDS;
}), }),
unwrapToken: task(function*(token) { unwrapToken: task(
waitFor(function* (token) {
// will be using the Token Auth Method, so set it here // will be using the Token Auth Method, so set it here
this.set('selectedAuth', 'token'); this.set('selectedAuth', 'token');
let adapter = this.store.adapterFor('tools'); let adapter = this.store.adapterFor('tools');
@ -168,9 +173,11 @@ export default Component.extend(DEFAULTS, {
} catch (e) { } catch (e) {
this.set('error', `Token unwrap failed: ${e.errors[0]}`); this.set('error', `Token unwrap failed: ${e.errors[0]}`);
} }
}).withTestWaiter(), })
),
fetchMethods: task(function*() { fetchMethods: task(
waitFor(function* () {
let store = this.store; let store = this.store;
try { try {
let methods = yield store.findAll('auth-method', { let methods = yield store.findAll('auth-method', {
@ -180,7 +187,7 @@ export default Component.extend(DEFAULTS, {
}); });
this.set( this.set(
'methods', 'methods',
methods.map(m => { methods.map((m) => {
const method = m.serialize({ includeId: true }); const method = m.serialize({ includeId: true });
return { return {
...method, ...method,
@ -194,7 +201,8 @@ export default Component.extend(DEFAULTS, {
} catch (e) { } catch (e) {
this.set('error', `There was an error fetching Auth Methods: ${e.errors[0]}`); this.set('error', `There was an error fetching Auth Methods: ${e.errors[0]}`);
} }
}).withTestWaiter(), })
),
showLoading: or('isLoading', 'authenticate.isRunning', 'fetchMethods.isRunning', 'unwrapToken.isRunning'), showLoading: or('isLoading', 'authenticate.isRunning', 'fetchMethods.isRunning', 'unwrapToken.isRunning'),
@ -202,7 +210,7 @@ export default Component.extend(DEFAULTS, {
this.set('loading', false); this.set('loading', false);
let errors; let errors;
if (e.errors) { if (e.errors) {
errors = e.errors.map(error => { errors = e.errors.map((error) => {
if (error.detail) { if (error.detail) {
return error.detail; return error.detail;
} }
@ -215,7 +223,8 @@ export default Component.extend(DEFAULTS, {
this.set('error', `${message}${errors.join('.')}`); this.set('error', `${message}${errors.join('.')}`);
}, },
authenticate: task(function*(backendType, data) { authenticate: task(
waitFor(function* (backendType, data) {
let clusterId = this.cluster.id; let clusterId = this.cluster.id;
try { try {
if (backendType === 'okta') { if (backendType === 'okta') {
@ -246,9 +255,10 @@ export default Component.extend(DEFAULTS, {
} catch (e) { } catch (e) {
this.handleError(e); this.handleError(e);
} }
}).withTestWaiter(), })
),
delayAuthMessageReminder: task(function*() { delayAuthMessageReminder: task(function* () {
if (Ember.testing) { if (Ember.testing) {
this.showLoading = true; this.showLoading = true;
yield timeout(0); yield timeout(0);
@ -274,7 +284,7 @@ export default Component.extend(DEFAULTS, {
}); });
let backend = this.selectedAuthBackend || {}; let backend = this.selectedAuthBackend || {};
let backendMeta = BACKENDS.find( let backendMeta = BACKENDS.find(
b => (b.type || '').toLowerCase() === (backend.type || '').toLowerCase() (b) => (b.type || '').toLowerCase() === (backend.type || '').toLowerCase()
); );
let attributes = (backendMeta || {}).formAttributes || []; let attributes = (backendMeta || {}).formAttributes || [];

View File

@ -4,9 +4,9 @@ import Component from './outer-html';
import { later } from '@ember/runloop'; import { later } from '@ember/runloop';
import { task, timeout, waitForEvent } from 'ember-concurrency'; import { task, timeout, waitForEvent } from 'ember-concurrency';
import { computed } from '@ember/object'; import { computed } from '@ember/object';
import { waitFor } from '@ember/test-waiters';
/* eslint-disable ember/no-ember-testing-in-module-scope */ const WAIT_TIME = 500;
const WAIT_TIME = Ember.testing ? 0 : 500;
const ERROR_WINDOW_CLOSED = const ERROR_WINDOW_CLOSED =
'The provider window was closed before authentication was complete. Please click Sign In to try again.'; 'The provider window was closed before authentication was complete. Please click Sign In to try again.';
const ERROR_MISSING_PARAMS = const ERROR_MISSING_PARAMS =
@ -29,6 +29,7 @@ export default Component.extend({
onNamespace() {}, onNamespace() {},
didReceiveAttrs() { didReceiveAttrs() {
this._super();
let { oldSelectedAuthPath, selectedAuthPath } = this; let { oldSelectedAuthPath, selectedAuthPath } = this;
let shouldDebounce = !oldSelectedAuthPath && !selectedAuthPath; let shouldDebounce = !oldSelectedAuthPath && !selectedAuthPath;
if (oldSelectedAuthPath !== selectedAuthPath) { if (oldSelectedAuthPath !== selectedAuthPath) {
@ -44,7 +45,7 @@ export default Component.extend({
// Assumes authentication using OIDC until it's known that the mount is // Assumes authentication using OIDC until it's known that the mount is
// configured for JWT authentication via static keys, JWKS, or OIDC discovery. // configured for JWT authentication via static keys, JWKS, or OIDC discovery.
isOIDC: computed('errorMessage', function() { isOIDC: computed('errorMessage', function () {
return this.errorMessage !== ERROR_JWT_LOGIN; return this.errorMessage !== ERROR_JWT_LOGIN;
}), }),
@ -52,11 +53,12 @@ export default Component.extend({
return this.window || window; return this.window || window;
}, },
fetchRole: task(function*(roleName, options = { debounce: true }) { fetchRole: task(
waitFor(function* (roleName, options = { debounce: true }) {
if (options.debounce) { if (options.debounce) {
this.onRoleName(roleName); this.onRoleName(roleName);
// debounce // debounce
yield timeout(WAIT_TIME); yield timeout(Ember.testing ? 0 : WAIT_TIME);
} }
let path = this.selectedAuthPath || this.selectedAuthType; let path = this.selectedAuthPath || this.selectedAuthType;
let id = JSON.stringify([path, roleName]); let id = JSON.stringify([path, roleName]);
@ -64,7 +66,8 @@ export default Component.extend({
try { try {
role = yield this.store.findRecord('role-jwt', id, { adapterOptions: { namespace: this.namespace } }); role = yield this.store.findRecord('role-jwt', id, { adapterOptions: { namespace: this.namespace } });
} catch (e) { } catch (e) {
if (!e.httpStatus || e.httpStatus !== 400) { // throwing here causes failures in tests
if ((!e.httpStatus || e.httpStatus !== 400) && !Ember.testing) {
throw e; throw e;
} }
if (e.errors && e.errors.length > 0) { if (e.errors && e.errors.length > 0) {
@ -73,8 +76,7 @@ export default Component.extend({
} }
this.set('role', role); this.set('role', role);
}) })
.restartable() ).restartable(),
.withTestWaiter(),
handleOIDCError(err) { handleOIDCError(err) {
this.onLoading(false); this.onLoading(false);
@ -82,7 +84,7 @@ export default Component.extend({
this.onError(err); this.onError(err);
}, },
prepareForOIDC: task(function*(oidcWindow) { prepareForOIDC: task(function* (oidcWindow) {
const thisWindow = this.getWindow(); const thisWindow = this.getWindow();
// show the loading animation in the parent // show the loading animation in the parent
this.onLoading(true); this.onLoading(true);
@ -104,7 +106,7 @@ export default Component.extend({
} }
}), }),
watchPopup: task(function*(oidcWindow) { watchPopup: task(function* (oidcWindow) {
while (true) { while (true) {
yield timeout(WAIT_TIME); yield timeout(WAIT_TIME);
if (!oidcWindow || oidcWindow.closed) { if (!oidcWindow || oidcWindow.closed) {
@ -113,7 +115,7 @@ export default Component.extend({
} }
}), }),
watchCurrent: task(function*(oidcWindow) { watchCurrent: task(function* (oidcWindow) {
// when user is about to change pages, close the popup window // when user is about to change pages, close the popup window
yield waitForEvent(this.getWindow(), 'beforeunload'); yield waitForEvent(this.getWindow(), 'beforeunload');
oidcWindow.close(); oidcWindow.close();
@ -125,7 +127,7 @@ export default Component.extend({
oidcWindow.close(); oidcWindow.close();
}, },
exchangeOIDC: task(function*(oidcState, oidcWindow) { exchangeOIDC: task(function* (oidcState, oidcWindow) {
if (oidcState === null || oidcState === undefined) { if (oidcState === null || oidcState === undefined) {
return; return;
} }

View File

@ -82,7 +82,7 @@ export default Component.extend({
* @private * @private
* @type boolean * @type boolean
*/ */
valuesMatch: computed('value', '_value', function() { valuesMatch: computed('value', '_value', function () {
const { value, _value } = this; const { value, _value } = this;
const anyBlank = isBlank(value) || isBlank(_value); const anyBlank = isBlank(value) || isBlank(_value);
return !anyBlank && value === _value; return !anyBlank && value === _value;
@ -99,6 +99,7 @@ export default Component.extend({
}, },
didReceiveAttrs() { didReceiveAttrs() {
this._super();
// if there's no value, reset encoding // if there's no value, reset encoding
if (this.value === '') { if (this.value === '') {
set(this, 'currentEncoding', UTF8); set(this, 'currentEncoding', UTF8);

View File

@ -50,7 +50,7 @@ export default class ConfigComponent extends Component {
return content; return content;
} }
@(task(function*() { @(task(function* () {
try { try {
yield this.args.model.save(); yield this.args.model.save();
} catch (err) { } catch (err) {

View File

@ -34,7 +34,7 @@ export default class HistoryComponent extends Component {
return null; return null;
} }
let dataList = this.args.model.activity.byNamespace; let dataList = this.args.model.activity.byNamespace;
return dataList.map(d => { return dataList.map((d) => {
return { return {
name: d['namespace_id'], name: d['namespace_id'],
id: d['namespace_path'] === '' ? 'root' : d['namespace_path'], id: d['namespace_path'] === '' ? 'root' : d['namespace_path'],
@ -48,7 +48,7 @@ export default class HistoryComponent extends Component {
return null; return null;
} }
let dataset = this.args.model.activity.byNamespace.slice(0, this.max_namespaces); let dataset = this.args.model.activity.byNamespace.slice(0, this.max_namespaces);
return dataset.map(d => { return dataset.map((d) => {
return { return {
label: d['namespace_path'] === '' ? 'root' : d['namespace_path'], label: d['namespace_path'] === '' ? 'root' : d['namespace_path'],
non_entity_tokens: d['counts']['non_entity_tokens'], non_entity_tokens: d['counts']['non_entity_tokens'],
@ -69,7 +69,7 @@ export default class HistoryComponent extends Component {
results = fields.join(',') + '\n'; results = fields.join(',') + '\n';
namespaces.forEach(function(item) { namespaces.forEach(function (item) {
let path = item.namespace_path !== '' ? item.namespace_path : 'root', let path = item.namespace_path !== '' ? item.namespace_path : 'root',
total = item.counts.clients, total = item.counts.clients,
unique = item.counts.distinct_entities, unique = item.counts.distinct_entities,
@ -95,7 +95,7 @@ export default class HistoryComponent extends Component {
// Get the namespace by matching the path from the namespace list // Get the namespace by matching the path from the namespace list
getNamespace(path) { getNamespace(path) {
return this.args.model.activity.byNamespace.find(ns => { return this.args.model.activity.byNamespace.find((ns) => {
if (path === 'root') { if (path === 'root') {
return ns.namespace_path === ''; return ns.namespace_path === '';
} }

View File

@ -100,7 +100,7 @@ export default Component.extend({
* This array provides the text and download hrefs for those links. * This array provides the text and download hrefs for those links.
* *
*/ */
downloadHrefs: computed('config', 'config.{backend,pem,caChain,der}', function() { downloadHrefs: computed('config', 'config.{backend,pem,caChain,der}', function () {
const config = this.config; const config = this.config;
const { backend, pem, caChain, der } = config; const { backend, pem, caChain, der } = config;
@ -139,7 +139,7 @@ export default Component.extend({
const isUpload = this.model.uploadPemBundle; const isUpload = this.model.uploadPemBundle;
model model
.save({ adapterOptions: { method } }) .save({ adapterOptions: { method } })
.then(m => { .then((m) => {
if (method === 'setSignedIntermediate' || isUpload) { if (method === 'setSignedIntermediate' || isUpload) {
this.send('refresh'); this.send('refresh');
this.flashMessages.success('The certificate for this backend has been updated.'); this.flashMessages.success('The certificate for this backend has been updated.');

View File

@ -44,7 +44,7 @@ export default Component.extend({
.save({ .save({
adapterOptions: { adapterOptions: {
method: section, method: section,
fields: get(config, `${section}Attrs`).map(attr => attr.name), fields: get(config, `${section}Attrs`).map((attr) => attr.name),
}, },
}) })
.then(() => { .then(() => {

View File

@ -1,3 +0,0 @@
import Component from '@ember/component';
export default Component.extend({});

View File

@ -1,3 +0,0 @@
import Component from '@ember/component';
export default Component.extend({});

View File

@ -1,3 +0,0 @@
import Component from '@ember/component';
export default Component.extend({});

View File

@ -4,7 +4,7 @@ import { computed } from '@ember/object';
import columnify from 'columnify'; import columnify from 'columnify';
export function stringifyObjectValues(data) { export function stringifyObjectValues(data) {
Object.keys(data).forEach(item => { Object.keys(data).forEach((item) => {
let val = data[item]; let val = data[item];
if (typeof val !== 'string') { if (typeof val !== 'string') {
val = JSON.stringify(val); val = JSON.stringify(val);
@ -15,13 +15,13 @@ export function stringifyObjectValues(data) {
export default Component.extend({ export default Component.extend({
content: null, content: null,
columns: computed('content', function() { columns: computed('content', function () {
let data = this.content; let data = this.content;
stringifyObjectValues(data); stringifyObjectValues(data);
return columnify(data, { return columnify(data, {
preserveNewLines: true, preserveNewLines: true,
headingTransform: function(heading) { headingTransform: function (heading) {
return capitalize(heading); return capitalize(heading);
}, },
}); });

View File

@ -1,3 +0,0 @@
import Component from '@ember/component';
export default Component.extend({});

View File

@ -39,13 +39,13 @@ export default Component.extend({
isRunning: or('executeCommand.isRunning', 'refreshRoute.isRunning'), isRunning: or('executeCommand.isRunning', 'refreshRoute.isRunning'),
executeCommand: task(function*(command, shouldThrow = false) { executeCommand: task(function* (command, shouldThrow = false) {
this.set('inputValue', ''); this.set('inputValue', '');
let service = this.console; let service = this.console;
let serviceArgs; let serviceArgs;
if ( if (
executeUICommand(command, args => this.logAndOutput(args), { executeUICommand(command, (args) => this.logAndOutput(args), {
api: () => this.routeToExplore.perform(command), api: () => this.routeToExplore.perform(command),
clearall: () => service.clearLog(true), clearall: () => service.clearLog(true),
clear: () => service.clearLog(), clear: () => service.clearLog(),
@ -90,7 +90,7 @@ export default Component.extend({
} }
}), }),
refreshRoute: task(function*() { refreshRoute: task(function* () {
let owner = getOwner(this); let owner = getOwner(this);
let currentRoute = owner.lookup(`router:main`).get('currentRouteName'); let currentRoute = owner.lookup(`router:main`).get('currentRouteName');
@ -103,7 +103,7 @@ export default Component.extend({
} }
}), }),
routeToExplore: task(function*(command) { routeToExplore: task(function* (command) {
let filter = command.replace('api', '').trim(); let filter = command.replace('api', '').trim();
let content = let content =
'Welcome to the Vault API explorer! \nYou can search for endpoints, see what parameters they accept, and even execute requests with your current token.'; 'Welcome to the Vault API explorer! \nYou can search for endpoints, see what parameters they accept, and even execute requests with your current token.';
@ -134,7 +134,7 @@ export default Component.extend({
}), }),
shiftCommandIndex(keyCode) { shiftCommandIndex(keyCode) {
this.console.shiftCommandIndex(keyCode, val => { this.console.shiftCommandIndex(keyCode, (val) => {
this.set('inputValue', val); this.set('inputValue', val);
}); });
}, },

View File

@ -15,7 +15,7 @@ export default Component.extend({
error: null, error: null,
unwrapData: null, unwrapData: null,
unwrap: task(function*(token) { unwrap: task(function* (token) {
let adapter = this.store.adapterFor('tools'); let adapter = this.store.adapterFor('tools');
this.set('error', null); this.set('error', null);
try { try {
@ -27,7 +27,7 @@ export default Component.extend({
} }
}).drop(), }).drop(),
markAndNavigate: task(function*() { markAndNavigate: task(function* () {
this.controlGroup.markTokenForUnwrap(this.model.id); this.controlGroup.markTokenForUnwrap(this.model.id);
let { url } = this.controlGroupResponse.uiParams; let { url } = this.controlGroupResponse.uiParams;
yield this.router.transitionTo(url); yield this.router.transitionTo(url);

View File

@ -21,18 +21,18 @@ export default Component.extend({
currentUserEntityId: alias('auth.authData.entity_id'), currentUserEntityId: alias('auth.authData.entity_id'),
currentUserIsRequesting: computed('currentUserEntityId', 'model.requestEntity.id', function() { currentUserIsRequesting: computed('currentUserEntityId', 'model.requestEntity.id', function () {
if (!this.model.requestEntity) return false; if (!this.model.requestEntity) return false;
return this.currentUserEntityId === this.model.requestEntity.id; return this.currentUserEntityId === this.model.requestEntity.id;
}), }),
currentUserHasAuthorized: computed('currentUserEntityId', 'model.authorizations.@each.id', function() { currentUserHasAuthorized: computed('currentUserEntityId', 'model.authorizations.@each.id', function () {
let authorizations = this.model.authorizations || []; let authorizations = this.model.authorizations || [];
return Boolean(authorizations.findBy('id', this.currentUserEntityId)); return Boolean(authorizations.findBy('id', this.currentUserEntityId));
}), }),
isSuccess: or('currentUserHasAuthorized', 'model.approved'), isSuccess: or('currentUserHasAuthorized', 'model.approved'),
requestorName: computed('currentUserIsRequesting', 'model.requestEntity', function() { requestorName: computed('currentUserIsRequesting', 'model.requestEntity', function () {
let entity = this.model.requestEntity; let entity = this.model.requestEntity;
if (this.currentUserIsRequesting) { if (this.currentUserIsRequesting) {
@ -44,7 +44,7 @@ export default Component.extend({
return 'Someone'; return 'Someone';
}), }),
bannerPrefix: computed('model.approved', 'currentUserHasAuthorized', function() { bannerPrefix: computed('model.approved', 'currentUserHasAuthorized', function () {
if (this.currentUserHasAuthorized) { if (this.currentUserHasAuthorized) {
return 'Thanks!'; return 'Thanks!';
} }
@ -54,7 +54,7 @@ export default Component.extend({
return 'Locked'; return 'Locked';
}), }),
bannerText: computed('model.approved', 'currentUserIsRequesting', 'currentUserHasAuthorized', function() { bannerText: computed('model.approved', 'currentUserIsRequesting', 'currentUserHasAuthorized', function () {
let isApproved = this.model.approved; let isApproved = this.model.approved;
let { currentUserHasAuthorized, currentUserIsRequesting } = this; let { currentUserHasAuthorized, currentUserIsRequesting } = this;
if (currentUserHasAuthorized) { if (currentUserHasAuthorized) {
@ -72,7 +72,7 @@ export default Component.extend({
return 'Someone is requesting access to a path locked by a Control Group'; return 'Someone is requesting access to a path locked by a Control Group';
}), }),
refresh: task(function*() { refresh: task(function* () {
try { try {
yield this.model.reload(); yield this.model.reload();
} catch (e) { } catch (e) {
@ -80,7 +80,7 @@ export default Component.extend({
} }
}).drop(), }).drop(),
authorize: task(function*() { authorize: task(function* () {
try { try {
yield this.model.save(); yield this.model.save();
yield this.refresh.perform(); yield this.refresh.perform();

View File

@ -6,7 +6,7 @@ import { action } from '@ember/object';
const LIST_ROOT_ROUTE = 'vault.cluster.secrets.backend.list-root'; const LIST_ROOT_ROUTE = 'vault.cluster.secrets.backend.list-root';
const SHOW_ROUTE = 'vault.cluster.secrets.backend.show'; const SHOW_ROUTE = 'vault.cluster.secrets.backend.show';
const getErrorMessage = errors => { const getErrorMessage = (errors) => {
let errorMessage = errors?.join('. ') || 'Something went wrong. Check the Vault logs for more information.'; let errorMessage = errors?.join('. ') || 'Something went wrong. Check the Vault logs for more information.';
if (errorMessage.indexOf('failed to verify') >= 0) { if (errorMessage.indexOf('failed to verify') >= 0) {
errorMessage = errorMessage =
@ -69,7 +69,7 @@ export default class DatabaseConnectionEdit extends Component {
.then(() => { .then(() => {
this.showSaveModal = true; this.showSaveModal = true;
}) })
.catch(e => { .catch((e) => {
const errorMessage = getErrorMessage(e.errors); const errorMessage = getErrorMessage(e.errors);
this.flashMessages.danger(errorMessage); this.flashMessages.danger(errorMessage);
}); });
@ -91,7 +91,7 @@ export default class DatabaseConnectionEdit extends Component {
this.flashMessages.success(`Successfully rotated root credentials for connection "${name}"`); this.flashMessages.success(`Successfully rotated root credentials for connection "${name}"`);
this.transitionToRoute(SHOW_ROUTE, name); this.transitionToRoute(SHOW_ROUTE, name);
}) })
.catch(e => { .catch((e) => {
this.flashMessages.danger(`Error rotating root credentials: ${e.errors}`); this.flashMessages.danger(`Error rotating root credentials: ${e.errors}`);
this.transitionToRoute(SHOW_ROUTE, name); this.transitionToRoute(SHOW_ROUTE, name);
}); });
@ -107,7 +107,7 @@ export default class DatabaseConnectionEdit extends Component {
.then(() => { .then(() => {
this.transitionToRoute(SHOW_ROUTE, secretId); this.transitionToRoute(SHOW_ROUTE, secretId);
}) })
.catch(e => { .catch((e) => {
const errorMessage = getErrorMessage(e.errors); const errorMessage = getErrorMessage(e.errors);
this.flashMessages.danger(errorMessage); this.flashMessages.danger(errorMessage);
}); });
@ -133,7 +133,7 @@ export default class DatabaseConnectionEdit extends Component {
// TODO: Why isn't the confirmAction closing? // TODO: Why isn't the confirmAction closing?
this.flashMessages.success('Successfully reset connection'); this.flashMessages.success('Successfully reset connection');
}) })
.catch(e => { .catch((e) => {
const errorMessage = getErrorMessage(e.errors); const errorMessage = getErrorMessage(e.errors);
this.flashMessages.danger(errorMessage); this.flashMessages.danger(errorMessage);
}); });
@ -147,7 +147,7 @@ export default class DatabaseConnectionEdit extends Component {
// TODO: Why isn't the confirmAction closing? // TODO: Why isn't the confirmAction closing?
this.flashMessages.success('Successfully rotated credentials'); this.flashMessages.success('Successfully rotated credentials');
}) })
.catch(e => { .catch((e) => {
const errorMessage = getErrorMessage(e.errors); const errorMessage = getErrorMessage(e.errors);
this.flashMessages.danger(errorMessage); this.flashMessages.danger(errorMessage);
}); });

View File

@ -49,7 +49,7 @@ export default class DatabaseRoleEdit extends Component {
} }
return this.store return this.store
.queryRecord('database/connection', { id: dbs[0], backend }) .queryRecord('database/connection', { id: dbs[0], backend })
.then(record => record.plugin_name) .then((record) => record.plugin_name)
.catch(() => null); .catch(() => null);
} }
@ -73,7 +73,7 @@ export default class DatabaseRoleEdit extends Component {
console.debug(e); console.debug(e);
} }
}) })
.catch(e => { .catch((e) => {
this.flashMessages.danger(e.errors?.join('. ')); this.flashMessages.danger(e.errors?.join('. '));
}); });
} }
@ -100,7 +100,7 @@ export default class DatabaseRoleEdit extends Component {
console.debug(e); console.debug(e);
} }
}) })
.catch(e => { .catch((e) => {
const errorMessage = e.errors?.join('. ') || e.message; const errorMessage = e.errors?.join('. ') || e.message;
this.flashMessages.danger( this.flashMessages.danger(
errorMessage || 'Could not save the role. Please check Vault logs for more information.' errorMessage || 'Could not save the role. Please check Vault logs for more information.'

View File

@ -20,7 +20,7 @@ export default class DatabaseRoleSettingForm extends Component {
get settingFields() { get settingFields() {
if (!this.args.roleType) return null; if (!this.args.roleType) return null;
let dbValidFields = getRoleFields(this.args.roleType); let dbValidFields = getRoleFields(this.args.roleType);
return this.args.attrs.filter(a => { return this.args.attrs.filter((a) => {
return dbValidFields.includes(a.name); return dbValidFields.includes(a.name);
}); });
} }
@ -30,7 +30,7 @@ export default class DatabaseRoleSettingForm extends Component {
const plugin = this.args.dbType; const plugin = this.args.dbType;
if (!type) return null; if (!type) return null;
let dbValidFields = getStatementFields(type, plugin); let dbValidFields = getStatementFields(type, plugin);
return this.args.attrs.filter(a => { return this.args.attrs.filter((a) => {
return dbValidFields.includes(a.name); return dbValidFields.includes(a.name);
}); });
} }

View File

@ -35,14 +35,14 @@ export default class DiffVersionSelector extends Component {
let string = `["${this.args.model.engineId}", "${this.args.model.id}", "${this.args.model.currentVersion}"]`; let string = `["${this.args.model.engineId}", "${this.args.model.id}", "${this.args.model.currentVersion}"]`;
return this.adapter return this.adapter
.querySecretDataByVersion(string) .querySecretDataByVersion(string)
.then(response => response.data) .then((response) => response.data)
.catch(() => null); .catch(() => null);
} }
get rightSideDataInit() { get rightSideDataInit() {
let string = `["${this.args.model.engineId}", "${this.args.model.id}", "${this.rightSideVersionInit}"]`; let string = `["${this.args.model.engineId}", "${this.args.model.id}", "${this.rightSideVersionInit}"]`;
return this.adapter return this.adapter
.querySecretDataByVersion(string) .querySecretDataByVersion(string)
.then(response => response.data) .then((response) => response.data)
.catch(() => null); .catch(() => null);
} }
get rightSideVersionInit() { get rightSideVersionInit() {

View File

@ -1,15 +0,0 @@
/**
* @module FormFieldGroupsLoop
* FormFieldGroupsLoop components are used to show optional form fields, generally when setting up a secret engine.
*
* @example
* ```js
* <FormFieldGroupsLoop @model={{model}} @mode={{mode}}/>
* ```
* @param {object} model - the data model of the parent component
* @param {object} model - the mode: create show or edit.
*/
import Component from '@glimmer/component';
export default class FormFieldGroupsLoop extends Component {}

View File

@ -48,7 +48,7 @@ export default Component.extend({
this.router.transitionTo('vault.cluster.secrets.backend.list-root', this.backendPath); this.router.transitionTo('vault.cluster.secrets.backend.list-root', this.backendPath);
}, },
options: computed('action', 'backendType', function() { options: computed('action', 'backendType', function () {
const action = this.action || 'creds'; const action = this.action || 'creds';
return MODEL_TYPES[`${this.backendType}-${action}`]; return MODEL_TYPES[`${this.backendType}-${action}`];
}), }),
@ -59,6 +59,7 @@ export default Component.extend({
}, },
didReceiveAttrs() { didReceiveAttrs() {
this._super();
if (this.wizard.featureState === 'displayRole') { if (this.wizard.featureState === 'displayRole') {
this.wizard.transitionFeatureMachine(this.wizard.featureState, 'CONTINUE', this.backendType); this.wizard.transitionFeatureMachine(this.wizard.featureState, 'CONTINUE', this.backendType);
} }

View File

@ -3,6 +3,7 @@ import { inject as service } from '@ember/service';
import Component from '@ember/component'; import Component from '@ember/component';
import { computed, set } from '@ember/object'; import { computed, set } from '@ember/object';
import { task } from 'ember-concurrency'; import { task } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
/** /**
* @module GeneratedItem * @module GeneratedItem
@ -26,10 +27,11 @@ export default Component.extend({
router: service(), router: service(),
validationMessages: null, validationMessages: null,
isFormInvalid: false, isFormInvalid: false,
props: computed('model', function() { props: computed('model', function () {
return this.model.serialize(); return this.model.serialize();
}), }),
saveModel: task(function*() { saveModel: task(
waitFor(function* () {
try { try {
yield this.model.save(); yield this.model.save();
} catch (err) { } catch (err) {
@ -42,16 +44,17 @@ export default Component.extend({
} }
this.router.transitionTo('vault.cluster.access.method.item.list').followRedirects(); this.router.transitionTo('vault.cluster.access.method.item.list').followRedirects();
this.flashMessages.success(`Successfully saved ${this.itemType} ${this.model.id}.`); this.flashMessages.success(`Successfully saved ${this.itemType} ${this.model.id}.`);
}).withTestWaiter(), })
),
init() { init() {
this._super(...arguments); this._super(...arguments);
this.set('validationMessages', {}); this.set('validationMessages', {});
if (this.mode === 'edit') { if (this.mode === 'edit') {
// For validation to work in edit mode, // For validation to work in edit mode,
// reconstruct the model values from field group // reconstruct the model values from field group
this.model.fieldGroups.forEach(element => { this.model.fieldGroups.forEach((element) => {
if (element.default) { if (element.default) {
element.default.forEach(attr => { element.default.forEach((attr) => {
let fieldValue = attr.options && attr.options.fieldValue; let fieldValue = attr.options && attr.options.fieldValue;
if (fieldValue) { if (fieldValue) {
this.model[attr.name] = this.model[fieldValue]; this.model[attr.name] = this.model[fieldValue];

View File

@ -19,11 +19,11 @@ import { computed } from '@ember/object';
export default Component.extend({ export default Component.extend({
tagName: '', tagName: '',
text: computed(function() { text: computed(function () {
return 'home'; return 'home';
}), }),
computedClasses: computed('classNames', function() { computedClasses: computed('classNames', function () {
return this.classNames.join(' '); return this.classNames.join(' ');
}), }),
}); });

View File

@ -32,7 +32,7 @@ export default Component.extend({
this.onSuccess(); this.onSuccess();
this.flashMessages.success(this.successMessage(...messageArgs)); this.flashMessages.success(this.successMessage(...messageArgs));
}) })
.catch(e => { .catch((e) => {
this.onError(...messageArgs); this.onError(...messageArgs);
this.flashMessages.success(this.errorMessage(e, ...messageArgs)); this.flashMessages.success(this.errorMessage(e, ...messageArgs));
}); });

View File

@ -3,6 +3,7 @@ import Component from '@ember/component';
import { computed } from '@ember/object'; import { computed } from '@ember/object';
import { task } from 'ember-concurrency'; import { task } from 'ember-concurrency';
import { humanize } from 'vault/helpers/humanize'; import { humanize } from 'vault/helpers/humanize';
import { waitFor } from '@ember/test-waiters';
export default Component.extend({ export default Component.extend({
flashMessages: service(), flashMessages: service(),
@ -19,7 +20,7 @@ export default Component.extend({
*/ */
onSave: () => {}, onSave: () => {},
cancelLink: computed('mode', 'model.identityType', function() { cancelLink: computed('mode', 'model.identityType', function () {
let { model, mode } = this; let { model, mode } = this;
let routes = { let routes = {
'create-entity': 'vault.cluster.access.identity', 'create-entity': 'vault.cluster.access.identity',
@ -49,7 +50,8 @@ export default Component.extend({
return `Successfully ${action} ${typeDisplay}.`; return `Successfully ${action} ${typeDisplay}.`;
}, },
save: task(function*() { save: task(
waitFor(function* () {
let model = this.model; let model = this.model;
let message = this.getMessage(model); let message = this.getMessage(model);
@ -62,10 +64,10 @@ export default Component.extend({
this.flashMessages.success(message); this.flashMessages.success(message);
yield this.onSave({ saveType: 'save', model }); yield this.onSave({ saveType: 'save', model });
}) })
.drop() ).drop(),
.withTestWaiter(),
willDestroy() { willDestroy() {
this._super(...arguments);
let model = this.model; let model = this.model;
if (!model) return; if (!model) return;
if ((model.get('isDirty') && !model.isDestroyed) || !model.isDestroying) { if ((model.get('isDirty') && !model.isDestroyed) || !model.isDestroying) {

View File

@ -13,7 +13,7 @@ export default Component.extend({
.then(() => { .then(() => {
this.flashMessages.success(`Successfully enabled entity: ${model.id}`); this.flashMessages.success(`Successfully enabled entity: ${model.id}`);
}) })
.catch(e => { .catch((e) => {
this.flashMessages.success( this.flashMessages.success(
`There was a problem enabling the entity: ${model.id} - ${e.errors.join(' ') || e.message}` `There was a problem enabling the entity: ${model.id} - ${e.errors.join(' ') || e.message}`
); );

View File

@ -20,7 +20,7 @@ export default Component.extend({
init() { init() {
this._super(...arguments); this._super(...arguments);
this.store.findAll('auth-method').then(methods => { this.store.findAll('auth-method').then((methods) => {
this.set('authMethods', methods); this.set('authMethods', methods);
this.set('aliasMountAccessor', methods.get('firstObject.accessor')); this.set('aliasMountAccessor', methods.get('firstObject.accessor'));
}); });
@ -43,7 +43,7 @@ export default Component.extend({
return data; return data;
}, },
lookup: task(function*() { lookup: task(function* () {
let flash = this.flashMessages; let flash = this.flashMessages;
let type = this.type; let type = this.type;
let store = this.store; let store = this.store;

View File

@ -5,11 +5,11 @@ import Base from './_popup-base';
export default Base.extend({ export default Base.extend({
model: alias('params.firstObject'), model: alias('params.firstObject'),
groupArray: computed('params', function() { groupArray: computed('params', function () {
return this.params.objectAt(1); return this.params.objectAt(1);
}), }),
memberId: computed('params', function() { memberId: computed('params', function () {
return this.params.objectAt(2); return this.params.objectAt(2);
}), }),

View File

@ -4,7 +4,7 @@ import { alias } from '@ember/object/computed';
export default Base.extend({ export default Base.extend({
model: alias('params.firstObject'), model: alias('params.firstObject'),
key: computed('params', function() { key: computed('params', function () {
return this.params.objectAt(1); return this.params.objectAt(1);
}), }),

View File

@ -4,7 +4,7 @@ import Base from './_popup-base';
export default Base.extend({ export default Base.extend({
model: alias('params.firstObject'), model: alias('params.firstObject'),
policyName: computed('params', function() { policyName: computed('params', function () {
return this.params.objectAt(1); return this.params.objectAt(1);
}), }),

View File

@ -51,15 +51,15 @@ export default Component.extend({
kvData: null, kvData: null,
kvDataAsJSON: computed('kvData', 'kvData.[]', function() { kvDataAsJSON: computed('kvData', 'kvData.[]', function () {
return this.kvData.toJSON(); return this.kvData.toJSON();
}), }),
kvDataIsAdvanced: computed('kvData', 'kvData.[]', function() { kvDataIsAdvanced: computed('kvData', 'kvData.[]', function () {
return this.kvData.isAdvanced(); return this.kvData.isAdvanced();
}), }),
kvHasDuplicateKeys: computed('kvData', 'kvData.@each.name', function() { kvHasDuplicateKeys: computed('kvData', 'kvData.@each.name', function () {
let data = this.kvData; let data = this.kvData;
return data.uniqBy('name').length !== data.get('length'); return data.uniqBy('name').length !== data.get('length');
}), }),

View File

@ -23,7 +23,7 @@ import { allFeatures } from 'vault/helpers/all-features';
*/ */
export default class LicenseInfoComponent extends Component { export default class LicenseInfoComponent extends Component {
get featuresInfo() { get featuresInfo() {
return allFeatures().map(feature => { return allFeatures().map((feature) => {
let active = this.args.features.includes(feature); let active = this.args.features.includes(feature);
if (active && feature === 'Performance Standby') { if (active && feature === 'Performance Standby') {
let count = this.args.performanceStandbyCount; let count = this.args.performanceStandbyCount;

View File

@ -15,7 +15,7 @@ export default Component.extend({
this.authMethods.perform(); this.authMethods.perform();
}, },
authMethods: task(function*() { authMethods: task(function* () {
let methods = yield this.store.findAll('auth-method'); let methods = yield this.store.findAll('auth-method');
if (!this.value) { if (!this.value) {
this.set('value', methods.get('firstObject.accessor')); this.set('value', methods.get('firstObject.accessor'));

View File

@ -5,6 +5,7 @@ import Component from '@ember/component';
import { task } from 'ember-concurrency'; import { task } from 'ember-concurrency';
import { methods } from 'vault/helpers/mountable-auth-methods'; import { methods } from 'vault/helpers/mountable-auth-methods';
import { engines, KMIP, TRANSFORM } from 'vault/helpers/mountable-secret-engines'; import { engines, KMIP, TRANSFORM } from 'vault/helpers/mountable-secret-engines';
import { waitFor } from '@ember/test-waiters';
const METHODS = methods(); const METHODS = methods();
const ENGINES = engines(); const ENGINES = engines();
@ -62,11 +63,11 @@ export default Component.extend({
}); });
}, },
mountTypes: computed('engines', 'mountType', function() { mountTypes: computed('engines', 'mountType', function () {
return this.mountType === 'secret' ? this.engines : METHODS; return this.mountType === 'secret' ? this.engines : METHODS;
}), }),
engines: computed('version.{features[],isEnterprise}', function() { engines: computed('version.{features[],isEnterprise}', function () {
if (this.version.isEnterprise) { if (this.version.isEnterprise) {
return ENGINES.concat([KMIP, TRANSFORM]); return ENGINES.concat([KMIP, TRANSFORM]);
} }
@ -74,6 +75,7 @@ export default Component.extend({
}), }),
willDestroy() { willDestroy() {
this._super(...arguments);
// if unsaved, we want to unload so it doesn't show up in the auth mount list // if unsaved, we want to unload so it doesn't show up in the auth mount list
this.mountModel.rollbackAttributes(); this.mountModel.rollbackAttributes();
}, },
@ -90,7 +92,8 @@ export default Component.extend({
} }
}, },
mountBackend: task(function*() { mountBackend: task(
waitFor(function* () {
const mountModel = this.mountModel; const mountModel = this.mountModel;
const { type, path } = mountModel; const { type, path } = mountModel;
let capabilities = null; let capabilities = null;
@ -142,8 +145,7 @@ export default Component.extend({
yield this.onMountSuccess(type, path); yield this.onMountSuccess(type, path);
return; return;
}) })
.drop() ).drop(),
.withTestWaiter(),
actions: { actions: {
onKeyUp(name, value) { onKeyUp(name, value) {

View File

@ -12,12 +12,12 @@ export default Component.extend({
targetNamespace: null, targetNamespace: null,
showLastSegment: false, showLastSegment: false,
normalizedNamespace: computed('targetNamespace', function() { normalizedNamespace: computed('targetNamespace', function () {
let ns = this.targetNamespace; let ns = this.targetNamespace;
return (ns || '').replace(/\.+/g, '/').replace(/☃/g, '.'); return (ns || '').replace(/\.+/g, '/').replace(/☃/g, '.');
}), }),
namespaceDisplay: computed('normalizedNamespace', 'showLastSegment', function() { namespaceDisplay: computed('normalizedNamespace', 'showLastSegment', function () {
let ns = this.normalizedNamespace; let ns = this.normalizedNamespace;
if (!ns) return 'root'; if (!ns) return 'root';
let showLastSegment = this.showLastSegment; let showLastSegment = this.showLastSegment;
@ -25,7 +25,7 @@ export default Component.extend({
return showLastSegment ? parts[parts.length - 1] : ns; return showLastSegment ? parts[parts.length - 1] : ns;
}), }),
isCurrentNamespace: computed('targetNamespace', 'currentNamespace', function() { isCurrentNamespace: computed('targetNamespace', 'currentNamespace', function () {
return this.currentNamespace === this.targetNamespace; return this.currentNamespace === this.targetNamespace;
}), }),

View File

@ -36,7 +36,7 @@ export default Component.extend({
this.set('oldNamespace', ns); this.set('oldNamespace', ns);
}, },
fetchListCapability: task(function*() { fetchListCapability: task(function* () {
try { try {
let capability = yield this.store.findRecord('capabilities', 'sys/namespaces/'); let capability = yield this.store.findRecord('capabilities', 'sys/namespaces/');
this.set('listCapability', capability); this.set('listCapability', capability);
@ -47,7 +47,7 @@ export default Component.extend({
this.set('canList', false); this.set('canList', false);
} }
}), }),
setForAnimation: task(function*() { setForAnimation: task(function* () {
let leaves = this.menuLeaves; let leaves = this.menuLeaves;
let lastLeaves = this.lastMenuLeaves; let lastLeaves = this.lastMenuLeaves;
if (!lastLeaves) { if (!lastLeaves) {
@ -81,7 +81,7 @@ export default Component.extend({
accessibleNamespaces: alias('namespaceService.accessibleNamespaces'), accessibleNamespaces: alias('namespaceService.accessibleNamespaces'),
inRootNamespace: alias('namespaceService.inRootNamespace'), inRootNamespace: alias('namespaceService.inRootNamespace'),
namespaceTree: computed('accessibleNamespaces', function() { namespaceTree: computed('accessibleNamespaces', function () {
let nsList = this.accessibleNamespaces; let nsList = this.accessibleNamespaces;
if (!nsList) { if (!nsList) {
@ -123,7 +123,7 @@ export default Component.extend({
// to render the nodes of each leaf // to render the nodes of each leaf
// gets set as 'lastMenuLeaves' in the ember concurrency task above // gets set as 'lastMenuLeaves' in the ember concurrency task above
menuLeaves: computed('namespacePath', 'namespaceTree', 'pathToLeaf', function() { menuLeaves: computed('namespacePath', 'namespaceTree', 'pathToLeaf', function () {
let ns = this.namespacePath; let ns = this.namespacePath;
ns = (ns || '').replace(/^\//, ''); ns = (ns || '').replace(/^\//, '');
let leaves = ancestorKeysForKey(ns); let leaves = ancestorKeysForKey(ns);
@ -136,7 +136,7 @@ export default Component.extend({
// the nodes at the root of the namespace tree // the nodes at the root of the namespace tree
// these will get rendered as the bottom layer // these will get rendered as the bottom layer
rootLeaves: computed('namespaceTree', function() { rootLeaves: computed('namespaceTree', function () {
let tree = this.namespaceTree; let tree = this.namespaceTree;
let leaves = Object.keys(tree); let leaves = Object.keys(tree);
return leaves; return leaves;
@ -144,11 +144,11 @@ export default Component.extend({
currentLeaf: alias('lastMenuLeaves.lastObject'), currentLeaf: alias('lastMenuLeaves.lastObject'),
canAccessMultipleNamespaces: gt('accessibleNamespaces.length', 1), canAccessMultipleNamespaces: gt('accessibleNamespaces.length', 1),
isUserRootNamespace: computed('auth.authData.userRootNamespace', 'namespacePath', function() { isUserRootNamespace: computed('auth.authData.userRootNamespace', 'namespacePath', function () {
return this.auth.authData.userRootNamespace === this.namespacePath; return this.auth.authData.userRootNamespace === this.namespacePath;
}), }),
namespaceDisplay: computed('namespacePath', 'accessibleNamespaces', 'accessibleNamespaces.[]', function() { namespaceDisplay: computed('namespacePath', 'accessibleNamespaces', 'accessibleNamespaces.[]', function () {
let namespace = this.namespacePath; let namespace = this.namespacePath;
if (!namespace) return ''; if (!namespace) return '';
let parts = namespace?.split('/'); let parts = namespace?.split('/');

View File

@ -9,7 +9,7 @@ export default Component.extend({
tagName: 'header', tagName: 'header',
navDrawerOpen: false, navDrawerOpen: false,
consoleFullscreen: false, consoleFullscreen: false,
hideLinks: computed('router.currentRouteName', function() { hideLinks: computed('router.currentRouteName', function () {
let currentRoute = this.router.currentRouteName; let currentRoute = this.router.currentRouteName;
if ('vault.cluster.oidc-provider' === currentRoute) { if ('vault.cluster.oidc-provider' === currentRoute) {
return true; return true;

View File

@ -27,7 +27,7 @@ export default class OidcConsentBlockComponent extends Component {
buildUrl(urlString, params) { buildUrl(urlString, params) {
try { try {
let url = new URL(urlString); let url = new URL(urlString);
Object.keys(params).forEach(key => { Object.keys(params).forEach((key) => {
if (params[key] && validParameters.includes(key)) { if (params[key] && validParameters.includes(key)) {
url.searchParams.append(key, params[key]); url.searchParams.append(key, params[key]);
} }

View File

@ -1,6 +1,8 @@
import Component from '@ember/component'; import Component from '@ember/component';
import { set } from '@ember/object'; import { set } from '@ember/object';
import { task } from 'ember-concurrency'; import { task } from 'ember-concurrency';
import { waitFor } from '@ember/test-waiters';
const BASE_64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gi; const BASE_64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gi;
export default Component.extend({ export default Component.extend({
@ -41,7 +43,8 @@ export default Component.extend({
reader.readAsDataURL(file); reader.readAsDataURL(file);
}, },
setPGPKey: task(function*(dataURL, filename) { setPGPKey: task(
waitFor(function* (dataURL, filename) {
const b64File = dataURL.split(',')[1].trim(); const b64File = dataURL.split(',')[1].trim();
const decoded = atob(b64File).trim(); const decoded = atob(b64File).trim();
@ -51,7 +54,8 @@ export default Component.extend({
// the original as it was only encoded when we used `readAsDataURL`. // the original as it was only encoded when we used `readAsDataURL`.
const fileData = decoded.match(BASE_64_REGEX) ? decoded : b64File; const fileData = decoded.match(BASE_64_REGEX) ? decoded : b64File;
yield this.onChange(this.index, { value: fileData, fileName: filename }); yield this.onChange(this.index, { value: fileData, fileName: filename });
}).withTestWaiter(), })
),
actions: { actions: {
pickedFile(e) { pickedFile(e) {

View File

@ -34,7 +34,7 @@ export default Component.extend({
list = [...this.listData, ...this.newList(this.listLength - this.listData.length)]; list = [...this.listData, ...this.newList(this.listLength - this.listData.length)];
} }
this.set('listData', list || this.listData); this.set('listData', list || this.listData);
this.onDataUpdate((list || this.listData).compact().map(k => k.value)); this.onDataUpdate((list || this.listData).compact().map((k) => k.value));
}, },
newList(length) { newList(length) {
@ -47,7 +47,7 @@ export default Component.extend({
setKey(index, key) { setKey(index, key) {
let { listData } = this; let { listData } = this;
listData.splice(index, 1, key); listData.splice(index, 1, key);
this.onDataUpdate(listData.compact().map(k => k.value)); this.onDataUpdate(listData.compact().map((k) => k.value));
}, },
}, },
}); });

View File

@ -37,7 +37,7 @@ export default Component.extend({
defaultSpan: 12, defaultSpan: 12,
retentionMonths: 24, retentionMonths: 24,
startDate: computed('start', function() { startDate: computed('start', function () {
if (!this.start) return null; if (!this.start) return null;
let date; let date;
try { try {
@ -48,7 +48,7 @@ export default Component.extend({
return null; return null;
} }
}), }),
endDate: computed('end', function() { endDate: computed('end', function () {
if (!this.end) return null; if (!this.end) return null;
let date; let date;
try { try {
@ -60,7 +60,7 @@ export default Component.extend({
} }
}), }),
error: computed('end', 'endDate', 'retentionMonths', 'start', 'startDate', function() { error: computed('end', 'endDate', 'retentionMonths', 'start', 'startDate', function () {
if (!this.startDate) { if (!this.startDate) {
return 'Start date is invalid. Please use format MM/yyyy'; return 'Start date is invalid. Please use format MM/yyyy';
} }

View File

@ -10,20 +10,20 @@ export default Component.extend({
size: 20, size: 20,
strokeWidth: 1, strokeWidth: 1,
viewBox: computed('size', function() { viewBox: computed('size', function () {
let s = this.size; let s = this.size;
return `0 0 ${s} ${s}`; return `0 0 ${s} ${s}`;
}), }),
centerValue: computed('size', function() { centerValue: computed('size', function () {
return this.size / 2; return this.size / 2;
}), }),
r: computed('size', 'strokeWidth', function() { r: computed('size', 'strokeWidth', function () {
return (this.size - this.strokeWidth) / 2; return (this.size - this.strokeWidth) / 2;
}), }),
c: computed('r', function() { c: computed('r', function () {
return 2 * Math.PI * this.r; return 2 * Math.PI * this.r;
}), }),
dashArrayOffset: computed('c', 'progressDecimal', function() { dashArrayOffset: computed('c', 'progressDecimal', function () {
return this.c * (1 - this.progressDecimal); return this.c * (1 - this.progressDecimal);
}), }),
}); });

View File

@ -12,7 +12,7 @@ export default Component.extend({
flashMessages: service(), flashMessages: service(),
isUploading: alias('restore.isRunning'), isUploading: alias('restore.isRunning'),
abortController: null, abortController: null,
restore: task(function*() { restore: task(function* () {
this.set('errors', null); this.set('errors', null);
let adapter = getOwner(this).lookup('adapter:application'); let adapter = getOwner(this).lookup('adapter:application');
try { try {

View File

@ -1,18 +1,26 @@
<div class="field"> <div class="field">
<div class="regex-label-wrapper"> <div class="regex-label-wrapper">
<div class="regex-label"> <div class="regex-label">
<label for="{{@attr.name}}" class="is-label"> <label for={{@attr.name}} class="is-label">
{{@labelString}} {{@labelString}}
{{#if @attr.options.helpText}} {{#if @attr.options.helpText}}
{{#info-tooltip}} <InfoTooltip>
<span data-test-help-text> <span data-test-help-text>
{{@attr.options.helpText}} {{@attr.options.helpText}}
</span> </span>
{{/info-tooltip}} </InfoTooltip>
{{/if}} {{/if}}
</label> </label>
{{#if @attr.options.subText}} {{#if @attr.options.subText}}
<p class="sub-text">{{@attr.options.subText}} {{#if @attr.options.docLink}}<a href="{{@attr.options.docLink}}" target="_blank" rel="noopener noreferrer">See our documentation</a> for help.{{/if}}</p> <p class="sub-text">
{{@attr.options.subText}}
{{#if @attr.options.docLink}}
<a href={{@attr.options.docLink}} target="_blank" rel="noopener noreferrer">
See our documentation
</a>
for help.
{{/if}}
</p>
{{/if}} {{/if}}
</div> </div>
<div> <div>
@ -32,14 +40,14 @@
data-test-input={{@attr.name}} data-test-input={{@attr.name}}
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
{{on 'change' @onChange}} {{on "change" @onChange}}
value={{@value}} value={{@value}}
class="input" class="input"
/> />
</div> </div>
{{#if this.showTestValue}} {{#if this.showTestValue}}
<div data-test-regex-validator-test-string> <div data-test-regex-validator-test-string>
<label for="{{@attr.name}}" class="is-label"> <label for={{@attr.name}} class="is-label">
Test string Test string
</label> </label>
<input <input
@ -48,8 +56,9 @@
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
value={{this.testValue}} value={{this.testValue}}
{{on 'change' this.updateTestValue}} {{on "change" this.updateTestValue}}
class="input {{if this.regexError 'has-error'}}" /> class="input {{if this.regexError "has-error"}}"
/>
{{#if (and this.testValue @value)}} {{#if (and this.testValue @value)}}
<div data-test-regex-validation-message> <div data-test-regex-validation-message>
@ -63,6 +72,5 @@
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}

View File

@ -41,7 +41,7 @@ export default Component.extend(FocusOnInsertMixin, {
} }
}, },
waitForKeyUp: task(function*() { waitForKeyUp: task(function* () {
while (true) { while (true) {
let event = yield waitForEvent(document.body, 'keyup'); let event = yield waitForEvent(document.body, 'keyup');
this.onEscape(event); this.onEscape(event);

View File

@ -28,9 +28,8 @@ import ControlGroupError from 'vault/lib/control-group-error';
import Ember from 'ember'; import Ember from 'ember';
import keys from 'vault/lib/keycodes'; import keys from 'vault/lib/keycodes';
import { action } from '@ember/object'; import { action, set } from '@ember/object';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import { set } from '@ember/object';
import { tracked } from '@glimmer/tracking'; import { tracked } from '@glimmer/tracking';
import { isBlank, isNone } from '@ember/utils'; import { isBlank, isNone } from '@ember/utils';
@ -66,7 +65,7 @@ export default class SecretCreateOrUpdate extends Component {
let adapter = this.store.adapterFor('secret-v2'); let adapter = this.store.adapterFor('secret-v2');
let type = { modelName: 'secret-v2' }; let type = { modelName: 'secret-v2' };
let query = { backend: this.args.model.backend }; let query = { backend: this.args.model.backend };
adapter.query(this.store, type, query).then(result => { adapter.query(this.store, type, query).then((result) => {
this.secretPaths = result.data.keys; this.secretPaths = result.data.keys;
}); });
} }
@ -143,7 +142,7 @@ export default class SecretCreateOrUpdate extends Component {
.then(() => { .then(() => {
this.saveComplete(successCallback, key); this.saveComplete(successCallback, key);
}) })
.catch(e => { .catch((e) => {
// when mode is not create the metadata error is handled in secret-edit-metadata // when mode is not create the metadata error is handled in secret-edit-metadata
if (this.args.mode === 'create') { if (this.args.mode === 'create') {
this.error = e.errors.join(' '); this.error = e.errors.join(' ');
@ -155,7 +154,7 @@ export default class SecretCreateOrUpdate extends Component {
} }
} }
}) })
.catch(error => { .catch((error) => {
if (error instanceof ControlGroupError) { if (error instanceof ControlGroupError) {
let errorMessage = this.controlGroup.logFromError(error); let errorMessage = this.controlGroup.logFromError(error);
this.error = errorMessage.content; this.error = errorMessage.content;
@ -188,7 +187,7 @@ export default class SecretCreateOrUpdate extends Component {
return false; return false;
} }
@(task(function*(name, value) { @(task(function* (name, value) {
this.checkValidation(name, value); this.checkValidation(name, value);
while (true) { while (true) {
let event = yield waitForEvent(document.body, 'keyup'); let event = yield waitForEvent(document.body, 'keyup');

View File

@ -1,3 +1,4 @@
/* eslint ember/no-computed-properties-in-native-classes: 'warn' */
import Ember from 'ember'; import Ember from 'ember';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import Component from '@glimmer/component'; import Component from '@glimmer/component';
@ -6,7 +7,7 @@ import { action } from '@ember/object';
import { alias } from '@ember/object/computed'; import { alias } from '@ember/object/computed';
import { maybeQueryRecord } from 'vault/macros/maybe-query-record'; import { maybeQueryRecord } from 'vault/macros/maybe-query-record';
const getErrorMessage = errors => { const getErrorMessage = (errors) => {
let errorMessage = errors?.join('. ') || 'Something went wrong. Check the Vault logs for more information.'; let errorMessage = errors?.join('. ') || 'Something went wrong. Check the Vault logs for more information.';
return errorMessage; return errorMessage;
}; };
@ -19,7 +20,7 @@ export default class SecretDeleteMenu extends Component {
@maybeQueryRecord( @maybeQueryRecord(
'capabilities', 'capabilities',
context => { (context) => {
if (!context.args || !context.args.modelForData || !context.args.modelForData.id) return; if (!context.args || !context.args.modelForData || !context.args.modelForData.id) return;
let [backend, id] = JSON.parse(context.args.modelForData.id); let [backend, id] = JSON.parse(context.args.modelForData.id);
return { return {
@ -33,7 +34,7 @@ export default class SecretDeleteMenu extends Component {
@maybeQueryRecord( @maybeQueryRecord(
'capabilities', 'capabilities',
context => { (context) => {
if (!context.args || !context.args.modelForData || !context.args.modelForData.id) return; if (!context.args || !context.args.modelForData || !context.args.modelForData.id) return;
let [backend, id] = JSON.parse(context.args.modelForData.id); let [backend, id] = JSON.parse(context.args.modelForData.id);
return { return {
@ -47,7 +48,7 @@ export default class SecretDeleteMenu extends Component {
@maybeQueryRecord( @maybeQueryRecord(
'capabilities', 'capabilities',
context => { (context) => {
if (!context.args.model || !context.args.model.engine || !context.args.model.id) return; if (!context.args.model || !context.args.model.engine || !context.args.model.id) return;
let backend = context.args.model.engine.id; let backend = context.args.model.engine.id;
let id = context.args.model.id; let id = context.args.model.id;
@ -64,7 +65,7 @@ export default class SecretDeleteMenu extends Component {
@maybeQueryRecord( @maybeQueryRecord(
'capabilities', 'capabilities',
context => { (context) => {
if (!context.args.model || context.args.mode === 'create') { if (!context.args.model || context.args.mode === 'create') {
return; return;
} }
@ -85,7 +86,7 @@ export default class SecretDeleteMenu extends Component {
@maybeQueryRecord( @maybeQueryRecord(
'capabilities', 'capabilities',
context => { (context) => {
if (!context.args.model || context.args.mode === 'create') { if (!context.args.model || context.args.mode === 'create') {
return; return;
} }
@ -136,7 +137,7 @@ export default class SecretDeleteMenu extends Component {
return this.store return this.store
.adapterFor('secret-v2-version') .adapterFor('secret-v2-version')
.v2DeleteOperation(this.store, this.args.modelForData.id, deleteType, currentVersionForNoReadMetadata) .v2DeleteOperation(this.store, this.args.modelForData.id, deleteType, currentVersionForNoReadMetadata)
.then(resp => { .then((resp) => {
if (Ember.testing) { if (Ember.testing) {
this.showDeleteModal = false; this.showDeleteModal = false;
// we don't want a refresh otherwise test loop will rerun in a loop // we don't want a refresh otherwise test loop will rerun in a loop

View File

@ -16,9 +16,8 @@
*/ */
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import { action } from '@ember/object'; import { action, set } from '@ember/object';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import { set } from '@ember/object';
import { tracked } from '@glimmer/tracking'; import { tracked } from '@glimmer/tracking';
export default class SecretEditMetadata extends Component { export default class SecretEditMetadata extends Component {

View File

@ -36,7 +36,7 @@
* @param {object} wrappedData - when copy the data it's the token of the secret returned. * @param {object} wrappedData - when copy the data it's the token of the secret returned.
* @param {object} editActions - actions passed from parent to child * @param {object} editActions - actions passed from parent to child
*/ */
/* eslint ember/no-computed-properties-in-native-classes: 'warn' */
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import { action } from '@ember/object'; import { action } from '@ember/object';
import { not } from '@ember/object/computed'; import { not } from '@ember/object/computed';
@ -75,7 +75,7 @@ export default class SecretEditToolbar extends Component {
this.store this.store
.adapterFor('secret-v2-version') .adapterFor('secret-v2-version')
.queryRecord(this.args.modelForData.id, { wrapTTL: 1800 }) .queryRecord(this.args.modelForData.id, { wrapTTL: 1800 })
.then(resp => { .then((resp) => {
this.wrappedData = resp.wrap_info.token; this.wrappedData = resp.wrap_info.token;
this.flashMessages.success('Secret Successfully Wrapped!'); this.flashMessages.success('Secret Successfully Wrapped!');
}) })
@ -93,7 +93,7 @@ export default class SecretEditToolbar extends Component {
id: this.args.modelForData.id, id: this.args.modelForData.id,
wrapTTL: 1800, wrapTTL: 1800,
}) })
.then(resp => { .then((resp) => {
this.wrappedData = resp.wrap_info.token; this.wrappedData = resp.wrap_info.token;
this.flashMessages.success('Secret Successfully Wrapped!'); this.flashMessages.success('Secret Successfully Wrapped!');
}) })

View File

@ -73,7 +73,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
checkSecretCapabilities: maybeQueryRecord( checkSecretCapabilities: maybeQueryRecord(
'capabilities', 'capabilities',
context => { (context) => {
if (!context.model || context.mode === 'create') { if (!context.model || context.mode === 'create') {
return; return;
} }
@ -94,7 +94,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
checkMetadataCapabilities: maybeQueryRecord( checkMetadataCapabilities: maybeQueryRecord(
'capabilities', 'capabilities',
context => { (context) => {
if (!context.model || !context.isV2) { if (!context.model || !context.isV2) {
return; return;
} }
@ -117,27 +117,31 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
buttonDisabled: or('requestInFlight', 'model.isFolder', 'model.flagsIsInvalid'), buttonDisabled: or('requestInFlight', 'model.isFolder', 'model.flagsIsInvalid'),
modelForData: computed('isV2', 'model', function() { modelForData: computed('isV2', 'model', function () {
let { model } = this; let { model } = this;
if (!model) return null; if (!model) return null;
return this.isV2 ? model.belongsTo('selectedVersion').value() : model; return this.isV2 ? model.belongsTo('selectedVersion').value() : model;
}), }),
basicModeDisabled: computed('secretDataIsAdvanced', 'showAdvancedMode', function() { basicModeDisabled: computed('secretDataIsAdvanced', 'showAdvancedMode', function () {
return this.secretDataIsAdvanced || this.showAdvancedMode === false; return this.secretDataIsAdvanced || this.showAdvancedMode === false;
}), }),
secretDataAsJSON: computed('secretData', 'secretData.[]', function() { secretDataAsJSON: computed('secretData', 'secretData.[]', function () {
return this.secretData.toJSON(); return this.secretData.toJSON();
}), }),
secretDataIsAdvanced: computed('secretData', 'secretData.[]', function() { secretDataIsAdvanced: computed('secretData', 'secretData.[]', function () {
return this.secretData.isAdvanced(); return this.secretData.isAdvanced();
}), }),
showAdvancedMode: or('secretDataIsAdvanced', 'preferAdvancedEdit'), showAdvancedMode: or('secretDataIsAdvanced', 'preferAdvancedEdit'),
isWriteWithoutRead: computed('model.failedServerRead', 'modelForData.failedServerRead', 'isV2', function() { isWriteWithoutRead: computed(
'model.failedServerRead',
'modelForData.failedServerRead',
'isV2',
function () {
if (!this.model) return; if (!this.model) return;
// if the version couldn't be read from the server // if the version couldn't be read from the server
if (this.isV2 && this.modelForData.failedServerRead) { if (this.isV2 && this.modelForData.failedServerRead) {
@ -148,7 +152,8 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
return true; return true;
} }
return false; return false;
}), }
),
actions: { actions: {
refresh() { refresh() {

View File

@ -30,7 +30,7 @@ export default Component.extend({
queryParams: null, queryParams: null,
ariaLabel: null, ariaLabel: null,
linkParams: computed('mode', 'secret', 'queryParams', function() { linkParams: computed('mode', 'secret', 'queryParams', function () {
let data = { mode: this.mode, secret: this.secret, queryParams: this.queryParams }; let data = { mode: this.mode, secret: this.secret, queryParams: this.queryParams };
return linkParams(data); return linkParams(data);
}), }),

View File

@ -36,10 +36,10 @@ export default class SecretListHeaderTab extends Component {
async fetchCapabilities() { async fetchCapabilities() {
let capabilitiesArray = ['canList', 'canCreate', 'canUpdate']; let capabilitiesArray = ['canList', 'canCreate', 'canUpdate'];
let checkCapabilities = function(object) { let checkCapabilities = function (object) {
let array = []; let array = [];
// we only want to look at the canList, canCreate and canUpdate on the capabilities record // we only want to look at the canList, canCreate and canUpdate on the capabilities record
capabilitiesArray.forEach(item => { capabilitiesArray.forEach((item) => {
// object is sometimes null // object is sometimes null
if (object) { if (object) {
array.push(object[item]); array.push(object[item]);
@ -47,7 +47,7 @@ export default class SecretListHeaderTab extends Component {
}); });
return array; return array;
}; };
let checker = arr => arr.every(item => !item); // same things as listing every item as !item && !item, etc. let checker = (arr) => arr.every((item) => !item); // same things as listing every item as !item && !item, etc.
// For now only check capabilities for the Database Secrets Engine // For now only check capabilities for the Database Secrets Engine
if (this.args.displayName === 'Database') { if (this.args.displayName === 'Database') {
let peekRecordRoles = this.store.peekRecord('capabilities', 'database/roles/'); let peekRecordRoles = this.store.peekRecord('capabilities', 'database/roles/');

Some files were not shown because too many files have changed in this diff Show More