mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 19:47:54 +00:00
UI/utils cleanup (#21863)
* key-utils: create core addon and tests * key-util: remove lib/key-utils and replace all imports with core util
This commit is contained in:
@@ -7,11 +7,10 @@ import { inject as service } from '@ember/service';
|
||||
import { alias, gt } from '@ember/object/computed';
|
||||
import Component from '@ember/component';
|
||||
import { computed } from '@ember/object';
|
||||
import keyUtils from 'vault/lib/key-utils';
|
||||
import pathToTree from 'vault/lib/path-to-tree';
|
||||
import { task, timeout } from 'ember-concurrency';
|
||||
import pathToTree from 'vault/lib/path-to-tree';
|
||||
import { ancestorKeysForKey } from 'core/utils/key-utils';
|
||||
|
||||
const { ancestorKeysForKey } = keyUtils;
|
||||
const DOT_REPLACEMENT = '☃';
|
||||
const ANIMATION_DURATION = 250;
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import { inject as service } from '@ember/service';
|
||||
import { computed } from '@ember/object';
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import ListController from 'core/mixins/list-controller';
|
||||
import { keyIsFolder } from 'core/utils/key-utils';
|
||||
|
||||
export default Controller.extend(ListController, {
|
||||
flashMessages: service(),
|
||||
@@ -26,7 +26,7 @@ export default Controller.extend(ListController, {
|
||||
isLoading: false,
|
||||
|
||||
filterIsFolder: computed('filter', function () {
|
||||
return !!utils.keyIsFolder(this.filter);
|
||||
return !!keyIsFolder(this.filter);
|
||||
}),
|
||||
|
||||
emptyTitle: computed('baseKey.id', 'filter', 'filterIsFolder', function () {
|
||||
|
||||
@@ -7,10 +7,10 @@ import { or } from '@ember/object/computed';
|
||||
import { computed } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Controller from '@ember/controller';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import BackendCrumbMixin from 'vault/mixins/backend-crumb';
|
||||
import WithNavToNearestAncestor from 'vault/mixins/with-nav-to-nearest-ancestor';
|
||||
import ListController from 'core/mixins/list-controller';
|
||||
import { keyIsFolder } from 'core/utils/key-utils';
|
||||
|
||||
export default Controller.extend(ListController, BackendCrumbMixin, WithNavToNearestAncestor, {
|
||||
flashMessages: service(),
|
||||
@@ -19,7 +19,7 @@ export default Controller.extend(ListController, BackendCrumbMixin, WithNavToNea
|
||||
tab: '',
|
||||
|
||||
filterIsFolder: computed('filter', function () {
|
||||
return !!utils.keyIsFolder(this.filter);
|
||||
return !!keyIsFolder(this.filter);
|
||||
}),
|
||||
|
||||
isConfigurableTab: or('isCertTab', 'isConfigure'),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { computed } from '@ember/object';
|
||||
import Mixin from '@ember/object/mixin';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import { keyIsFolder, keyPartsForKey, parentKeyForKey } from 'core/utils/key-utils';
|
||||
|
||||
export default Mixin.create({
|
||||
// what attribute has the path for the key
|
||||
@@ -26,16 +26,16 @@ export default Mixin.create({
|
||||
// rather than using defineProperty for all of these,
|
||||
// we're just going to hardcode the known keys for the path ('id' and 'path')
|
||||
isFolder: computed('id', 'path', function () {
|
||||
return utils.keyIsFolder(this.pathVal());
|
||||
return keyIsFolder(this.pathVal());
|
||||
}),
|
||||
|
||||
keyParts: computed('id', 'path', function () {
|
||||
return utils.keyPartsForKey(this.pathVal());
|
||||
return keyPartsForKey(this.pathVal());
|
||||
}),
|
||||
|
||||
parentKey: computed('id', 'path', 'isCreating', {
|
||||
get: function () {
|
||||
return this.isCreating ? this.initialParentKey : utils.parentKeyForKey(this.pathVal());
|
||||
return this.isCreating ? this.initialParentKey : parentKeyForKey(this.pathVal());
|
||||
},
|
||||
set: function (_, value) {
|
||||
return value;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
import Mixin from '@ember/object/mixin';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import { task } from 'ember-concurrency';
|
||||
import { ancestorKeysForKey } from 'core/utils/key-utils';
|
||||
|
||||
// This mixin is currently used in a controller and a component, but we
|
||||
// don't see cancellation of the task as the while loop runs in either
|
||||
@@ -18,7 +18,7 @@ import { task } from 'ember-concurrency';
|
||||
// the ancestors array and transitions to the root
|
||||
export default Mixin.create({
|
||||
navToNearestAncestor: task(function* (key) {
|
||||
const ancestors = utils.ancestorKeysForKey(key);
|
||||
const ancestors = ancestorKeysForKey(key);
|
||||
let errored = false;
|
||||
let nearest = ancestors.pop();
|
||||
while (nearest) {
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import { set } from '@ember/object';
|
||||
import { hash } from 'rsvp';
|
||||
import { set } from '@ember/object';
|
||||
import Route from '@ember/routing/route';
|
||||
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { keyIsFolder, parentKeyForKey } from 'core/utils/key-utils';
|
||||
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||
|
||||
export default Route.extend(UnloadModelRoute, {
|
||||
store: service(),
|
||||
|
||||
beforeModel() {
|
||||
const { lease_id: leaseId } = this.paramsFor(this.routeName);
|
||||
const parentKey = utils.parentKeyForKey(leaseId);
|
||||
if (utils.keyIsFolder(leaseId)) {
|
||||
const parentKey = parentKeyForKey(leaseId);
|
||||
if (keyIsFolder(leaseId)) {
|
||||
if (parentKey) {
|
||||
return this.transitionTo('vault.cluster.access.leases.list', parentKey);
|
||||
} else {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import { parentKeyForKey } from 'core/utils/key-utils';
|
||||
import EditBase from './secret-edit';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
|
||||
export default EditBase.extend({
|
||||
queryParams: {
|
||||
@@ -17,7 +17,7 @@ export default EditBase.extend({
|
||||
|
||||
beforeModel() {
|
||||
const { secret } = this.paramsFor(this.routeName);
|
||||
const parentKey = utils.parentKeyForKey(secret);
|
||||
const parentKey = parentKeyForKey(secret);
|
||||
const { backend } = this.paramsFor('vault.cluster.secrets.backend');
|
||||
if (this.backendType(backend) !== 'transit') {
|
||||
if (parentKey) {
|
||||
|
||||
@@ -8,9 +8,9 @@ import { set } from '@ember/object';
|
||||
import { resolve } from 'rsvp';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Route from '@ember/routing/route';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||
import { encodePath, normalizePath } from 'vault/utils/path-encoding-helpers';
|
||||
import { keyIsFolder, parentKeyForKey } from 'core/utils/key-utils';
|
||||
|
||||
export default Route.extend(UnloadModelRoute, {
|
||||
store: service(),
|
||||
@@ -79,9 +79,9 @@ export default Route.extend(UnloadModelRoute, {
|
||||
beforeModel({ to: { queryParams } }) {
|
||||
const secret = this.secretParam();
|
||||
return this.buildModel(secret, queryParams).then(() => {
|
||||
const parentKey = utils.parentKeyForKey(secret);
|
||||
const parentKey = parentKeyForKey(secret);
|
||||
const mode = this.routeName.split('.').pop();
|
||||
if (mode === 'edit' && utils.keyIsFolder(secret)) {
|
||||
if (mode === 'edit' && keyIsFolder(secret)) {
|
||||
if (parentKey) {
|
||||
return this.transitionTo('vault.cluster.secrets.backend.list', encodePath(parentKey));
|
||||
} else {
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import UnloadModelRoute from 'vault/mixins/unload-model-route';
|
||||
import { normalizePath } from 'vault/utils/path-encoding-helpers';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { parentKeyForKey } from 'core/utils/key-utils';
|
||||
|
||||
export default Route.extend(UnloadModelRoute, {
|
||||
store: service(),
|
||||
@@ -16,7 +16,7 @@ export default Route.extend(UnloadModelRoute, {
|
||||
beforeModel() {
|
||||
const backendModel = this.modelFor('vault.cluster.secrets.backend');
|
||||
const { secret } = this.paramsFor(this.routeName);
|
||||
const parentKey = utils.parentKeyForKey(secret);
|
||||
const parentKey = parentKeyForKey(secret);
|
||||
if (backendModel.get('isV2KV')) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import Component from '@glimmer/component';
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import { ancestorKeysForKey, keyPartsForKey, keyWithoutParentKey } from 'core/utils/key-utils';
|
||||
import { encodePath } from 'vault/utils/path-encoding-helpers';
|
||||
|
||||
/**
|
||||
@@ -60,8 +60,8 @@ export default class KeyValueHeader extends Component {
|
||||
const path = this.args.path;
|
||||
const currentPath = this.currentPath;
|
||||
const showCurrent = this.showCurrent;
|
||||
const ancestors = utils.ancestorKeysForKey(baseKey);
|
||||
const parts = utils.keyPartsForKey(baseKey);
|
||||
const ancestors = ancestorKeysForKey(baseKey);
|
||||
const parts = keyPartsForKey(baseKey);
|
||||
if (ancestors.length === 0) {
|
||||
crumbs.push({
|
||||
label: baseKey,
|
||||
@@ -87,8 +87,8 @@ export default class KeyValueHeader extends Component {
|
||||
});
|
||||
|
||||
crumbs.push({
|
||||
label: utils.keyWithoutParentKey(baseKey),
|
||||
text: this.stripTrailingSlash(utils.keyWithoutParentKey(baseKey)),
|
||||
label: keyWithoutParentKey(baseKey),
|
||||
text: this.stripTrailingSlash(keyWithoutParentKey(baseKey)),
|
||||
path: currentPath,
|
||||
model: baseKeyModel,
|
||||
});
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Ember from 'ember';
|
||||
import { debounce, later } from '@ember/runloop';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { guidFor } from '@ember/object/internals';
|
||||
import Component from '@glimmer/component';
|
||||
|
||||
// TODO MOVE THESE TO THE ADDON
|
||||
import utils from 'vault/lib/key-utils';
|
||||
import keys from 'vault/lib/keycodes';
|
||||
import { encodePath } from 'vault/utils/path-encoding-helpers';
|
||||
import Ember from 'ember';
|
||||
import { keyIsFolder, parentKeyForKey } from 'core/utils/key-utils';
|
||||
// TODO MOVE THESE TO THE ADDON
|
||||
import keys from 'vault/lib/keycodes';
|
||||
|
||||
/**
|
||||
* @module NavigateInput
|
||||
@@ -94,7 +94,7 @@ export default class NavigateInput extends Component {
|
||||
if (mode.startsWith('secrets') && (!val || val === baseKey)) {
|
||||
return;
|
||||
}
|
||||
if (this.args.filterMatchesKey && !utils.keyIsFolder(val)) {
|
||||
if (this.args.filterMatchesKey && !keyIsFolder(val)) {
|
||||
const params = [routeFor('show', mode, this.args.urls), extraParams, this.keyForNav(val)].compact();
|
||||
this.transitionToRoute(...params);
|
||||
} else {
|
||||
@@ -126,7 +126,7 @@ export default class NavigateInput extends Component {
|
||||
|
||||
// pop to the nearest parentKey or to the root
|
||||
onEscape(val) {
|
||||
const key = utils.parentKeyForKey(val) || '';
|
||||
const key = parentKeyForKey(val) || '';
|
||||
this.args.filterDidChange(key);
|
||||
this.filterUpdated(key);
|
||||
}
|
||||
@@ -150,11 +150,11 @@ export default class NavigateInput extends Component {
|
||||
}
|
||||
// select the key to nav to, assumed to be a folder
|
||||
let key = val ? val.trim() : '';
|
||||
const isFolder = utils.keyIsFolder(key);
|
||||
const isFolder = keyIsFolder(key);
|
||||
|
||||
if (!isFolder) {
|
||||
// nav to the closest parentKey (or the root)
|
||||
key = utils.parentKeyForKey(val) || '';
|
||||
key = parentKeyForKey(val) || '';
|
||||
}
|
||||
|
||||
const pageFilter = val.replace(key, '');
|
||||
@@ -167,7 +167,7 @@ export default class NavigateInput extends Component {
|
||||
if (key) {
|
||||
args.push(key);
|
||||
}
|
||||
if (pageFilter && !utils.keyIsFolder(pageFilter)) {
|
||||
if (pageFilter && !keyIsFolder(pageFilter)) {
|
||||
args.push({
|
||||
queryParams: {
|
||||
page: 1,
|
||||
|
||||
@@ -3,37 +3,38 @@
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
function keyIsFolder(key) {
|
||||
export function keyIsFolder(key: string) {
|
||||
return key ? !!key.match(/\/$/) : false;
|
||||
}
|
||||
|
||||
function keyPartsForKey(key) {
|
||||
export function keyPartsForKey(key: string) {
|
||||
if (!key) {
|
||||
return null;
|
||||
}
|
||||
var isFolder = keyIsFolder(key);
|
||||
var parts = key.split('/');
|
||||
const isFolder = keyIsFolder(key);
|
||||
const parts = key.split('/');
|
||||
if (isFolder) {
|
||||
// remove last item which is empty
|
||||
parts.pop();
|
||||
}
|
||||
return parts.length > 1 ? parts : null;
|
||||
}
|
||||
|
||||
function parentKeyForKey(key) {
|
||||
var parts = keyPartsForKey(key);
|
||||
export function parentKeyForKey(key: string) {
|
||||
const parts = keyPartsForKey(key);
|
||||
if (!parts) {
|
||||
return null;
|
||||
return '';
|
||||
}
|
||||
return parts.slice(0, -1).join('/') + '/';
|
||||
}
|
||||
|
||||
function keyWithoutParentKey(key) {
|
||||
export function keyWithoutParentKey(key: string) {
|
||||
return key ? key.replace(parentKeyForKey(key), '') : null;
|
||||
}
|
||||
|
||||
function ancestorKeysForKey(key) {
|
||||
var ancestors = [],
|
||||
parentKey = parentKeyForKey(key);
|
||||
export function ancestorKeysForKey(key: string) {
|
||||
const ancestors = [];
|
||||
let parentKey = parentKeyForKey(key);
|
||||
|
||||
while (parentKey) {
|
||||
ancestors.unshift(parentKey);
|
||||
@@ -42,11 +43,3 @@ function ancestorKeysForKey(key) {
|
||||
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
export default {
|
||||
keyIsFolder,
|
||||
keyPartsForKey,
|
||||
parentKeyForKey,
|
||||
keyWithoutParentKey,
|
||||
ancestorKeysForKey,
|
||||
};
|
||||
7
ui/lib/core/app/utils/key-utils.js
Normal file
7
ui/lib/core/app/utils/key-utils.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export {
|
||||
keyIsFolder,
|
||||
keyPartsForKey,
|
||||
parentKeyForKey,
|
||||
keyWithoutParentKey,
|
||||
ancestorKeysForKey,
|
||||
} from 'core/utils/key-utils';
|
||||
62
ui/tests/unit/utils/key-utils-test.js
Normal file
62
ui/tests/unit/utils/key-utils-test.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
ancestorKeysForKey,
|
||||
keyIsFolder,
|
||||
keyPartsForKey,
|
||||
keyWithoutParentKey,
|
||||
parentKeyForKey,
|
||||
} from 'vault/utils/key-utils';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Utility | key-utils', function () {
|
||||
test('keyIsFolder', function (assert) {
|
||||
let result = keyIsFolder('foo');
|
||||
assert.false(result, 'not folder');
|
||||
|
||||
result = keyIsFolder('foo/');
|
||||
assert.true(result, 'is folder');
|
||||
|
||||
result = keyIsFolder('foo/bar');
|
||||
assert.false(result, 'not folder');
|
||||
});
|
||||
test('keyPartsForKey', function (assert) {
|
||||
let result = keyPartsForKey('');
|
||||
assert.strictEqual(result, null, 'falsy value returns null');
|
||||
|
||||
result = keyPartsForKey('foo');
|
||||
assert.strictEqual(result, null, 'returns null if not a folder');
|
||||
|
||||
result = keyPartsForKey('foo/bar');
|
||||
assert.deepEqual(result, ['foo', 'bar'], 'returns parts of key');
|
||||
|
||||
result = keyPartsForKey('foo/bar/');
|
||||
assert.deepEqual(result, ['foo', 'bar'], 'returns parts of key when ends in slash');
|
||||
});
|
||||
test('parentKeyForKey', function (assert) {
|
||||
let result = parentKeyForKey('my/very/nested/secret/path');
|
||||
assert.strictEqual(result, 'my/very/nested/secret/', 'returns parent path for key');
|
||||
|
||||
result = parentKeyForKey('my/nested/secret/');
|
||||
assert.strictEqual(result, 'my/nested/', 'returns correct parents');
|
||||
|
||||
result = parentKeyForKey('my-secret');
|
||||
assert.strictEqual(result, '', 'returns empty string when no parents');
|
||||
});
|
||||
test('keyWithoutParentKey', function (assert) {
|
||||
let result = keyWithoutParentKey('my/very/nested/secret/path');
|
||||
assert.strictEqual(result, 'path', 'returns key without parent key');
|
||||
|
||||
result = keyWithoutParentKey('my-secret');
|
||||
assert.strictEqual(result, 'my-secret', 'returns path when no parent');
|
||||
|
||||
result = keyWithoutParentKey('folder/');
|
||||
assert.strictEqual(result, 'folder/', 'returns path as-is when folder without parent');
|
||||
});
|
||||
test('ancestorKeysForKey', function (assert) {
|
||||
const expected = ['my/', 'my/very/', 'my/very/nested/', 'my/very/nested/secret/'];
|
||||
let result = ancestorKeysForKey('my/very/nested/secret/path');
|
||||
assert.deepEqual(result, expected, 'returns array of ancestor paths');
|
||||
|
||||
result = ancestorKeysForKey('foobar');
|
||||
assert.deepEqual(result, [], 'returns empty array for root path');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user