Files
vault/ui/app/services/console.js

114 lines
3.1 KiB
JavaScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
// Low level service that allows users to input paths to make requests to vault
// this service provides the UI synecdote to the cli commands read, write, delete, and list
import Service from '@ember/service';
import { getOwner } from '@ember/owner';
import { shiftCommandIndex } from 'vault/lib/console-helpers';
import { encodePath } from 'vault/utils/path-encoding-helpers';
import { sanitizePath, ensureTrailingSlash } from 'core/utils/sanitize-path';
import { tracked } from '@glimmer/tracking';
import { addManyToArray } from 'vault/helpers/add-to-array';
const VERBS = {
read: 'GET',
list: 'GET',
write: 'POST',
delete: 'DELETE',
};
export default class ConsoleService extends Service {
@tracked isOpen = false;
@tracked commandIndex = null;
@tracked log = [];
get commandHistory() {
return this.log.filter((log) => log.type === 'command');
}
// Not a getter so it can be stubbed in tests
adapter() {
return getOwner(this).lookup('adapter:console');
}
shiftCommandIndex(keyCode, setCommandFn = () => {}) {
const [newIndex, newCommand] = shiftCommandIndex(keyCode, this.commandHistory, this.commandIndex);
if (newCommand !== undefined && newIndex !== undefined) {
this.commandIndex = newIndex;
setCommandFn(newCommand);
}
}
clearLog(clearAll = false) {
let history;
if (!clearAll) {
history = this.commandHistory.slice();
history.setEach('hidden', true);
}
this.log = [];
if (history) {
this.log = addManyToArray(this.log, history);
}
}
logAndOutput(command, logContent) {
const log = this.log.slice();
if (command) {
log.push({ type: 'command', content: command });
this.commandIndex = null;
}
if (logContent) {
log.push(logContent);
}
this.log = log;
}
ajax(operation, path, options = {}) {
const verb = VERBS[operation];
const adapter = this.adapter();
const url = adapter.buildURL(encodePath(path));
const { data, wrapTTL } = options;
return adapter.ajax(url, verb, {
data,
wrapTTL,
});
}
kvGet(path, data, flags = {}) {
const { wrapTTL, metadata } = flags;
// Split on first / to find backend and secret path
const pathSegment = metadata ? 'metadata' : 'data';
const [backend, secretPath] = path.split(/\/(.+)?/);
const kvPath = `${backend}/${pathSegment}/${secretPath}`;
return this.ajax('read', sanitizePath(kvPath), { wrapTTL });
}
read(path, data, flags) {
const wrapTTL = flags?.wrapTTL;
return this.ajax('read', sanitizePath(path), { wrapTTL });
}
write(path, data, flags) {
const wrapTTL = flags?.wrapTTL;
return this.ajax('write', sanitizePath(path), { data, wrapTTL });
}
delete(path) {
return this.ajax('delete', sanitizePath(path));
}
list(path, data, flags) {
const wrapTTL = flags?.wrapTTL;
const listPath = ensureTrailingSlash(sanitizePath(path));
return this.ajax('list', listPath, {
data: {
list: true,
},
wrapTTL,
});
}
}