Skip to content

Commit

Permalink
UI add custom metadata to KV2 (#12169)
Browse files Browse the repository at this point in the history
* initial setup

* form field editType kv is very helpful

* setting up things

* setup two routes for metadata

* routing

* clean up routing

* meh router changes not my favorite but its working

* show metadata

* add controller for backendCrumb mixin

* setting up edit metadata and trimming SecretEditMetadata component

* add edit metadata save functionality

* create new version work

* setup model and formfieldgroups for added config data.

* add config network request to secret-engine

* fix validations on config

* add config rows

* breaking up secret edit

* add validation for metadata on create

* stuff, but broken now on metadata tab

* fix metadata route error

* permissions

* saving small text changes

* permissions

* cleanup

* some test fixes and convert secret create or update to glimmer

* all these changes fix secret create kv test

* remove alert banners per design request

* fix error for array instead of object in jsonEditor

* add changelog

* styling

* turn into glimmer component

* cleanup

* test failure fix

* add delete or

* clean up

* remove all hardcoded for api integration

* add helper and fix create mode on create new version

* address chelseas pr comments

* add jsdocs to helper

* fix test
  • Loading branch information
Monkeychip committed Aug 31, 2021
1 parent 09909e7 commit 9e4a095
Show file tree
Hide file tree
Showing 35 changed files with 1,428 additions and 735 deletions.
3 changes: 3 additions & 0 deletions changelog/12169.txt
@@ -0,0 +1,3 @@
```release-note:feature
ui: Add custom metadata to KV secret engine and metadata to config
```
43 changes: 35 additions & 8 deletions ui/app/adapters/secret-engine.js
@@ -1,13 +1,18 @@
import { assign } from '@ember/polyfills';
import ApplicationAdapter from './application';
import { encodePath } from 'vault/utils/path-encoding-helpers';
import { splitObject } from 'vault/helpers/split-object';

export default ApplicationAdapter.extend({
url(path) {
const url = `${this.buildURL()}/mounts`;
return path ? url + '/' + encodePath(path) : url;
},

urlForConfig(path) {
return `/v1/${path}/config`;
},

internalURL(path) {
let url = `/${this.urlPrefix()}/internal/ui/mounts`;
if (path) {
Expand All @@ -26,15 +31,37 @@ export default ApplicationAdapter.extend({

createRecord(store, type, snapshot) {
const serializer = store.serializerFor(type.modelName);
const data = serializer.serialize(snapshot);
let data = serializer.serialize(snapshot);
const path = snapshot.attr('path');

return this.ajax(this.url(path), 'POST', { data }).then(() => {
// ember data doesn't like 204s if it's not a DELETE
return {
data: assign({}, data, { path: path + '/', id: path }),
};
});
// for kv2 we make two network requests
if (data.type === 'kv' && data.options.version !== 1) {
// data has both data for sys mount and the config, we need to separate them
let splitObjects = splitObject(data, ['max_versions', 'delete_version_after', 'cas_required']);
let configData;
[configData, data] = splitObjects;
// first create the engine
return this.ajax(this.url(path), 'POST', { data })
.then(() => {
// second modify config on engine
return this.ajax(this.urlForConfig(path), 'POST', { data: configData });
})
.then(() => {
// ember data doesn't like 204s if it's not a DELETE
return {
data: assign({}, data, { path: path + '/', id: path }),
};
})
.catch(e => {
console.log(e, 'error');
});
} else {
return this.ajax(this.url(path), 'POST', { data }).then(() => {
// ember data doesn't like 204s if it's not a DELETE
return {
data: assign({}, data, { path: path + '/', id: path }),
};
});
}
},

findRecord(store, type, path, snapshot) {
Expand Down
35 changes: 34 additions & 1 deletion ui/app/components/kv-object-editor.js
@@ -1,3 +1,26 @@
/**
* @module KvObjectEditor
* KvObjectEditor components are called in FormFields when the editType on the model is kv. They are used to show a key-value input field.
*
* @example
* ```js
* <KvObjectEditor
* @value={{get model valuePath}}
* @onChange={{action "setAndBroadcast" valuePath }}
* @label="some label"
/>
* ```
* @param {string} value - the value is captured from the model.
* @param {function} onChange - function that captures the value on change
* @param {function} onKeyUp - function passed in that handles the dom keyup event. Used for validation on the kv custom metadata.
* @param {string} [label] - label displayed over key value inputs
* @param {string} [warning] - warning that is displayed
* @param {string} [helpText] - helper text. In tooltip.
* @param {string} [subText] - placed under label.
* @param {boolean} [small-label]- change label size.
* @param {boolean} [formSection] - if false the component is meant to live outside of a form, like in the customMetadata which is nested already inside a form-section.
*/

import { isNone } from '@ember/utils';
import { assert } from '@ember/debug';
import Component from '@ember/component';
Expand All @@ -7,12 +30,15 @@ import KVObject from 'vault/lib/kv-object';

export default Component.extend({
'data-test-component': 'kv-object-editor',
classNames: ['field', 'form-section'],
classNames: ['field'],
classNameBindings: ['formSection:form-section'],
formSection: true,
// public API
// Ember Object to mutate
value: null,
label: null,
helpText: null,
subText: null,
// onChange will be called with the changed Value
onChange() {},

Expand Down Expand Up @@ -65,5 +91,12 @@ export default Component.extend({
data.removeAt(index);
this.onChange(data.toJSON());
},

handleKeyUp(name, value) {
if (!this.onKeyUp) {
return;
}
this.onKeyUp(name, value);
},
},
});
23 changes: 18 additions & 5 deletions ui/app/components/mount-backend-form.js
Expand Up @@ -108,11 +108,24 @@ export default Component.extend({

actions: {
onKeyUp(name, value) {
this.mountModel.set('path', value);
this.mountModel.validations.attrs.path.isValid
? set(this.validationMessages, 'path', '')
: set(this.validationMessages, 'path', this.mountModel.validations.attrs.path.message);

// validate path
if (name === 'path') {
this.mountModel.set('path', value);
this.mountModel.validations.attrs.path.isValid
? set(this.validationMessages, 'path', '')
: set(this.validationMessages, 'path', this.mountModel.validations.attrs.path.message);
}
// check maxVersions is a number
if (name === 'maxVersions') {
this.mountModel.set('maxVersions', value);
this.mountModel.validations.attrs.maxVersions.isValid
? set(this.validationMessages, 'maxVersions', '')
: set(
this.validationMessages,
'maxVersions',
this.mountModel.validations.attrs.maxVersions.message
);
}
this.mountModel.validate().then(({ validations }) => {
this.set('isFormInvalid', !validations.isValid);
});
Expand Down

0 comments on commit 9e4a095

Please sign in to comment.