readonly sessions on mongo (+checks on BE)

This commit is contained in:
Jan Prochazka 2022-03-17 13:17:30 +01:00
parent 7d196c7c62
commit 8f1d76fd2a
8 changed files with 51 additions and 13 deletions

View File

@ -159,7 +159,7 @@ module.exports = {
async collectionData({ conid, database, options }) { async collectionData({ conid, database, options }) {
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
const res = await this.sendRequest(opened, { msgtype: 'collectionData', options }); const res = await this.sendRequest(opened, { msgtype: 'collectionData', options });
return res.result; return res.result || null;
}, },
async loadDataCore(msgtype, { conid, database, ...args }) { async loadDataCore(msgtype, { conid, database, ...args }) {
@ -167,6 +167,10 @@ module.exports = {
const res = await this.sendRequest(opened, { msgtype, ...args }); const res = await this.sendRequest(opened, { msgtype, ...args });
if (res.errorMessage) { if (res.errorMessage) {
console.error(res.errorMessage); console.error(res.errorMessage);
return {
errorMessage: res.errorMessage,
};
} }
return res.result || null; return res.result || null;
}, },
@ -193,19 +197,26 @@ module.exports = {
callMethod_meta: true, callMethod_meta: true,
async callMethod({ conid, database, method, args }) { async callMethod({ conid, database, method, args }) {
const opened = await this.ensureOpened(conid, database); return this.loadDataCore('callMethod', { conid, database, method, args });
const res = await this.sendRequest(opened, { msgtype: 'callMethod', method, args });
if (res.errorMessage) { // const opened = await this.ensureOpened(conid, database);
console.error(res.errorMessage); // const res = await this.sendRequest(opened, { msgtype: 'callMethod', method, args });
} // if (res.errorMessage) {
return res.result || null; // console.error(res.errorMessage);
// }
// return res.result || null;
}, },
updateCollection_meta: true, updateCollection_meta: true,
async updateCollection({ conid, database, changeSet }) { async updateCollection({ conid, database, changeSet }) {
const opened = await this.ensureOpened(conid, database); const opened = await this.ensureOpened(conid, database);
const res = await this.sendRequest(opened, { msgtype: 'updateCollection', changeSet }); const res = await this.sendRequest(opened, { msgtype: 'updateCollection', changeSet });
return res.result; if (res.errorMessage) {
return {
errorMessage: res.errorMessage,
};
}
return res.result || null;
}, },
status_meta: true, status_meta: true,

View File

@ -155,6 +155,7 @@ async function handleRunScript({ msgid, sql }) {
await waitConnected(); await waitConnected();
const driver = requireEngineDriver(storedConnection); const driver = requireEngineDriver(storedConnection);
try { try {
ensureExecuteCustomScript(driver);
await driver.script(systemConnection, sql); await driver.script(systemConnection, sql);
process.send({ msgtype: 'response', msgid }); process.send({ msgtype: 'response', msgid });
} catch (err) { } catch (err) {
@ -166,6 +167,7 @@ async function handleQueryData({ msgid, sql }) {
await waitConnected(); await waitConnected();
const driver = requireEngineDriver(storedConnection); const driver = requireEngineDriver(storedConnection);
try { try {
ensureExecuteCustomScript(driver);
const res = await driver.query(systemConnection, sql); const res = await driver.query(systemConnection, sql);
process.send({ msgtype: 'response', msgid, ...res }); process.send({ msgtype: 'response', msgid, ...res });
} catch (err) { } catch (err) {
@ -204,7 +206,10 @@ async function handleLoadKeyInfo({ msgid, key }) {
} }
async function handleCallMethod({ msgid, method, args }) { async function handleCallMethod({ msgid, method, args }) {
return handleDriverDataCore(msgid, driver => driver.callMethod(systemConnection, method, args)); return handleDriverDataCore(msgid, driver => {
ensureExecuteCustomScript(driver);
return driver.callMethod(systemConnection, method, args);
});
} }
async function handleLoadKeyTableRange({ msgid, key, cursor, count }) { async function handleLoadKeyTableRange({ msgid, key, cursor, count }) {
@ -217,10 +222,20 @@ async function handleLoadFieldValues({ msgid, schemaName, pureName, field, searc
); );
} }
function ensureExecuteCustomScript(driver) {
if (driver.readOnlySessions) {
return;
}
if (storedConnection.isReadOnly) {
throw new Error('Connection is read only');
}
}
async function handleUpdateCollection({ msgid, changeSet }) { async function handleUpdateCollection({ msgid, changeSet }) {
await waitConnected(); await waitConnected();
const driver = requireEngineDriver(storedConnection); const driver = requireEngineDriver(storedConnection);
try { try {
ensureExecuteCustomScript(driver);
const result = await driver.updateCollection(systemConnection, changeSet); const result = await driver.updateCollection(systemConnection, changeSet);
process.send({ msgtype: 'response', msgid, result }); process.send({ msgtype: 'response', msgid, result });
} catch (err) { } catch (err) {

View File

@ -135,10 +135,20 @@ function handleStream(driver, resultIndexHolder, sql) {
}); });
} }
function ensureExecuteCustomScript(driver) {
if (driver.readOnlySessions) {
return;
}
if (storedConnection.isReadOnly) {
throw new Error('Connection is read only');
}
}
async function handleConnect(connection) { async function handleConnect(connection) {
storedConnection = connection; storedConnection = connection;
const driver = requireEngineDriver(storedConnection); const driver = requireEngineDriver(storedConnection);
ensureExecuteCustomScript(driver);
systemConnection = await connectUtility(driver, storedConnection); systemConnection = await connectUtility(driver, storedConnection);
for (const [resolve] of afterConnectCallbacks) { for (const [resolve] of afterConnectCallbacks) {
resolve(); resolve();

View File

@ -47,6 +47,7 @@ export interface EngineDriver {
title: string; title: string;
defaultPort?: number; defaultPort?: number;
databaseEngineTypes: string[]; databaseEngineTypes: string[];
readOnlySessions: boolean,
supportedKeyTypes: { name: string; label: string }[]; supportedKeyTypes: { name: string; label: string }[];
supportsDatabaseUrl?: boolean; supportsDatabaseUrl?: boolean;
isElectronOnly?: boolean; isElectronOnly?: boolean;

View File

@ -173,6 +173,6 @@
<ToolStripCommandButton command="dataGrid.deleteSelectedRows" hideDisabled /> <ToolStripCommandButton command="dataGrid.deleteSelectedRows" hideDisabled />
<ToolStripCommandButton command="dataGrid.switchToJson" hideDisabled /> <ToolStripCommandButton command="dataGrid.switchToJson" hideDisabled />
<ToolStripCommandButton command="dataGrid.switchToTable" hideDisabled /> <ToolStripCommandButton command="dataGrid.switchToTable" hideDisabled />
<ToolStripExportButton {quickExportHandlerRef} command='collectionDataGrid.export' /> <ToolStripExportButton {quickExportHandlerRef} command="collectionDataGrid.export" />
</svelte:fragment> </svelte:fragment>
</ToolStripContainer> </ToolStripContainer>

View File

@ -140,7 +140,7 @@
} }
export function hasConnection() { export function hasConnection() {
return !!conid; return !!conid && (!$connection.isReadOnly || driver.readOnlySessions);
} }
async function executeCore(sql) { async function executeCore(sql) {

View File

@ -38,9 +38,9 @@ const driver = {
showConnectionField: (field, values) => { showConnectionField: (field, values) => {
if (field == 'useDatabaseUrl') return true; if (field == 'useDatabaseUrl') return true;
if (values.useDatabaseUrl) { if (values.useDatabaseUrl) {
return ['databaseUrl', 'defaultDatabase', 'singleDatabase'].includes(field); return ['databaseUrl', 'defaultDatabase', 'singleDatabase', 'isReadOnly'].includes(field);
} }
return ['server', 'port', 'user', 'password', 'defaultDatabase', 'singleDatabase'].includes(field); return ['server', 'port', 'user', 'password', 'defaultDatabase', 'singleDatabase', 'isReadOnly'].includes(field);
}, },
importExportArgs: [ importExportArgs: [

View File

@ -46,6 +46,7 @@ const mysqlDriverBase = {
dialect, dialect,
defaultPort: 3306, defaultPort: 3306,
getQuerySplitterOptions: () => mysqlSplitterOptions, getQuerySplitterOptions: () => mysqlSplitterOptions,
readOnlySessions: true,
getNewObjectTemplates() { getNewObjectTemplates() {
return [ return [