Merge branch 'master' into sqlite

This commit is contained in:
Jan Prochazka
2021-05-03 18:43:34 +02:00
41 changed files with 419 additions and 400 deletions

View File

@@ -9,6 +9,16 @@ const currentVersion = require('../currentVersion');
const platformInfo = require('../utility/platformInfo');
module.exports = {
settingsValue: {},
async _init() {
try {
this.settingsValue = JSON.parse(await fs.readFile(path.join(datadir(), 'settings.json'), { encoding: 'utf-8' }));
} catch (err) {
this.settingsValue = {};
}
},
get_meta: 'get',
async get() {
// const toolbarButtons = process.env.TOOLBAR;
@@ -47,23 +57,19 @@ module.exports = {
getSettings_meta: 'get',
async getSettings() {
try {
return JSON.parse(await fs.readFile(path.join(datadir(), 'settings.json'), { encoding: 'utf-8' }));
} catch (err) {
return {};
}
return this.settingsValue;
},
updateSettings_meta: 'post',
async updateSettings(values) {
if (!hasPermission(`settings/change`)) return false;
const oldSettings = await this.getSettings();
try {
const updated = {
...oldSettings,
...this.settingsValue,
...values,
};
await fs.writeFile(path.join(datadir(), 'settings.json'), JSON.stringify(updated, undefined, 2));
this.settingsValue = updated;
socket.emitChanged(`settings-changed`);
return updated;
} catch (err) {

View File

@@ -4,6 +4,7 @@ const socket = require('../utility/socket');
const { fork } = require('child_process');
const { DatabaseAnalyser } = require('dbgate-tools');
const { handleProcessCommunication } = require('../utility/processComm');
const config = require('./config');
module.exports = {
/** @type {import('dbgate-types').OpenedDatabaseConnection[]} */
@@ -79,6 +80,7 @@ module.exports = {
msgtype: 'connect',
connection: { ...connection, database },
structure: lastClosed ? lastClosed.structure : null,
globalSettings: config.settingsValue
});
return newOpened;
},

View File

@@ -64,19 +64,23 @@ module.exports = {
const res = [];
for (const packageName of _.union(files1, files2)) {
if (!/^dbgate-plugin-.*$/.test(packageName)) continue;
const isPackaged = files1.includes(packageName);
const manifest = await fs
.readFile(path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'package.json'), {
encoding: 'utf-8',
})
.then(x => JSON.parse(x));
const readmeFile = path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'README.md');
// @ts-ignore
if (await fs.exists(readmeFile)) {
manifest.readme = await fs.readFile(readmeFile, { encoding: 'utf-8' });
try {
const isPackaged = files1.includes(packageName);
const manifest = await fs
.readFile(path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'package.json'), {
encoding: 'utf-8',
})
.then(x => JSON.parse(x));
const readmeFile = path.join(isPackaged ? packagedPluginsDir() : pluginsdir(), packageName, 'README.md');
// @ts-ignore
if (await fs.exists(readmeFile)) {
manifest.readme = await fs.readFile(readmeFile, { encoding: 'utf-8' });
}
manifest.isPackaged = isPackaged;
res.push(manifest);
} catch (err) {
console.log(`Skipped plugin ${packageName}, error:`, err.message);
}
manifest.isPackaged = isPackaged;
res.push(manifest);
}
return res;
},

View File

@@ -5,6 +5,7 @@ const _ = require('lodash');
const AsyncLock = require('async-lock');
const { handleProcessCommunication } = require('../utility/processComm');
const lock = new AsyncLock();
const config = require('./config');
module.exports = {
opened: [],
@@ -65,7 +66,7 @@ module.exports = {
if (newOpened.disconnected) return;
this.close(conid, false);
});
subprocess.send({ msgtype: 'connect', ...connection });
subprocess.send({ msgtype: 'connect', ...connection, globalSettings: config.settingsValue });
return newOpened;
});
return res;

View File

