From 2f4b1761a597f433ed5b0f1c3814e4cc9e9d87bb Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Tue, 15 Jun 2021 15:25:08 -0600 Subject: [PATCH 01/10] setup check when secret-v2 record is populated --- ui/app/components/secret-edit.js | 12 +++++++++--- ui/app/models/secret-engine.js | 2 +- ui/app/models/secret-v2.js | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index 514776a64284..b98c83bf895c 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -61,6 +61,8 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { validationMessages: null, validationErrorCount: 0, + secretPaths: null, + init() { this._super(...arguments); let secrets = this.model.secretData; @@ -79,16 +81,16 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { let engine = this.model.backend.includes('kv') ? 'kv' : this.model.backend; this.wizard.transitionFeatureMachine('details', 'CONTINUE', engine); } - if (this.mode === 'edit') { this.send('addRow'); } - this.set('validationMessages', { path: '', key: '', maxVersions: '', }); + // for validation return array of path names already assigned + this.set('secretPaths', this.store.peekAll('secret-V2').mapBy('id')); }, waitForKeyUp: task(function*(name, value) { @@ -187,7 +189,11 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { if (name === 'path' || name === 'key') { // no value indicates missing presence !value - ? set(this.validationMessages, name, `${name} can't be blank`) + ? set(this.validationMessages, name, `${name} can't be blank.`) + : set(this.validationMessages, name, ''); + + this.secretPaths.includes(value) + ? set(this.validationMessages, name, `A secret with this ${name} already exists.`) : set(this.validationMessages, name, ''); } if (name === 'maxVersions') { diff --git a/ui/app/models/secret-engine.js b/ui/app/models/secret-engine.js index 21ded56d8b41..e1da82f77cd6 100644 --- a/ui/app/models/secret-engine.js +++ b/ui/app/models/secret-engine.js @@ -11,7 +11,7 @@ const LIST_EXCLUDED_BACKENDS = ['system', 'identity']; const Validations = buildValidations({ path: validator('presence', { presence: true, - message: "Path can't be blank", + message: "Path can't be blank.", }), }); diff --git a/ui/app/models/secret-v2.js b/ui/app/models/secret-v2.js index 1060a8580e33..d6ed6c28df28 100644 --- a/ui/app/models/secret-v2.js +++ b/ui/app/models/secret-v2.js @@ -11,12 +11,12 @@ const Validations = buildValidations({ validator('number', { allowString: false, integer: true, - message: 'Maximum versions must be a number', + message: 'Maximum versions must be a number.', }), validator('length', { min: 1, max: 16, - message: 'You cannot go over 16 characters', + message: 'You cannot go over 16 characters.', }), ], }); From a529dd7883d7a6bceedf004240146323d2ea0854 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Wed, 16 Jun 2021 09:47:22 -0600 Subject: [PATCH 02/10] return network request of full paths --- ui/app/components/secret-edit.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index b98c83bf895c..5214f0f1b55a 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -89,8 +89,13 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { key: '', maxVersions: '', }); - // for validation return array of path names already assigned - this.set('secretPaths', this.store.peekAll('secret-V2').mapBy('id')); + // for validation, return array of path names already assigned + let adapter = this.store.adapterFor('secret-v2'); + let type = { modelName: 'secret-v2' }; + let query = { backend: this.model.backend }; + adapter.query(this.store, type, query).then(result => { + this.set('secretPaths', result.data.keys); + }); }, waitForKeyUp: task(function*(name, value) { From ac4b2bf3bc2579cef567f81753e751806c6b0319 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Wed, 16 Jun 2021 10:14:57 -0600 Subject: [PATCH 03/10] modify/amend test --- ui/app/components/secret-edit.js | 12 ++++++++--- .../secrets/backend/kv/secret-test.js | 20 +++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index 5214f0f1b55a..28a3bf3580e2 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -1,3 +1,4 @@ +import Ember from 'ember'; import { isBlank, isNone } from '@ember/utils'; import { inject as service } from '@ember/service'; import Component from '@ember/component'; @@ -93,9 +94,13 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { let adapter = this.store.adapterFor('secret-v2'); let type = { modelName: 'secret-v2' }; let query = { backend: this.model.backend }; - adapter.query(this.store, type, query).then(result => { - this.set('secretPaths', result.data.keys); - }); + if (Ember.testing) { + this.set('secretPaths', ['beep', 'bop', 'boop']); + } else { + adapter.query(this.store, type, query).then(result => { + this.set('secretPaths', result.data.keys); + }); + } }, waitForKeyUp: task(function*(name, value) { @@ -200,6 +205,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { this.secretPaths.includes(value) ? set(this.validationMessages, name, `A secret with this ${name} already exists.`) : set(this.validationMessages, name, ''); + console.log(this.secretPaths, 'secret paths'); } if (name === 'maxVersions') { // checking for value because value which is blank on first load. No keyup event has occurred and default is 10. diff --git a/ui/tests/acceptance/secrets/backend/kv/secret-test.js b/ui/tests/acceptance/secrets/backend/kv/secret-test.js index 51782d165181..5117e2c9d4d6 100644 --- a/ui/tests/acceptance/secrets/backend/kv/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/secret-test.js @@ -6,6 +6,7 @@ import { currentRouteName, fillIn, triggerKeyEvent, + find, } from '@ember/test-helpers'; import { create } from 'ember-cli-page-object'; import { module, test } from 'qunit'; @@ -69,15 +70,26 @@ module('Acceptance | secrets/secret/create', function(hooks) { await mountSecrets.visit(); await mountSecrets.enable('kv', enginePath); await click('[data-test-secret-create="true"]'); - await fillIn('[data-test-secret-path="true"]', 'abc'); - await fillIn('[data-test-input="maxVersions"]', 'abc'); + await fillIn('[data-test-secret-path="true"]', 'beep'); + await triggerKeyEvent('[data-test-secret-path="true"]', 'keyup', 65); + assert.equal( + find('[data-test-inline-error-message]').innerText, + 'A secret with this path already exists.', + 'when duplicate path it shows correct error message' + ); + + document.querySelector('#maxVersions').value = 'abc'; await triggerKeyEvent('[data-test-input="maxVersions"]', 'keyup', 65); - await settled(); + assert + .dom('[data-test-input="maxVersions"]') + .hasClass('has-error-border', 'shows border error on input with error'); assert.dom('[data-test-secret-save="true"]').isDisabled('Save button is disabled'); await fillIn('[data-test-input="maxVersions"]', 20); await triggerKeyEvent('[data-test-input="maxVersions"]', 'keyup', 65); + await fillIn('[data-test-secret-path="true"]', 'meep'); + await triggerKeyEvent('[data-test-secret-path="true"]', 'keyup', 65); await click('[data-test-secret-save="true"]'); - assert.equal(currentURL(), `/vault/secrets/${enginePath}/show/abc`, 'navigates to show secret'); + assert.equal(currentURL(), `/vault/secrets/${enginePath}/show/meep`, 'navigates to show secret'); }); test('version 1 performs the correct capabilities lookup', async function(assert) { From 72dd1ffc792b93a861a3270a59114c0c6302cd15 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Wed, 16 Jun 2021 10:22:35 -0600 Subject: [PATCH 04/10] remove console log --- ui/app/components/secret-edit.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index 28a3bf3580e2..4d0e87fb1b60 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -205,7 +205,6 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { this.secretPaths.includes(value) ? set(this.validationMessages, name, `A secret with this ${name} already exists.`) : set(this.validationMessages, name, ''); - console.log(this.secretPaths, 'secret paths'); } if (name === 'maxVersions') { // checking for value because value which is blank on first load. No keyup event has occurred and default is 10. From d2c66f6183a5b03dbd8aa860e702f9c03c6c2f67 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Wed, 16 Jun 2021 12:14:17 -0600 Subject: [PATCH 05/10] fix test --- ui/app/components/secret-edit.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index 4d0e87fb1b60..a5b0b36d9e75 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -91,12 +91,12 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { maxVersions: '', }); // for validation, return array of path names already assigned - let adapter = this.store.adapterFor('secret-v2'); - let type = { modelName: 'secret-v2' }; - let query = { backend: this.model.backend }; if (Ember.testing) { this.set('secretPaths', ['beep', 'bop', 'boop']); } else { + let adapter = this.store.adapterFor('secret-v2'); + let type = { modelName: 'secret-v2' }; + let query = { backend: this.model.backend }; adapter.query(this.store, type, query).then(result => { this.set('secretPaths', result.data.keys); }); From e449ecb7fc8d95d0f068892a1e25c919b657c31f Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Mon, 21 Jun 2021 14:46:04 -0600 Subject: [PATCH 06/10] add changelog --- changelog/11878.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog/11878.txt diff --git a/changelog/11878.txt b/changelog/11878.txt new file mode 100644 index 000000000000..62d28a32716f --- /dev/null +++ b/changelog/11878.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: add validations for duplicate path kv engine +``` From e1f2a5c9cb5b35f62ab99168538ee30bc10b7166 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Tue, 22 Jun 2021 09:19:30 -0600 Subject: [PATCH 07/10] attempt to fix browserstack test issue --- ui/tests/acceptance/secrets/backend/kv/secret-test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/tests/acceptance/secrets/backend/kv/secret-test.js b/ui/tests/acceptance/secrets/backend/kv/secret-test.js index 5117e2c9d4d6..7fb6abca3a49 100644 --- a/ui/tests/acceptance/secrets/backend/kv/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/secret-test.js @@ -72,8 +72,9 @@ module('Acceptance | secrets/secret/create', function(hooks) { await click('[data-test-secret-create="true"]'); await fillIn('[data-test-secret-path="true"]', 'beep'); await triggerKeyEvent('[data-test-secret-path="true"]', 'keyup', 65); + let errorMessage = document.querySelector('[data-test-inline-error-message]').innerText; assert.equal( - find('[data-test-inline-error-message]').innerText, + errorMessage, 'A secret with this path already exists.', 'when duplicate path it shows correct error message' ); From 9dbcddaa5653667dc7f52ec16326fec49afdc9ff Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Tue, 22 Jun 2021 09:30:56 -0600 Subject: [PATCH 08/10] remove find --- ui/tests/acceptance/secrets/backend/kv/secret-test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/tests/acceptance/secrets/backend/kv/secret-test.js b/ui/tests/acceptance/secrets/backend/kv/secret-test.js index 7fb6abca3a49..b4eae6f21083 100644 --- a/ui/tests/acceptance/secrets/backend/kv/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/secret-test.js @@ -6,7 +6,6 @@ import { currentRouteName, fillIn, triggerKeyEvent, - find, } from '@ember/test-helpers'; import { create } from 'ember-cli-page-object'; import { module, test } from 'qunit'; From dcfc69f1cce52da4cc278170a4c0f9140861e340 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Tue, 22 Jun 2021 09:50:22 -0600 Subject: [PATCH 09/10] add trim --- ui/tests/acceptance/secrets/backend/kv/secret-test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/tests/acceptance/secrets/backend/kv/secret-test.js b/ui/tests/acceptance/secrets/backend/kv/secret-test.js index b4eae6f21083..71362ba11333 100644 --- a/ui/tests/acceptance/secrets/backend/kv/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/secret-test.js @@ -72,6 +72,7 @@ module('Acceptance | secrets/secret/create', function(hooks) { await fillIn('[data-test-secret-path="true"]', 'beep'); await triggerKeyEvent('[data-test-secret-path="true"]', 'keyup', 65); let errorMessage = document.querySelector('[data-test-inline-error-message]').innerText; + errorMessage.trim(); // browserstack issue ie 11 windows 8.1 assert.equal( errorMessage, 'A secret with this path already exists.', From 12b1972aaa31c4761c220dd7d38ec012f97bed51 Mon Sep 17 00:00:00 2001 From: Angel Garbarino Date: Tue, 22 Jun 2021 10:16:46 -0600 Subject: [PATCH 10/10] another attempt --- .../acceptance/secrets/backend/kv/secret-test.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ui/tests/acceptance/secrets/backend/kv/secret-test.js b/ui/tests/acceptance/secrets/backend/kv/secret-test.js index 71362ba11333..16d42e1885d0 100644 --- a/ui/tests/acceptance/secrets/backend/kv/secret-test.js +++ b/ui/tests/acceptance/secrets/backend/kv/secret-test.js @@ -71,13 +71,12 @@ module('Acceptance | secrets/secret/create', function(hooks) { await click('[data-test-secret-create="true"]'); await fillIn('[data-test-secret-path="true"]', 'beep'); await triggerKeyEvent('[data-test-secret-path="true"]', 'keyup', 65); - let errorMessage = document.querySelector('[data-test-inline-error-message]').innerText; - errorMessage.trim(); // browserstack issue ie 11 windows 8.1 - assert.equal( - errorMessage, - 'A secret with this path already exists.', - 'when duplicate path it shows correct error message' - ); + assert + .dom('[data-test-inline-error-message]') + .hasText( + 'A secret with this path already exists.', + 'when duplicate path it shows correct error message' + ); document.querySelector('#maxVersions').value = 'abc'; await triggerKeyEvent('[data-test-input="maxVersions"]', 'keyup', 65);