Early work on Postgres SQL support.

This commit is contained in:
Ylian Saint-Hilaire 2021-11-02 19:44:41 -07:00
parent 5c7cd3b017
commit 97bd723e4e
4 changed files with 70 additions and 10 deletions

View File

@ -645,6 +645,7 @@
<Folder Include="typings\globals\is-plain-object\" />
<Folder Include="typings\globals\jsbn\" />
<Folder Include="typings\globals\klaw\" />
<Folder Include="typings\globals\load-json-file\" />
<Folder Include="typings\globals\localforage\" />
<Folder Include="typings\globals\lru-cache\" />
<Folder Include="typings\globals\marked\" />
@ -655,10 +656,13 @@
<Folder Include="typings\globals\object-assign\" />
<Folder Include="typings\globals\once\" />
<Folder Include="typings\globals\passport\" />
<Folder Include="typings\globals\pg-pool\" />
<Folder Include="typings\globals\split2\" />
<Folder Include="typings\globals\sprintf-js\" />
<Folder Include="typings\globals\type-check\" />
<Folder Include="typings\globals\underscore\" />
<Folder Include="typings\globals\uuid\" />
<Folder Include="typings\globals\window-size\" />
<Folder Include="views\" />
</ItemGroup>
<ItemGroup>
@ -681,6 +685,7 @@
<TypeScriptCompile Include="typings\globals\is-plain-object\index.d.ts" />
<TypeScriptCompile Include="typings\globals\jsbn\index.d.ts" />
<TypeScriptCompile Include="typings\globals\klaw\index.d.ts" />
<TypeScriptCompile Include="typings\globals\load-json-file\index.d.ts" />
<TypeScriptCompile Include="typings\globals\localforage\index.d.ts" />
<TypeScriptCompile Include="typings\globals\lru-cache\index.d.ts" />
<TypeScriptCompile Include="typings\globals\marked\index.d.ts" />
@ -691,10 +696,13 @@
<TypeScriptCompile Include="typings\globals\object-assign\index.d.ts" />
<TypeScriptCompile Include="typings\globals\once\index.d.ts" />
<TypeScriptCompile Include="typings\globals\passport\index.d.ts" />
<TypeScriptCompile Include="typings\globals\pg-pool\index.d.ts" />
<TypeScriptCompile Include="typings\globals\split2\index.d.ts" />
<TypeScriptCompile Include="typings\globals\sprintf-js\index.d.ts" />
<TypeScriptCompile Include="typings\globals\type-check\index.d.ts" />
<TypeScriptCompile Include="typings\globals\underscore\index.d.ts" />
<TypeScriptCompile Include="typings\globals\uuid\index.d.ts" />
<TypeScriptCompile Include="typings\globals\window-size\index.d.ts" />
<TypeScriptCompile Include="typings\index.d.ts" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />

53
db.js
View File

