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:
parent
5e316537f2
commit
5c2a08de6d
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:change
|
||||||
|
ui: Upgrade Ember to version 3.24
|
||||||
|
```
|
|
@ -0,0 +1,3 @@
|
||||||
|
defaults
|
||||||
|
not IE 11
|
||||||
|
maintained node versions
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
/coverage/
|
/coverage/
|
||||||
|
!.*
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
# ember-try
|
# ember-try
|
||||||
/.node_modules.ember-try/
|
/.node_modules.ember-try/
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
/.sass-cache
|
/.sass-cache
|
||||||
|
/.eslintcache
|
||||||
/connect.lock
|
/connect.lock
|
||||||
/coverage/
|
/coverage/
|
||||||
/libpeerconnection.log
|
/libpeerconnection.log
|
||||||
|
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"printWidth": 110
|
|
||||||
}
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: 'es5',
|
||||||
|
printWidth: 110,
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: '*.hbs',
|
||||||
|
options: {
|
||||||
|
singleQuote: false,
|
||||||
|
printWidth: 125,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
'require-input-label': 'off',
|
||||||
'simple-unless': false,
|
'no-down-event-binding': 'warn',
|
||||||
|
'self-closing-void-elements': 'off',
|
||||||
'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,
|
|
||||||
},
|
},
|
||||||
|
ignore: ['lib/story-md', 'tests/**'],
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 });
|
||||||
|
|
|
@ -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 === '') {
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,23 +24,25 @@ const AuthConfigBase = Component.extend({
|
||||||
flashMessages: service(),
|
flashMessages: service(),
|
||||||
router: service(),
|
router: service(),
|
||||||
wizard: service(),
|
wizard: service(),
|
||||||
saveModel: task(function*() {
|
saveModel: task(
|
||||||
try {
|
waitFor(function* () {
|
||||||
yield this.model.save();
|
try {
|
||||||
} catch (err) {
|
yield this.model.save();
|
||||||
// AdapterErrors are handled by the error-message component
|
} catch (err) {
|
||||||
// in the form
|
// AdapterErrors are handled by the error-message component
|
||||||
if (err instanceof AdapterError === false) {
|
// in the form
|
||||||
throw err;
|
if (err instanceof AdapterError === false) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
if (this.wizard.currentMachine === 'authentication' && this.wizard.featureState === 'config') {
|
||||||
}
|
this.wizard.transitionFeatureMachine(this.wizard.featureState, 'CONTINUE');
|
||||||
if (this.wizard.currentMachine === 'authentication' && this.wizard.featureState === 'config') {
|
}
|
||||||
this.wizard.transitionFeatureMachine(this.wizard.featureState, 'CONTINUE');
|
this.router.transitionTo('vault.cluster.access.methods').followRedirects();
|
||||||
}
|
this.flashMessages.success('The configuration was saved successfully.');
|
||||||
this.router.transitionTo('vault.cluster.access.methods').followRedirects();
|
})
|
||||||
this.flashMessages.success('The configuration was saved successfully.');
|
),
|
||||||
}).withTestWaiter(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AuthConfigBase.reopenClass({
|
AuthConfigBase.reopenClass({
|
||||||
|
|
|
@ -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,36 +20,38 @@ 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(
|
||||||
let data = this.model.config.serialize();
|
waitFor(function* () {
|
||||||
data.description = this.model.description;
|
let data = this.model.config.serialize();
|
||||||
|
data.description = this.model.description;
|
||||||
|
|
||||||
// token_type should not be tuneable for the token auth method, default is 'default-service'
|
// token_type should not be tuneable for the token auth method, default is 'default-service'
|
||||||
if (this.model.type === 'token') {
|
if (this.model.type === 'token') {
|
||||||
delete data.token_type;
|
delete data.token_type;
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
yield this.model.tune(data);
|
|
||||||
} catch (err) {
|
|
||||||
// AdapterErrors are handled by the error-message component
|
|
||||||
// in the form
|
|
||||||
if (err instanceof AdapterError === false) {
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
// because we're not calling model.save the model never updates with
|
|
||||||
// the error. Forcing the error message by manually setting the errorMessage
|
|
||||||
try {
|
try {
|
||||||
this.model.set('errorMessage', err.errors.firstObject);
|
yield this.model.tune(data);
|
||||||
} catch {
|
} catch (err) {
|
||||||
// do nothing
|
// AdapterErrors are handled by the error-message component
|
||||||
|
// in the form
|
||||||
|
if (err instanceof AdapterError === false) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
// because we're not calling model.save the model never updates with
|
||||||
|
// the error. Forcing the error message by manually setting the errorMessage
|
||||||
|
try {
|
||||||
|
this.model.set('errorMessage', err.errors.firstObject);
|
||||||
|
} catch {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
if (this.wizard.currentMachine === 'authentication' && this.wizard.featureState === 'config') {
|
||||||
}
|
this.wizard.transitionFeatureMachine(this.wizard.featureState, 'CONTINUE');
|
||||||
if (this.wizard.currentMachine === 'authentication' && this.wizard.featureState === 'config') {
|
}
|
||||||
this.wizard.transitionFeatureMachine(this.wizard.featureState, 'CONTINUE');
|
this.router.transitionTo('vault.cluster.access.methods').followRedirects();
|
||||||
}
|
this.flashMessages.success('The configuration was saved successfully.');
|
||||||
this.router.transitionTo('vault.cluster.access.methods').followRedirects();
|
})
|
||||||
this.flashMessages.success('The configuration was saved successfully.');
|
),
|
||||||
}).withTestWaiter(),
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -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,59 +144,65 @@ 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(
|
||||||
// will be using the Token Auth Method, so set it here
|
waitFor(function* (token) {
|
||||||
this.set('selectedAuth', 'token');
|
// will be using the Token Auth Method, so set it here
|
||||||
let adapter = this.store.adapterFor('tools');
|
this.set('selectedAuth', 'token');
|
||||||
try {
|
let adapter = this.store.adapterFor('tools');
|
||||||
let response = yield adapter.toolAction('unwrap', null, { clientToken: token });
|
try {
|
||||||
this.set('token', response.auth.client_token);
|
let response = yield adapter.toolAction('unwrap', null, { clientToken: token });
|
||||||
this.send('doSubmit');
|
this.set('token', response.auth.client_token);
|
||||||
} catch (e) {
|
this.send('doSubmit');
|
||||||
this.set('error', `Token unwrap failed: ${e.errors[0]}`);
|
} catch (e) {
|
||||||
}
|
this.set('error', `Token unwrap failed: ${e.errors[0]}`);
|
||||||
}).withTestWaiter(),
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
|
||||||
fetchMethods: task(function*() {
|
fetchMethods: task(
|
||||||
let store = this.store;
|
waitFor(function* () {
|
||||||
try {
|
let store = this.store;
|
||||||
let methods = yield store.findAll('auth-method', {
|
try {
|
||||||
adapterOptions: {
|
let methods = yield store.findAll('auth-method', {
|
||||||
unauthenticated: true,
|
adapterOptions: {
|
||||||
},
|
unauthenticated: true,
|
||||||
});
|
},
|
||||||
this.set(
|
});
|
||||||
'methods',
|
this.set(
|
||||||
methods.map(m => {
|
'methods',
|
||||||
const method = m.serialize({ includeId: true });
|
methods.map((m) => {
|
||||||
return {
|
const method = m.serialize({ includeId: true });
|
||||||
...method,
|
return {
|
||||||
mountDescription: method.description,
|
...method,
|
||||||
};
|
mountDescription: method.description,
|
||||||
})
|
};
|
||||||
);
|
})
|
||||||
next(() => {
|
);
|
||||||
store.unloadAll('auth-method');
|
next(() => {
|
||||||
});
|
store.unloadAll('auth-method');
|
||||||
} catch (e) {
|
});
|
||||||
this.set('error', `There was an error fetching Auth Methods: ${e.errors[0]}`);
|
} catch (e) {
|
||||||
}
|
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,40 +223,42 @@ export default Component.extend(DEFAULTS, {
|
||||||
this.set('error', `${message}${errors.join('.')}`);
|
this.set('error', `${message}${errors.join('.')}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
authenticate: task(function*(backendType, data) {
|
authenticate: task(
|
||||||
let clusterId = this.cluster.id;
|
waitFor(function* (backendType, data) {
|
||||||
try {
|
let clusterId = this.cluster.id;
|
||||||
if (backendType === 'okta') {
|
try {
|
||||||
this.delayAuthMessageReminder.perform();
|
if (backendType === 'okta') {
|
||||||
}
|
this.delayAuthMessageReminder.perform();
|
||||||
let authResponse = yield this.auth.authenticate({ clusterId, backend: backendType, data });
|
|
||||||
|
|
||||||
let { isRoot, namespace } = authResponse;
|
|
||||||
let transition;
|
|
||||||
let { redirectTo } = this;
|
|
||||||
if (redirectTo) {
|
|
||||||
// reset the value on the controller because it's bound here
|
|
||||||
this.set('redirectTo', '');
|
|
||||||
// here we don't need the namespace because it will be encoded in redirectTo
|
|
||||||
transition = this.router.transitionTo(redirectTo);
|
|
||||||
} else {
|
|
||||||
transition = this.router.transitionTo('vault.cluster', { queryParams: { namespace } });
|
|
||||||
}
|
|
||||||
// returning this w/then because if we keep it
|
|
||||||
// in the task, it will get cancelled when the component in un-rendered
|
|
||||||
yield transition.followRedirects().then(() => {
|
|
||||||
if (isRoot) {
|
|
||||||
this.flashMessages.warning(
|
|
||||||
'You have logged in with a root token. As a security precaution, this root token will not be stored by your browser and you will need to re-authenticate after the window is closed or refreshed.'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
let authResponse = yield this.auth.authenticate({ clusterId, backend: backendType, data });
|
||||||
} catch (e) {
|
|
||||||
this.handleError(e);
|
|
||||||
}
|
|
||||||
}).withTestWaiter(),
|
|
||||||
|
|
||||||
delayAuthMessageReminder: task(function*() {
|
let { isRoot, namespace } = authResponse;
|
||||||
|
let transition;
|
||||||
|
let { redirectTo } = this;
|
||||||
|
if (redirectTo) {
|
||||||
|
// reset the value on the controller because it's bound here
|
||||||
|
this.set('redirectTo', '');
|
||||||
|
// here we don't need the namespace because it will be encoded in redirectTo
|
||||||
|
transition = this.router.transitionTo(redirectTo);
|
||||||
|
} else {
|
||||||
|
transition = this.router.transitionTo('vault.cluster', { queryParams: { namespace } });
|
||||||
|
}
|
||||||
|
// returning this w/then because if we keep it
|
||||||
|
// in the task, it will get cancelled when the component in un-rendered
|
||||||
|
yield transition.followRedirects().then(() => {
|
||||||
|
if (isRoot) {
|
||||||
|
this.flashMessages.warning(
|
||||||
|
'You have logged in with a root token. As a security precaution, this root token will not be stored by your browser and you will need to re-authenticate after the window is closed or refreshed.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.handleError(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
|
||||||
|
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 || [];
|
||||||
|
|
||||||
|
|
|
@ -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,29 +53,30 @@ export default Component.extend({
|
||||||
return this.window || window;
|
return this.window || window;
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchRole: task(function*(roleName, options = { debounce: true }) {
|
fetchRole: task(
|
||||||
if (options.debounce) {
|
waitFor(function* (roleName, options = { debounce: true }) {
|
||||||
this.onRoleName(roleName);
|
if (options.debounce) {
|
||||||
// debounce
|
this.onRoleName(roleName);
|
||||||
yield timeout(WAIT_TIME);
|
// debounce
|
||||||
}
|
yield timeout(Ember.testing ? 0 : WAIT_TIME);
|
||||||
let path = this.selectedAuthPath || this.selectedAuthType;
|
|
||||||
let id = JSON.stringify([path, roleName]);
|
|
||||||
let role = null;
|
|
||||||
try {
|
|
||||||
role = yield this.store.findRecord('role-jwt', id, { adapterOptions: { namespace: this.namespace } });
|
|
||||||
} catch (e) {
|
|
||||||
if (!e.httpStatus || e.httpStatus !== 400) {
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
if (e.errors && e.errors.length > 0) {
|
let path = this.selectedAuthPath || this.selectedAuthType;
|
||||||
this.set('errorMessage', e.errors[0]);
|
let id = JSON.stringify([path, roleName]);
|
||||||
|
let role = null;
|
||||||
|
try {
|
||||||
|
role = yield this.store.findRecord('role-jwt', id, { adapterOptions: { namespace: this.namespace } });
|
||||||
|
} catch (e) {
|
||||||
|
// throwing here causes failures in tests
|
||||||
|
if ((!e.httpStatus || e.httpStatus !== 400) && !Ember.testing) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
if (e.errors && e.errors.length > 0) {
|
||||||
|
this.set('errorMessage', e.errors[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 === '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.');
|
||||||
|
|
|
@ -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(() => {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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.'
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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 {}
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,32 +27,34 @@ 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(
|
||||||
try {
|
waitFor(function* () {
|
||||||
yield this.model.save();
|
try {
|
||||||
} catch (err) {
|
yield this.model.save();
|
||||||
// AdapterErrors are handled by the error-message component
|
} catch (err) {
|
||||||
// in the form
|
// AdapterErrors are handled by the error-message component
|
||||||
if (err instanceof AdapterError === false) {
|
// in the form
|
||||||
throw err;
|
if (err instanceof AdapterError === false) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
this.router.transitionTo('vault.cluster.access.method.item.list').followRedirects();
|
||||||
}
|
this.flashMessages.success(`Successfully saved ${this.itemType} ${this.model.id}.`);
|
||||||
this.router.transitionTo('vault.cluster.access.method.item.list').followRedirects();
|
})
|
||||||
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];
|
||||||
|
|
|
@ -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(' ');
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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));
|
||||||
});
|
});
|
||||||
|
|
|
@ -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,23 +50,24 @@ export default Component.extend({
|
||||||
return `Successfully ${action} ${typeDisplay}.`;
|
return `Successfully ${action} ${typeDisplay}.`;
|
||||||
},
|
},
|
||||||
|
|
||||||
save: task(function*() {
|
save: task(
|
||||||
let model = this.model;
|
waitFor(function* () {
|
||||||
let message = this.getMessage(model);
|
let model = this.model;
|
||||||
|
let message = this.getMessage(model);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
yield model.save();
|
yield model.save();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// err will display via model state
|
// err will display via model state
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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) {
|
||||||
|
|
|
@ -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}`
|
||||||
);
|
);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -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');
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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'));
|
||||||
|
|
|
@ -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,60 +92,60 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mountBackend: task(function*() {
|
mountBackend: task(
|
||||||
const mountModel = this.mountModel;
|
waitFor(function* () {
|
||||||
const { type, path } = mountModel;
|
const mountModel = this.mountModel;
|
||||||
let capabilities = null;
|
const { type, path } = mountModel;
|
||||||
try {
|
let capabilities = null;
|
||||||
capabilities = yield this.store.findRecord('capabilities', `${path}/config`);
|
try {
|
||||||
} catch (err) {
|
capabilities = yield this.store.findRecord('capabilities', `${path}/config`);
|
||||||
if (Ember.testing) {
|
} catch (err) {
|
||||||
//captures mount-backend-form component test
|
if (Ember.testing) {
|
||||||
yield mountModel.save();
|
//captures mount-backend-form component test
|
||||||
let mountType = this.mountType;
|
yield mountModel.save();
|
||||||
mountType = mountType === 'secret' ? `${mountType}s engine` : `${mountType} method`;
|
let mountType = this.mountType;
|
||||||
this.flashMessages.success(`Successfully mounted the ${type} ${mountType} at ${path}.`);
|
mountType = mountType === 'secret' ? `${mountType}s engine` : `${mountType} method`;
|
||||||
yield this.onMountSuccess(type, path);
|
this.flashMessages.success(`Successfully mounted the ${type} ${mountType} at ${path}.`);
|
||||||
return;
|
yield this.onMountSuccess(type, path);
|
||||||
} else {
|
return;
|
||||||
throw err;
|
} else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!capabilities.get('canUpdate')) {
|
if (!capabilities.get('canUpdate')) {
|
||||||
// if there is no sys/mount issue then error is config endpoint.
|
// if there is no sys/mount issue then error is config endpoint.
|
||||||
this.flashMessages.warning(
|
this.flashMessages.warning(
|
||||||
'You do not have access to the config endpoint. The secret engine was mounted, but the configuration settings were not saved.'
|
'You do not have access to the config endpoint. The secret engine was mounted, but the configuration settings were not saved.'
|
||||||
);
|
|
||||||
// remove the config data from the model otherwise it will save it even if the network request failed.
|
|
||||||
[this.mountModel.maxVersions, this.mountModel.casRequired, this.mountModel.deleteVersionAfter] = [
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
yield mountModel.save();
|
|
||||||
} catch (err) {
|
|
||||||
if (err.message === 'mountIssue') {
|
|
||||||
this.mountIssue = true;
|
|
||||||
this.set('isFormInvalid', this.mountIssue);
|
|
||||||
this.flashMessages.danger(
|
|
||||||
'You do not have access to the sys/mounts endpoint. The secret engine was not mounted.'
|
|
||||||
);
|
);
|
||||||
|
// remove the config data from the model otherwise it will save it even if the network request failed.
|
||||||
|
[this.mountModel.maxVersions, this.mountModel.casRequired, this.mountModel.deleteVersionAfter] = [
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
yield mountModel.save();
|
||||||
|
} catch (err) {
|
||||||
|
if (err.message === 'mountIssue') {
|
||||||
|
this.mountIssue = true;
|
||||||
|
this.set('isFormInvalid', this.mountIssue);
|
||||||
|
this.flashMessages.danger(
|
||||||
|
'You do not have access to the sys/mounts endpoint. The secret engine was not mounted.'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.set('errorMessage', 'This mount path already exist.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.set('errorMessage', 'This mount path already exist.');
|
let mountType = this.mountType;
|
||||||
|
mountType = mountType === 'secret' ? `${mountType}s engine` : `${mountType} method`;
|
||||||
|
this.flashMessages.success(`Successfully mounted the ${type} ${mountType} at ${path}.`);
|
||||||
|
yield this.onMountSuccess(type, path);
|
||||||
return;
|
return;
|
||||||
}
|
})
|
||||||
let mountType = this.mountType;
|
).drop(),
|
||||||
mountType = mountType === 'secret' ? `${mountType}s engine` : `${mountType} method`;
|
|
||||||
this.flashMessages.success(`Successfully mounted the ${type} ${mountType} at ${path}.`);
|
|
||||||
yield this.onMountSuccess(type, path);
|
|
||||||
return;
|
|
||||||
})
|
|
||||||
.drop()
|
|
||||||
.withTestWaiter(),
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
onKeyUp(name, value) {
|
onKeyUp(name, value) {
|
||||||
|
|
|
@ -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;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -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('/');
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,17 +43,19 @@ export default Component.extend({
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
},
|
},
|
||||||
|
|
||||||
setPGPKey: task(function*(dataURL, filename) {
|
setPGPKey: task(
|
||||||
const b64File = dataURL.split(',')[1].trim();
|
waitFor(function* (dataURL, filename) {
|
||||||
const decoded = atob(b64File).trim();
|
const b64File = dataURL.split(',')[1].trim();
|
||||||
|
const decoded = atob(b64File).trim();
|
||||||
|
|
||||||
// If a b64-encoded file was uploaded, then after decoding, it
|
// If a b64-encoded file was uploaded, then after decoding, it
|
||||||
// will still be b64.
|
// will still be b64.
|
||||||
// If after decoding it's not b64, we want
|
// If after decoding it's not b64, we want
|
||||||
// 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) {
|
||||||
|
|
|
@ -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));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -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';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>
|
||||||
|
@ -22,7 +30,7 @@
|
||||||
@size="small"
|
@size="small"
|
||||||
@checked={{this.showTestValue}}
|
@checked={{this.showTestValue}}
|
||||||
@onChange={{this.toggleTestValue}}
|
@onChange={{this.toggleTestValue}}
|
||||||
>
|
>
|
||||||
<span class="has-text-grey">Validation</span>
|
<span class="has-text-grey">Validation</span>
|
||||||
</Toggle>
|
</Toggle>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,37 +40,37 @@
|
||||||
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
|
||||||
data-test-input={{concat @attr.name "-testval"}}
|
data-test-input={{concat @attr.name "-testval"}}
|
||||||
id={{concat @attr.name "-testval"}}
|
id={{concat @attr.name "-testval"}}
|
||||||
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>
|
||||||
{{#if this.regexError}}
|
{{#if this.regexError}}
|
||||||
<AlertInline @type="danger" @message="Your regex doesn't match the subject string" />
|
<AlertInline @type="danger" @message="Your regex doesn't match the subject string" />
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="message-inline">
|
<div class="message-inline">
|
||||||
<Icon @name="check-circle-fill" class="has-text-success" />
|
<Icon @name="check-circle-fill" class="has-text-success" />
|
||||||
<p data-test-inline-success-message>Your regex matches the subject string</p>
|
<p data-test-inline-success-message>Your regex matches the subject string</p>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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!');
|
||||||
})
|
})
|
||||||
|
|
|
@ -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,38 +117,43 @@ 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(
|
||||||
if (!this.model) return;
|
'model.failedServerRead',
|
||||||
// if the version couldn't be read from the server
|
'modelForData.failedServerRead',
|
||||||
if (this.isV2 && this.modelForData.failedServerRead) {
|
'isV2',
|
||||||
return true;
|
function () {
|
||||||
|
if (!this.model) return;
|
||||||
|
// if the version couldn't be read from the server
|
||||||
|
if (this.isV2 && this.modelForData.failedServerRead) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// if the model couldn't be read from the server
|
||||||
|
if (!this.isV2 && this.model.failedServerRead) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// if the model couldn't be read from the server
|
),
|
||||||
if (!this.isV2 && this.model.failedServerRead) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}),
|
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
refresh() {
|
refresh() {
|
||||||
|
|
|
@ -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);
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue