From fbce5986c17fc917ab1206c3280b416166609995 Mon Sep 17 00:00:00 2001 From: claire bontempo <68122737+hellobontempo@users.noreply.github.com> Date: Fri, 18 Mar 2022 16:47:42 -0700 Subject: [PATCH] UI/Wrong sentinel error message for auth methods (#14551) * priortize adapter error over model error * glimmerize message-error component * message error tweaks * fix glimmerize * fix some tests * change error handling for mount backend form * throw API error for secret engine not mounting * fix tests" * fix tests * cleanup error handling for secret engine mounts * fix test selector * add changelog * STOP BEING FLAKY --- changelog/14551.txt | 3 + ui/app/adapters/secret-engine.js | 11 +-- ui/app/components/config-pki-ca.js | 5 +- ui/app/components/config-pki.js | 6 +- ui/app/components/mount-backend-form.js | 49 ++++++++---- ui/app/mixins/policy-edit-controller.js | 5 +- ui/app/models/policy.js | 2 +- ui/app/templates/components/config-pki-ca.hbs | 2 +- ui/app/templates/components/config-pki.hbs | 2 +- .../components/mount-backend-form.hbs | 2 +- .../vault/cluster/policies/create.hbs | 2 +- ui/lib/core/addon/components/message-error.js | 75 ++++++++----------- .../templates/components/message-error.hbs | 4 +- ui/tests/acceptance/client-current-test.js | 13 +--- .../pki/section-urls-test.js | 5 +- .../settings/mount-secret-backend-test.js | 2 +- .../integration/components/auth-form-test.js | 2 +- .../integration/components/ttl-picker-test.js | 5 +- ui/tests/pages/components/auth-form.js | 3 +- 19 files changed, 97 insertions(+), 101 deletions(-) create mode 100644 changelog/14551.txt diff --git a/changelog/14551.txt b/changelog/14551.txt new file mode 100644 index 000000000..47ef9add2 --- /dev/null +++ b/changelog/14551.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: Fix issue where UI incorrectly handled API errors when mounting backends +``` \ No newline at end of file diff --git a/ui/app/adapters/secret-engine.js b/ui/app/adapters/secret-engine.js index 1d75aae42..40edfc300 100644 --- a/ui/app/adapters/secret-engine.js +++ b/ui/app/adapters/secret-engine.js @@ -61,15 +61,8 @@ export default ApplicationAdapter.extend({ data.id = path; } // first create the engine - try { - await this.ajax(this.url(path), 'POST', { data }); - } catch (e) { - // if error determine if path duplicate or permissions - if (e.httpStatus === 400) { - throw new Error('samePath'); - } - throw new Error('mountIssue'); - } + await this.ajax(this.url(path), 'POST', { data }); + // second post to config try { await this.ajax(this.urlForConfig(path), 'POST', { data: configData }); diff --git a/ui/app/components/config-pki-ca.js b/ui/app/components/config-pki-ca.js index c5814bd70..f90bbddbe 100644 --- a/ui/app/components/config-pki-ca.js +++ b/ui/app/components/config-pki-ca.js @@ -7,6 +7,7 @@ export default Component.extend({ classNames: 'config-pki-ca', store: service('store'), flashMessages: service(), + errors: null, /* * @param boolean @@ -150,8 +151,8 @@ export default Component.extend({ ); } }) - .catch(() => { - // handle promise rejection - error will be shown by message-error component + .catch((e) => { + this.set('errors', e.errors); }) .finally(() => { this.set('loading', false); diff --git a/ui/app/components/config-pki.js b/ui/app/components/config-pki.js index 1a45d6fa4..50b5a9119 100644 --- a/ui/app/components/config-pki.js +++ b/ui/app/components/config-pki.js @@ -5,7 +5,7 @@ import { get } from '@ember/object'; export default Component.extend({ classNames: 'config-pki', flashMessages: service(), - + errors: null, /* * * @param String @@ -55,8 +55,8 @@ export default Component.extend({ } this.send('refresh'); }) - .catch(() => { - // handle promise rejection - error will be shown by message-error component + .catch((e) => { + this.set('errors', e.errors); }) .finally(() => { this.set('loading', false); diff --git a/ui/app/components/mount-backend-form.js b/ui/app/components/mount-backend-form.js index 2433af9bc..0493003d9 100644 --- a/ui/app/components/mount-backend-form.js +++ b/ui/app/components/mount-backend-form.js @@ -113,8 +113,39 @@ export default Component.extend({ } } - if (!capabilities.get('canUpdate')) { - // if there is no sys/mount issue then error is config endpoint. + let changedAttrKeys = Object.keys(mountModel.changedAttributes()); + const updatesConfig = + mountModel.isV2KV && + (changedAttrKeys.includes('casRequired') || + changedAttrKeys.includes('deleteVersionAfter') || + changedAttrKeys.includes('maxVersions')); + + try { + yield mountModel.save(); + } catch (err) { + if (err.httpStatus === 403) { + 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; + } + if (err.errors) { + let errors = err.errors.map((e) => { + if (typeof e === 'object') return e.title || e.message || JSON.stringify(e); + return e; + }); + this.set('errors', errors); + } else if (err.message) { + this.set('errorMessage', err.message); + } else { + this.set('errorMessage', 'An error occurred, check the vault logs.'); + } + return; + } + if (updatesConfig && !capabilities.get('canUpdate')) { + // config error is not thrown from secret-engine adapter, so handling here this.flashMessages.warning( 'You do not have access to the config endpoint. The secret engine was mounted, but the configuration settings were not saved.' ); @@ -125,20 +156,6 @@ export default Component.extend({ 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; - } let mountType = this.mountType; mountType = mountType === 'secret' ? `${mountType}s engine` : `${mountType} method`; this.flashMessages.success(`Successfully mounted the ${type} ${mountType} at ${path}.`); diff --git a/ui/app/mixins/policy-edit-controller.js b/ui/app/mixins/policy-edit-controller.js index 85fefea65..4361bfe43 100644 --- a/ui/app/mixins/policy-edit-controller.js +++ b/ui/app/mixins/policy-edit-controller.js @@ -36,9 +36,8 @@ export default Mixin.create({ } return this.transitionToRoute('vault.cluster.policy.show', m.get('policyType'), m.get('name')); }) - .catch(() => { - // do nothing here... - // message-error component will show errors + .catch((e) => { + model.set('errors', e.errors); }); }, diff --git a/ui/app/models/policy.js b/ui/app/models/policy.js index 1cb15a30f..af8c3d8a4 100644 --- a/ui/app/models/policy.js +++ b/ui/app/models/policy.js @@ -4,12 +4,12 @@ import { computed } from '@ember/object'; import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; export default Model.extend({ + errors: attr('array'), name: attr('string'), policy: attr('string'), policyType: computed('constructor.modelName', function () { return this.constructor.modelName.split('/')[1]; }), - updatePath: lazyCapabilities(apiPath`sys/policies/${'policyType'}/${'id'}`, 'id', 'policyType'), canDelete: alias('updatePath.canDelete'), canEdit: alias('updatePath.canUpdate'), diff --git a/ui/app/templates/components/config-pki-ca.hbs b/ui/app/templates/components/config-pki-ca.hbs index b56a06023..3bf28bfb2 100644 --- a/ui/app/templates/components/config-pki-ca.hbs +++ b/ui/app/templates/components/config-pki-ca.hbs @@ -150,7 +150,7 @@ {{else}}