UI: Fix KV v2 json editor (#24224)

* Fix JSON editor in KVv2 unable to paste. Fixes #23940

* Default to JSON view on edit with secret is complex

* Add changelog
This commit is contained in:
Chelsea Shaw
2023-11-21 15:11:14 -06:00
committed by GitHub
parent 18e6385e05
commit 82ca52d447
7 changed files with 40 additions and 8 deletions

3
changelog/24224.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:bug
ui: Fix JSON editor in KV V2 unable to handle pasted values
```

View File

@@ -15,7 +15,7 @@
{{#if @showJson}}
<JsonEditor
@title="{{if @isEdit 'Version' 'Secret'}} data"
@value={{or (stringify @secret.secretData) this.emptyJson}}
@value={{this.codeMirrorString}}
@valueUpdated={{this.handleJson}}
/>
{{#if (or @modelValidations.secretData.errors this.lintingErrors)}}

View File

@@ -6,7 +6,7 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import KVObject from 'vault/lib/kv-object';
import { stringify } from 'core/helpers/stringify';
/**
* @module KvDataFields is used for rendering the fields associated with kv secret data, it hides/shows a json editor and renders validation errors for the json editor
@@ -28,10 +28,13 @@ import KVObject from 'vault/lib/kv-object';
export default class KvDataFields extends Component {
@tracked lintingErrors;
@tracked codeMirrorString;
get emptyJson() {
// if secretData is null, this specially formats a blank object and renders a nice initial state for the json editor
return KVObject.create({ content: [{ name: '', value: '' }] }).toJSONString(true);
constructor() {
super(...arguments);
this.codeMirrorString = this.args.secret?.secretData
? stringify([this.args.secret.secretData], {})
: '{ "": "" }';
}
@action
@@ -41,5 +44,6 @@ export default class KvDataFields extends Component {
if (!this.lintingErrors) {
this.args.secret.secretData = JSON.parse(value);
}
this.codeMirrorString = value;
}
}

View File

@@ -5,7 +5,12 @@
<KvPageHeader @breadcrumbs={{@breadcrumbs}} @pageTitle="Create New Version">
<:toolbarFilters>
<Toggle @name="json" @checked={{this.showJsonView}} @onChange={{fn (mut this.showJsonView)}}>
<Toggle
@name="json"
@checked={{or this.showJsonView this.secretDataIsAdvanced}}
@onChange={{fn (mut this.showJsonView)}}
@disabled={{this.secretDataIsAdvanced}}
>
<span class="has-text-grey">JSON</span>
</Toggle>
</:toolbarFilters>
@@ -38,7 +43,7 @@
<MessageError @model={{@secret}} @errorMessage={{this.errorMessage}} />
<KvDataFields
@showJson={{this.showJsonView}}
@showJson={{or this.showJsonView this.secretDataIsAdvanced}}
@secret={{@secret}}
@modelValidations={{this.modelValidations}}
@isEdit={{true}}

View File

@@ -38,10 +38,15 @@ export default class KvSecretEdit extends Component {
@tracked modelValidations;
@tracked invalidFormAlert;
originalSecret;
secretDataIsAdvanced;
constructor() {
super(...arguments);
this.originalSecret = JSON.stringify(this.args.secret.secretData || {});
if (this.originalSecret.lastIndexOf('{') > 0) {
// Dumb way to check if there's a nested object in the secret
this.secretDataIsAdvanced = true;
}
}
get showOldVersionAlert() {

View File

@@ -24,6 +24,7 @@ import {
} from 'vault/tests/helpers/policy-generator/kv';
import { clearRecords, writeSecret, writeVersionedSecret } from 'vault/tests/helpers/kv/kv-run-commands';
import { FORM, PAGE } from 'vault/tests/helpers/kv/kv-selectors';
import codemirror from 'vault/tests/helpers/codemirror';
/**
* This test set is for testing edge cases, such as specific bug fixes or reported user workflows
@@ -269,6 +270,20 @@ module('Acceptance | kv-v2 workflow | edge cases', function (hooks) {
await click(PAGE.breadcrumbAtIdx(2));
assert.dom(PAGE.list.item()).exists({ count: 2 }, 'two secrets are listed');
});
test('complex values default to JSON display', async function (assert) {
await visit(`/vault/secrets/${this.backend}/kv/create`);
await fillIn(FORM.inputByAttr('path'), 'complex');
await click(FORM.toggleJson);
assert.strictEqual(codemirror().getValue(), '{ "": "" }');
codemirror().setValue('{ "foo3": { "name": "bar3" } }');
await click(FORM.saveBtn);
// Future: test that json is automatic on details too
await click(PAGE.detail.createNewVersion);
assert.dom(FORM.toggleJson).isDisabled();
assert.dom(FORM.toggleJson).isChecked();
});
});
// NAMESPACE TESTS

View File

@@ -43,7 +43,7 @@ module('Integration | Component | kv-v2 | KvDataFields', function (hooks) {
assert.strictEqual(
codemirror().getValue(' '),
`{ \"\": \"\" }`, // eslint-disable-line no-useless-escape
`{ \"\": \"\" }`, // eslint-disable-line no-useless-escape
'json editor initializes with empty object'
);
await fillIn(`${FORM.jsonEditor} textarea`, 'blah');