KV Key Whitespace Warning (#23702) (#23773)

* adds warning for kv key that contains whitespace

* adds changelog entry
This commit is contained in:
Jordan Reimer
2023-10-20 12:01:33 -06:00
committed by GitHub
parent 33edf89a86
commit 64f9d236be
4 changed files with 47 additions and 6 deletions

3
changelog/23702.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
ui: Adds a warning when whitespace is detected in a key of a KV secret
```

View File

@@ -25,6 +25,7 @@
@value={{row.name}}
placeholder={{this.placeholders.key}}
{{on "change" (fn this.updateRow row index)}}
{{on "input" (fn this.validateKey index)}}
class="input"
/>
</div>
@@ -70,6 +71,15 @@
{{/if}}
</div>
</div>
{{#if (includes index this.whitespaceWarningRows)}}
<div class="has-bottom-margin-s">
<AlertInline
@type="warning"
@message="Key contains whitespace. If this is desired, you'll need to encode it with %20 in API requests."
data-test-kv-whitespace-warning={{index}}
/>
</div>
{{/if}}
{{/each}}
{{#if this.hasDuplicateKeys}}
<Hds::Alert data-test-duplicate-keys-warning @type="inline" @color="warning" as |A|>

View File

@@ -9,6 +9,7 @@ import { isNone } from '@ember/utils';
import { assert } from '@ember/debug';
import { action } from '@ember/object';
import { guidFor } from '@ember/object/internals';
import { A } from '@ember/array';
import KVObject from 'vault/lib/kv-object';
/**
@@ -38,6 +39,7 @@ import KVObject from 'vault/lib/kv-object';
export default class KvObjectEditor extends Component {
@tracked kvData;
whitespaceWarningRows = A();
get placeholders() {
return {
@@ -73,6 +75,7 @@ export default class KvObjectEditor extends Component {
const oldObj = this.kvData.objectAt(index);
assert('object guids match', guidFor(oldObj) === guidFor(object));
this.kvData.removeAt(index);
this.whitespaceWarningRows.removeObject(index);
this.args.onChange(this.kvData.toJSON());
}
@action
@@ -81,4 +84,16 @@ export default class KvObjectEditor extends Component {
this.args.onKeyUp(event.target.value);
}
}
@action
validateKey(rowIndex, event) {
const { value } = event.target;
const keyHasWhitespace = new RegExp('\\s', 'g').test(value);
const rows = [...this.whitespaceWarningRows];
const rowHasWarning = rows.includes(rowIndex);
if (!keyHasWhitespace && rowHasWarning) {
this.whitespaceWarningRows.removeObject(rowIndex);
} else if (keyHasWhitespace && !rowHasWarning) {
this.whitespaceWarningRows.addObject(rowIndex);
}
}
}

View File

@@ -5,7 +5,7 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { render, fillIn, click } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { create } from 'ember-cli-page-object';
@@ -22,14 +22,14 @@ module('Integration | Component | kv-object-editor', function (hooks) {
});
test('it renders with no initial value', async function (assert) {
await render(hbs`{{kv-object-editor onChange=this.spy}}`);
await render(hbs`<KvObjectEditor @onChange={{this.spy}} />`);
assert.strictEqual(component.rows.length, 1, 'renders a single row');
await component.addRow();
assert.strictEqual(component.rows.length, 1, 'will only render row with a blank key');
});
test('it calls onChange when the val changes', async function (assert) {
await render(hbs`{{kv-object-editor onChange=this.spy}}`);
await render(hbs`<KvObjectEditor @onChange={{this.spy}} />`);
await component.rows.objectAt(0).kvKey('foo').kvVal('bar');
assert.strictEqual(this.spy.callCount, 2, 'calls onChange each time change is triggered');
assert.deepEqual(
@@ -50,7 +50,7 @@ module('Integration | Component | kv-object-editor', function (hooks) {
test('it renders passed data', async function (assert) {
const metadata = { foo: 'bar', baz: 'bop' };
this.set('value', metadata);
await render(hbs`{{kv-object-editor value=this.value}}`);
await render(hbs`<KvObjectEditor @value={{this.value}} />`);
assert.strictEqual(
component.rows.length,
Object.keys(metadata).length + 1,
@@ -59,7 +59,7 @@ module('Integration | Component | kv-object-editor', function (hooks) {
});
test('it deletes a row', async function (assert) {
await render(hbs`{{kv-object-editor onChange=this.spy}}`);
await render(hbs`<KvObjectEditor @onChange={{this.spy}} />`);
await component.rows.objectAt(0).kvKey('foo').kvVal('bar');
await component.addRow();
assert.strictEqual(component.rows.length, 2);
@@ -74,7 +74,7 @@ module('Integration | Component | kv-object-editor', function (hooks) {
test('it shows a warning if there are duplicate keys', async function (assert) {
const metadata = { foo: 'bar', baz: 'bop' };
this.set('value', metadata);
await render(hbs`{{kv-object-editor value=this.value onChange=this.spy}}`);
await render(hbs`<KvObjectEditor @value={{this.value}} @onChange={{this.spy}} />`);
await component.rows.objectAt(0).kvKey('foo');
assert.ok(component.showsDuplicateError, 'duplicate keys are allowed but an error message is shown');
@@ -97,4 +97,17 @@ module('Integration | Component | kv-object-editor', function (hooks) {
assert.dom('textarea').doesNotExist('Value input hidden when block is provided');
assert.dom('[data-test-yield]').exists('Component yields block');
});
test('it should display whitespace warning for keys', async function (assert) {
await render(hbs`<KvObjectEditor @onChange={{this.spy}} />`);
await fillIn('[data-test-kv-key="0"]', 'test ');
assert.dom('[data-test-kv-whitespace-warning="0"]').exists();
await fillIn('[data-test-kv-key="0"]', 'test');
assert.dom('[data-test-kv-whitespace-warning="0"]').doesNotExist();
await fillIn('[data-test-kv-key="0"]', 'test ');
await click('[data-test-kv-add-row="0"]');
assert.dom('[data-test-kv-whitespace-warning="0"]').exists();
await click('[data-test-kv-delete-row="0"]');
assert.dom('[data-test-kv-whitespace-warning="0"]').doesNotExist();
});
});