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:
Chelsea Shaw
2023-07-14 14:45:57 -05:00
committed by GitHub
parent cc366f6cba
commit 88ca498fb4
14 changed files with 119 additions and 58 deletions

View File

@@ -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;

View File

@@ -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 () {

View File

@@ -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'),

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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,
});

View File

@@ -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,

View File

@@ -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,
};

View File

@@ -0,0 +1,7 @@
export {
keyIsFolder,
keyPartsForKey,
parentKeyForKey,
keyWithoutParentKey,
ancestorKeysForKey,
} from 'core/utils/key-utils';

View 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');
});
});