@ -230,7 +230,7 @@ module.exports.CreateDB = function (parent, func) {
// TODO: Remove all meshes that dont have any links
// Remove all events, power events and SMBIOS data from the main collection. They are all in seperate collections now.
if ((obj.databaseType == 4) || (obj.databaseType == 5)) {
if ((obj.databaseType == 4) || (obj.databaseType == 5) || (obj.databaseType == 6)) {
// MariaDB or MySQL
obj.RemoveAllOfType('event', function () { });
obj.RemoveAllOfType('power', function () { });
@ -640,6 +640,43 @@ module.exports.CreateDB = function (parent, func) {
});
setTimeout(function () { tempDatastore.end(); }, 2000);
}
} else if (parent.args.postgres) {
// Postgres SQL
var connectinArgs = parent.args.postgres;
var dbname = (connectinArgs.database != null) ? connectinArgs.database : 'meshcentral';
obj.databaseType = 6;
const pgtools = require('pgtools');
pgtools.createdb(connectinArgs, dbname, function (err, res) {
const { Pool, Client } = require('pg');
connectinArgs.database = dbname;
Datastore = new Client(connectinArgs);
Datastore.connect()
parent.debug('db', 'Checking tables...');
sqlDbBatchExec([
'CREATE TABLE IF NOT EXISTS main (id VARCHAR(256) PRIMARY KEY NOT NULL, type CHAR(32), domain CHAR(64), extra CHAR(255), extraex CHAR(255), doc JSON)',
'CREATE TABLE IF NOT EXISTS events(id SERIAL PRIMARY KEY, time TIMESTAMP, domain CHAR(64), action CHAR(255), nodeid CHAR(255), userid CHAR(255), doc JSON)',
'CREATE TABLE IF NOT EXISTS eventids(fkid INT NOT NULL, target CHAR(255), CONSTRAINT fk_eventid FOREIGN KEY (fkid) REFERENCES events (id) ON DELETE CASCADE ON UPDATE RESTRICT)',
'CREATE TABLE IF NOT EXISTS serverstats (time TIMESTAMP PRIMARY KEY, expire TIMESTAMP, doc JSON)',
'CREATE TABLE IF NOT EXISTS power (id SERIAL PRIMARY KEY, time TIMESTAMP, nodeid CHAR(255), doc JSON)',
'CREATE TABLE IF NOT EXISTS smbios (id CHAR(255) PRIMARY KEY, time TIMESTAMP, expire TIMESTAMP, doc JSON)',
'CREATE TABLE IF NOT EXISTS plugin (id SERIAL PRIMARY KEY, doc JSON)'
], function (results) {
parent.debug('db', 'Checking indexes...');
sqlDbExec('CREATE INDEX ndxtypedomainextra ON main (type, domain, extra)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxextra ON main (extra)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxextraex ON main (extraex)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxeventstime ON events(time)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxeventsusername ON events(domain, userid, time)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxeventsdomainnodeidtime ON events(domain, nodeid, time)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxeventids ON eventids(target)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxserverstattime ON serverstats (time)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxserverstatexpire ON serverstats (expire)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxpowernodeidtime ON power (nodeid, time)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxsmbiostime ON smbios (time)', null, function (err, response) { });
sqlDbExec('CREATE INDEX ndxsmbiosexpire ON smbios (expire)', null, function (err, response) { });
setupFunctions(func);
});
});
} else if (parent.args.mongodb) {
// Use MongoDB
obj.databaseType = 3;
@ -1011,12 +1048,12 @@ module.exports.CreateDB = function (parent, func) {
.then(function (rows) {
conn.release();
const docs = [];
for (var i in rows) { if (rows[i].doc) { docs.push(performTypedRecordDecrypt((typeof rows[i].doc == 'object')? rows[i].doc : JSON.parse(rows[i].doc))); } }
for (var i in rows) { if (rows[i].doc) { docs.push(performTypedRecordDecrypt((typeof rows[i].doc == 'object') ? rows[i].doc : JSON.parse(rows[i].doc))); } }
if (func) try { func(null, docs); } catch (ex) { console.log('SQLERR1', ex); }
})
.catch(function (err) { conn.release(); if (func) try { func(err); } catch (ex) { console.log('SQLERR2', ex); } });
}).catch(function (err) { if (func) { try { func(err); } catch (ex) { console.log('SQLERR3', ex); } } });
} else if (obj.databaseType == 5) { // MySQL
} else if ((obj.databaseType == 5) || (obj.databaseType == 6)) { // MySQL or Postgres SQL
Datastore.query(query, args, function (error, results, fields) {
if (error != null) {
if (func) try { func(error); } catch (ex) { console.log('SQLERR4', ex); }
@ -1041,10 +1078,10 @@ module.exports.CreateDB = function (parent, func) {
if (func) try { func(null, rows[0]); } catch (ex) { console.log(ex); }
})
.catch(function (err) { conn.release(); if (func) try { func(err); } catch (ex) { console.log(ex); } });
}).catch(function (err) { if (func) { try { func(err); } catch (ex) { console.log(ex); } } });
} else if (obj.databaseType == 5) { // MySQL
}).catch(function (err) { if (func) { try { func(err); } catch (ex) { console.log(ex); } } });
} else if ((obj.databaseType == 5) || (obj.databaseType == 6)) { // MySQL or Postgres SQL
Datastore.query(query, args, function (error, results, fields) {
if (func) try { func(error, results?results[0]:null); } catch (ex) { console.log(ex); }
if (func) try { func(error, results ? results[0] : null); } catch (ex) { console.log(ex); }
});
}
}
@ -1061,7 +1098,7 @@ module.exports.CreateDB = function (parent, func) {
.catch(function (err) { conn.release(); if (func) { try { func(err); } catch (ex) { console.log(ex); } } });
})
.catch(function (err) { if (func) { try { func(err); } catch (ex) { console.log(ex); } } });
} else if (obj.databaseType == 5) { // MySQL
} else if ((obj.databaseType == 5) || (obj.databaseType == 6)) { // MySQL or Postgres SQL
var Promises = [];
for (var i in queries) { if (typeof queries[i] == 'string') { Promises.push(Datastore.query(queries[i])); } else { Promises.push(Datastore.query(queries[i][0], queries[i][1])); } }
Promise.all(Promises)
@ -1071,7 +1108,7 @@ module.exports.CreateDB = function (parent, func) {
}
function setupFunctions(func) {
if ((obj.databaseType == 4) || (obj.databaseType == 5)) {
if ((obj.databaseType == 4) || (obj.databaseType == 5) || (obj.databaseType == 6)) {
// Database actions on the main collection (MariaDB or MySQL)
obj.Set = function (value, func) {
obj.dbCounters.fileSet++;

View File

@ -3341,6 +3341,7 @@ function mainStart() {
if (config.settings.mysql != null) { modules.push('mysql'); } // Add MySQL.
//if (config.settings.mysql != null) { modules.push('@mysql/xdevapi'); } // Add MySQL, official driver (https://dev.mysql.com/doc/dev/connector-nodejs/8.0/)
if (config.settings.mongodb != null) { modules.push('mongodb@4.1.0'); modules.push('saslprep'); } // Add MongoDB, official driver.
if (config.settings.postgres != null) { modules.push('pg@8.7.1'); modules.push('pgtools@0.3.2'); } // Add Postgres, Postgres driver.
if (config.settings.mariadb != null) { modules.push('mariadb'); } // Add MariaDB, official driver.
if (config.settings.vault != null) { modules.push('node-vault'); } // Add official HashiCorp's Vault module.
if (config.settings.plugins != null) { modules.push('semver'); } // Required for version compat testing and update checks

View File

@ -36,6 +36,9 @@
"sample-config-advanced.json"
],
"dependencies": {
"@yetzt/nedb": "^1.8.0",
"archiver": "^4.0.2",
"archiver-zip-encrypted": "^1.0.10",
"body-parser": "^1.19.0",
"cbor": "~5.2.0",
"compression": "^1.7.4",
@ -43,13 +46,24 @@
"express": "^4.17.0",
"express-handlebars": "^3.1.0",
"express-ws": "^4.0.0",
"image-size": "^1.0.0",
"ipcheck": "^0.1.0",
"loadavg-windows": "^1.1.1",
"minimist": "^1.2.5",
"mongodb": "^4.1.0",
"multiparty": "^4.2.1",
"@yetzt/nedb": "^1.8.0",
"node-forge": "^0.10.0",
"node-rdpjs-2": "^0.3.5",
"node-windows": "^0.1.4",
"otplib": "^10.2.3",
"pg": "^8.7.1",
"pgtools": "^0.3.2",
"saslprep": "^1.0.3",
"ssh2": "^1.5.0",
"web-push": "^3.4.5",
"ws": "^5.2.3",
"yauzl": "^2.10.0"
"yauzl": "^2.10.0",
"yubikeyotp": "^0.2.0"
},
"repository": {
"type": "git",