Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI/cp validations kv duplicate path #11878

Merged
merged 11 commits into from
Jun 22, 2021
3 changes: 3 additions & 0 deletions changelog/11878.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
ui: add validations for duplicate path kv engine
```
22 changes: 19 additions & 3 deletions ui/app/components/secret-edit.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -61,6 +62,8 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
validationMessages: null,
validationErrorCount: 0,

secretPaths: null,

init() {
this._super(...arguments);
let secrets = this.model.secretData;
Expand All @@ -79,16 +82,25 @@ 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
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);
});
}
},

waitForKeyUp: task(function*(name, value) {
Expand Down Expand Up @@ -187,7 +199,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') {
Expand Down
2 changes: 1 addition & 1 deletion ui/app/models/secret-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
}),
});

Expand Down
4 changes: 2 additions & 2 deletions ui/app/models/secret-v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
}),
],
});
Expand Down
20 changes: 16 additions & 4 deletions ui/tests/acceptance/secrets/backend/kv/secret-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,27 @@ 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
.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);
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) {
Expand Down