redis: support readonly and database url

This commit is contained in:
Jan Prochazka
2022-03-27 18:34:22 +02:00
parent 11c82b1aac
commit 0e8166577f
4 changed files with 75 additions and 56 deletions

View File

@@ -211,6 +211,10 @@ async function handleLoadKeyInfo({ msgid, key }) {
async function handleCallMethod({ msgid, method, args }) { async function handleCallMethod({ msgid, method, args }) {
return handleDriverDataCore(msgid, driver => { return handleDriverDataCore(msgid, driver => {
if (storedConnection.isReadOnly) {
throw new Error('Connection is read only, cannot call custom methods');
}
ensureExecuteCustomScript(driver); ensureExecuteCustomScript(driver);
return driver.callMethod(systemConnection, method, args); return driver.callMethod(systemConnection, method, args);
}); });

View File

@@ -3,15 +3,15 @@
import AppObjectCore from '../appobj/AppObjectCore.svelte'; import AppObjectCore from '../appobj/AppObjectCore.svelte';
import { plusExpandIcon } from '../icons/expandIcons'; import { plusExpandIcon } from '../icons/expandIcons';
import FontIcon from '../icons/FontIcon.svelte';
import ConfirmModal from '../modals/ConfirmModal.svelte'; import ConfirmModal from '../modals/ConfirmModal.svelte';
import InputTextModal from '../modals/InputTextModal.svelte'; import InputTextModal from '../modals/InputTextModal.svelte';
import { showModal } from '../modals/modalTools'; import { showModal } from '../modals/modalTools';
import newQuery from '../query/newQuery'; import newQuery from '../query/newQuery';
import { activeDbKeysStore } from '../stores'; import { activeDbKeysStore } from '../stores';
import { apiCall } from '../utility/api'; import { apiCall } from '../utility/api';
import { getConnectionInfo } from '../utility/metadataLoaders';
import openNewTab from '../utility/openNewTab'; import openNewTab from '../utility/openNewTab';
import { showSnackbarError } from '../utility/snackbar'; import { showSnackbarError } from '../utility/snackbar';
import DbKeysSubTree from './DbKeysSubTree.svelte'; import DbKeysSubTree from './DbKeysSubTree.svelte';
@@ -29,56 +29,60 @@ import { showSnackbarError } from '../utility/snackbar';
let reloadToken = 0; let reloadToken = 0;
// $: console.log(item.text, indentLevel); // $: console.log(item.text, indentLevel);
function createMenu() { async function createMenu() {
const connection = await getConnectionInfo({ conid });
return [ return [
item.key != null && { item.key != null &&
label: 'Delete key', !connection?.isReadOnly && {
onClick: () => { label: 'Delete key',
showModal(ConfirmModal, { onClick: () => {
message: `Really delete key ${item.key}?`, showModal(ConfirmModal, {
onConfirm: async () => { message: `Really delete key ${item.key}?`,
await apiCall('database-connections/call-method', { onConfirm: async () => {
conid, await apiCall('database-connections/call-method', {
database, conid,
method: 'del', database,
args: [item.key], method: 'del',
}); args: [item.key],
});
if (onRefreshParent) { if (onRefreshParent) {
onRefreshParent(); onRefreshParent();
} }
}, },
}); });
},
}, },
}, item.key != null &&
item.key != null && { !connection?.isReadOnly && {
label: 'Rename key', label: 'Rename key',
onClick: () => { onClick: () => {
showModal(InputTextModal, { showModal(InputTextModal, {
value: item.key, value: item.key,
label: 'New name', label: 'New name',
header: 'Rename key', header: 'Rename key',
onConfirm: async newName => { onConfirm: async newName => {
await apiCall('database-connections/call-method', { await apiCall('database-connections/call-method', {
conid, conid,
database, database,
method: 'rename', method: 'rename',
args: [item.key, newName], args: [item.key, newName],
}); });
if (onRefreshParent) { if (onRefreshParent) {
onRefreshParent(); onRefreshParent();
} }
}, },
}); });
},
}, },
}, item.type == 'dir' &&
item.type == 'dir' && { !connection?.isReadOnly && {
label: 'Reload', label: 'Reload',
onClick: () => { onClick: () => {
reloadToken += 1; reloadToken += 1;
},
}, },
},
item.type == 'dir' && { item.type == 'dir' && {
label: 'Delete branch', label: 'Delete branch',
onClick: () => { onClick: () => {

View File

@@ -80,16 +80,22 @@ function splitCommandLine(str) {
const driver = { const driver = {
...driverBase, ...driverBase,
analyserClass: Analyser, analyserClass: Analyser,
async connect({ server, port, password, database }) { async connect({ server, port, password, database, useDatabaseUrl, databaseUrl }) {
let db = 0; let db = 0;
if (_.isString(database) && database.startsWith('db')) db = parseInt(database.substring(2)); let pool;
if (_.isNumber(database)) db = database; if (useDatabaseUrl) {
const pool = new Redis({ pool = new Redis(databaseUrl);
host: server, } else {
port, if (_.isString(database) && database.startsWith('db')) db = parseInt(database.substring(2));
password, if (_.isNumber(database)) db = database;
db, pool = new Redis({
}); host: server,
port,
password,
db,
});
}
return pool; return pool;
}, },
// @ts-ignore // @ts-ignore

View File

@@ -26,6 +26,7 @@ const driver = {
databaseEngineTypes: ['keyvalue'], databaseEngineTypes: ['keyvalue'],
supportedCreateDatabase: false, supportedCreateDatabase: false,
getQuerySplitterOptions: () => redisSplitterOptions, getQuerySplitterOptions: () => redisSplitterOptions,
databaseUrlPlaceholder: 'e.g. redis://:authpassword@127.0.0.1:6380/4',
supportedKeyTypes: [ supportedKeyTypes: [
{ {
name: 'string', name: 'string',
@@ -75,7 +76,11 @@ const driver = {
], ],
showConnectionField: (field, values) => { showConnectionField: (field, values) => {
return ['server', 'port', 'password'].includes(field); if (field == 'useDatabaseUrl') return true;
if (values.useDatabaseUrl) {
return ['databaseUrl', 'isReadOnly'].includes(field);
}
return ['server', 'port', 'password', 'isReadOnly'].includes(field);
}, },
}; };