@@ -31,6 +31,7 @@ const scheduler = require('./controllers/scheduler');
const { rundir } = require('./utility/directories');
const platformInfo = require('./utility/platformInfo');
const processArgs = require('./utility/processArgs');
const timingSafeCheckToken = require('./utility/timingSafeCheckToken');
let authorization = null;
let checkLocalhostOrigin = null;
@@ -56,7 +57,7 @@ function start() {
}
app.use(function (req, res, next) {
if (authorization && req.headers.authorization != authorization) {
if (authorization && !timingSafeCheckToken(req.headers.authorization, authorization)) {
return res.status(403).json({ error: 'Not authorized!' });
}
if (checkLocalhostOrigin) {

View File

@@ -1,5 +1,6 @@
const stableStringify = require('json-stable-stringify');
const childProcessChecker = require('../utility/childProcessChecker');
const { extractBoolSettingsValue, extractIntSettingsValue } = require('dbgate-tools');
const requireEngineDriver = require('../utility/requireEngineDriver');
const connectUtility = require('../utility/connectUtility');
const { handleProcessCommunication } = require('../utility/processComm');
@@ -29,6 +30,7 @@ async function checkedAsyncCall(promise) {
async function handleFullRefresh() {
const driver = requireEngineDriver(storedConnection);
setStatusName('loadStructure');
analysedStructure = await checkedAsyncCall(driver.analyseFull(systemConnection));
process.send({ msgtype: 'structure', structure: analysedStructure });
setStatusName('ok');
@@ -36,6 +38,7 @@ async function handleFullRefresh() {
async function handleIncrementalRefresh() {
const driver = requireEngineDriver(storedConnection);
setStatusName('checkStructure');
const newStructure = await checkedAsyncCall(driver.analyseIncremental(systemConnection, analysedStructure));
if (newStructure != null) {
analysedStructure = newStructure;
@@ -62,7 +65,7 @@ async function readVersion() {
process.send({ msgtype: 'version', version });
}
async function handleConnect({ connection, structure }) {
async function handleConnect({ connection, structure, globalSettings }) {
storedConnection = connection;
lastPing = new Date().getTime();
@@ -76,7 +79,14 @@ async function handleConnect({ connection, structure }) {
} else {
handleFullRefresh();
}
setInterval(handleIncrementalRefresh, 30 * 1000);
if (extractBoolSettingsValue(globalSettings, 'connection.autoRefresh', true)) {
setInterval(
handleIncrementalRefresh,
extractIntSettingsValue(globalSettings, 'connection.autoRefreshInterval', 30, 3, 3600) * 1000
);
}
for (const [resolve] of afterConnectCallbacks) {
resolve();
}

View File

@@ -1,4 +1,5 @@
const stableStringify = require('json-stable-stringify');
const { extractBoolSettingsValue, extractIntSettingsValue } = require('dbgate-tools');
const childProcessChecker = require('../utility/childProcessChecker');
const requireEngineDriver = require('../utility/requireEngineDriver');
const { decryptConnection } = require('../utility/crypting');
@@ -51,6 +52,7 @@ function setStatusName(name) {
async function handleConnect(connection) {
storedConnection = connection;
const { globalSettings } = storedConnection;
setStatusName('pending');
lastPing = new Date().getTime();
@@ -59,7 +61,9 @@ async function handleConnect(connection) {
systemConnection = await connectUtility(driver, storedConnection);
readVersion();
handleRefresh();
setInterval(handleRefresh, 30 * 1000);
if (extractBoolSettingsValue(globalSettings, 'connection.autoRefresh', true)) {
setInterval(handleRefresh, extractIntSettingsValue(globalSettings, 'connection.autoRefreshInterval', 30, 5, 3600) * 1000);
}
} catch (err) {
setStatus({
name: 'error',

View File

@@ -34,7 +34,7 @@ async function getSshConnection(connection) {
password: connection.sshMode == 'userPassword' ? connection.sshPassword : undefined,
agentSocket: connection.sshMode == 'agent' ? platformInfo.sshAuthSock : undefined,
privateKey:
connection.sshMode == 'keyFile' && connection.sshKeyFile ? await fs.readFile(connection.sshKeyFile) : undefined,
connection.sshMode == 'keyFile' && connection.sshKeyfile ? await fs.readFile(connection.sshKeyfile) : undefined,
skipAutoPrivateKey: true,
noReadline: true,
};

View File

@@ -0,0 +1,9 @@
const crypto = require('crypto');
function timingSafeCheckToken(a, b) {
if (!a || !b) return false;
if (a.length != b.length) return false;
return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
}
module.exports = timingSafeCheckToken;