mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
Added database merge feature.
This commit is contained in:
parent
2cab56f4ad
commit
45a50db52c
@ -425,7 +425,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
var adminUser = obj.parent.users['user/' + domain.id + '/' + obj.domain.orphanagentuser.toLowerCase()];
|
var adminUser = obj.parent.users['user/' + domain.id + '/' + obj.domain.orphanagentuser.toLowerCase()];
|
||||||
if ((adminUser != null) && (adminUser.siteadmin == 0xFFFFFFFF)) {
|
if ((adminUser != null) && (adminUser.siteadmin == 0xFFFFFFFF)) {
|
||||||
// Mesh name is hex instead of base64
|
// Mesh name is hex instead of base64
|
||||||
var meshname = Buffer.from(obj.meshid, 'base64').toString('hex').substring(0, 18);
|
var meshname = obj.meshid.substring(0, 18);
|
||||||
|
|
||||||
// Create a new mesh for this device
|
// Create a new mesh for this device
|
||||||
var links = {};
|
var links = {};
|
||||||
|
@ -96,7 +96,7 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
try { require('./pass').hash('test', function () { }); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not.
|
||||||
|
|
||||||
// Check for invalid arguments
|
// Check for invalid arguments
|
||||||
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'configkey', 'loadconfigfromdb'];
|
var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'shownodes', 'showmeshes', 'showevents', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpsdebug', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbmerge', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'swarmdebug', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'configkey', 'loadconfigfromdb'];
|
||||||
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
|
for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } }
|
||||||
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
|
if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; }
|
||||||
for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
|
for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence.
|
||||||
@ -353,7 +353,7 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
// Import the entire database from a JSON file
|
// Import the entire database from a JSON file
|
||||||
if (obj.args.dbimport == true) { obj.args.dbimport = obj.getConfigFilePath('meshcentral.db.json'); }
|
if (obj.args.dbimport == true) { obj.args.dbimport = obj.getConfigFilePath('meshcentral.db.json'); }
|
||||||
var json = null, json2 = "", badCharCount = 0;
|
var json = null, json2 = "", badCharCount = 0;
|
||||||
try { json = obj.fs.readFileSync(obj.args.dbimport, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbimport + '.'); process.exit(); }
|
try { json = obj.fs.readFileSync(obj.args.dbimport, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
||||||
for (i = 0; i < json.length; i++) { if (json.charCodeAt(i) >= 32) { json2 += json[i]; } else { var tt = json.charCodeAt(i); if (tt != 10 && tt != 13) { badCharCount++; } } } // Remove all bad chars
|
for (i = 0; i < json.length; i++) { if (json.charCodeAt(i) >= 32) { json2 += json[i]; } else { var tt = json.charCodeAt(i); if (tt != 10 && tt != 13) { badCharCount++; } } } // Remove all bad chars
|
||||||
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
|
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
|
||||||
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbimport + ': ' + e); process.exit(); }
|
||||||
@ -363,6 +363,63 @@ function CreateMeshCentralServer(config, args) {
|
|||||||
obj.db.RemoveAll(function () { obj.db.InsertMany(json, function (err) { if (err != null) { console.log(err); } else { console.log('Imported ' + json.length + ' objects(s) from ' + obj.args.dbimport + '.'); } process.exit(); }); });
|
obj.db.RemoveAll(function () { obj.db.InsertMany(json, function (err) { if (err != null) { console.log(err); } else { console.log('Imported ' + json.length + ' objects(s) from ' + obj.args.dbimport + '.'); } process.exit(); }); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (obj.args.dbmerge) {
|
||||||
|
// Import the entire database from a JSON file
|
||||||
|
if (obj.args.dbmerge == true) { obj.args.dbmerge = obj.getConfigFilePath('meshcentral.db.json'); }
|
||||||
|
var json = null, json2 = "", badCharCount = 0;
|
||||||
|
try { json = obj.fs.readFileSync(obj.args.dbmerge, { encoding: 'utf8' }); } catch (e) { console.log('Invalid JSON file: ' + obj.args.dbmerge + ': ' + e); process.exit(); }
|
||||||
|
for (i = 0; i < json.length; i++) { if (json.charCodeAt(i) >= 32) { json2 += json[i]; } else { var tt = json.charCodeAt(i); if (tt != 10 && tt != 13) { badCharCount++; } } } // Remove all bad chars
|
||||||
|
if (badCharCount > 0) { console.log(badCharCount + ' invalid character(s) where removed.'); }
|
||||||
|
try { json = JSON.parse(json2); } catch (e) { console.log('Invalid JSON format: ' + obj.args.dbmerge + ': ' + e); process.exit(); }
|
||||||
|
if ((json == null) || (typeof json.length != 'number') || (json.length < 1)) { console.log('Invalid JSON format: ' + obj.args.dbimport + '.'); }
|
||||||
|
|
||||||
|
// Get all users from current database
|
||||||
|
obj.db.GetAllType('user', function (err, docs) {
|
||||||
|
var users = {}, usersCount = 0;
|
||||||
|
for (var i in docs) { users[docs[i]._id] = docs[i]; usersCount++; }
|
||||||
|
|
||||||
|
// Fetch all meshes from the database
|
||||||
|
obj.db.GetAllType('mesh', function (err, docs) {
|
||||||
|
obj.common.unEscapeAllLinksFieldName(docs);
|
||||||
|
var meshes = {}, meshesCount = 0;
|
||||||
|
for (var i in docs) { meshes[docs[i]._id] = docs[i]; meshesCount++; }
|
||||||
|
console.log('Loaded ' + usersCount + ' users and ' + meshesCount + ' meshes.');
|
||||||
|
// Look at each object in the import file
|
||||||
|
var objectToAdd = [];
|
||||||
|
for (var i in json) {
|
||||||
|
var newobj = json[i];
|
||||||
|
if (newobj.type == 'user') {
|
||||||
|
// Check if the user already exists
|
||||||
|
var existingUser = users[newobj._id];
|
||||||
|
if (existingUser) {
|
||||||
|
// Merge the links
|
||||||
|
for (var j in newobj.links) {
|
||||||
|
if ((existingUser.links == null) || (existingUser.links[j] == null)) {
|
||||||
|
if (existingUser.links == null) { existingUser.links = {}; }
|
||||||
|
existingUser.links[j] = newobj.links[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (existingUser.name == 'admin') { existingUser.links = {}; }
|
||||||
|
objectToAdd.push(existingUser); // Add this user
|
||||||
|
} else {
|
||||||
|
objectToAdd.push(newobj); // Add this user
|
||||||
|
}
|
||||||
|
} else if (newobj.type == 'mesh') {
|
||||||
|
// Add this object after escaping
|
||||||
|
objectToAdd.push(obj.common.escapeLinksFieldName(newobj));
|
||||||
|
} // Don't add nodes.
|
||||||
|
}
|
||||||
|
console.log('Importing ' + objectToAdd.length + ' object(s)...');
|
||||||
|
var pendingCalls = 1;
|
||||||
|
for (var i in objectToAdd) {
|
||||||
|
pendingCalls++;
|
||||||
|
obj.db.Set(objectToAdd[i], function (err) { if (err != null) { console.log(err); } else { if (--pendingCalls == 0) { process.exit(); } } });
|
||||||
|
}
|
||||||
|
if (--pendingCalls == 0) { process.exit(); }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Load configuration for database if needed
|
// Load configuration for database if needed
|
||||||
if (obj.args.loadconfigfromdb) {
|
if (obj.args.loadconfigfromdb) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.2.8-l",
|
"version": "0.2.8-m",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
@ -38,6 +38,7 @@
|
|||||||
"ipcheck": "^0.1.0",
|
"ipcheck": "^0.1.0",
|
||||||
"meshcentral": "*",
|
"meshcentral": "*",
|
||||||
"minimist": "^1.2.0",
|
"minimist": "^1.2.0",
|
||||||
|
"mongojs": "^2.6.0",
|
||||||
"multiparty": "^4.2.1",
|
"multiparty": "^4.2.1",
|
||||||
"nedb": "^1.8.0",
|
"nedb": "^1.8.0",
|
||||||
"node-forge": "^0.7.6",
|
"node-forge": "^0.7.6",
|
||||||
|
25
webserver.js
25
webserver.js
@ -177,7 +177,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
|
|
||||||
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||||
//function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, ''').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
//function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, ''').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||||
|
|
||||||
// Fetch all users from the database, keep this in memory
|
// Fetch all users from the database, keep this in memory
|
||||||
obj.db.GetAllType('user', function (err, docs) {
|
obj.db.GetAllType('user', function (err, docs) {
|
||||||
var domainUserCount = {}, i = 0;
|
var domainUserCount = {}, i = 0;
|
||||||
@ -2188,6 +2187,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
res.removeHeader("X-Powered-By");
|
res.removeHeader("X-Powered-By");
|
||||||
var domain = req.xdomain = getDomain(req);
|
var domain = req.xdomain = getDomain(req);
|
||||||
|
|
||||||
|
// If this domain has configured headers, use them.
|
||||||
|
// Example headers: { 'Strict-Transport-Security': 'max-age=360000;includeSubDomains' };
|
||||||
|
// { 'Referrer-Policy': 'no-referrer', 'x-frame-options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'Content-Security-Policy': "default-src http: ws: data: 'self';script-src http: 'unsafe-inline';style-src http: 'unsafe-inline'" };
|
||||||
|
if ((domain != null) && (domain.httpheaders != null) && (typeof domain.httpheaders == object)) { res.set(domain.httpheaders); }
|
||||||
|
|
||||||
// Detect if this is a file sharing domain, if so, just share files.
|
// Detect if this is a file sharing domain, if so, just share files.
|
||||||
if ((domain != null) && (domain.share != null)) {
|
if ((domain != null) && (domain.share != null)) {
|
||||||
var rpath;
|
var rpath;
|
||||||
@ -2200,24 +2204,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
obj.fs.exists(obj.path.join(domain.share, rpath), function (exists) { if (exists == true) { res.sendfile(rpath, { root: domain.share }); } else { res.sendStatus(404); } });
|
obj.fs.exists(obj.path.join(domain.share, rpath), function (exists) { if (exists == true) { res.sendfile(rpath, { root: domain.share }); } else { res.sendStatus(404); } });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Two more headers to take a look at:
|
//if (parent.config.settings.accesscontrolalloworigin != null) { headers['Access-Control-Allow-Origin'] = parent.config.settings.accesscontrolalloworigin; }
|
||||||
// 'Public-Key-Pins': 'pin-sha256="X3pGTSOuJeEVw989IJ/cEtXUEmy52zs1TZQrU06KUKg="; max-age=10'
|
|
||||||
// 'strict-transport-security': 'max-age=31536000; includeSubDomains'
|
|
||||||
var headers = null;
|
|
||||||
if (isTrustedCert() == false) {
|
|
||||||
// Default headers if no TLS is used
|
|
||||||
//headers = { 'Referrer-Policy': 'no-referrer', 'x-frame-options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'Content-Security-Policy': "default-src http: ws: data: 'self';script-src http: 'unsafe-inline';style-src http: 'unsafe-inline'" };
|
|
||||||
} else {
|
|
||||||
// Default headers if TLS is used
|
|
||||||
//headers = { 'Referrer-Policy': 'no-referrer', 'x-frame-options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'Content-Security-Policy': "default-src https: wss: data: 'self';script-src https: 'unsafe-inline';style-src https: 'unsafe-inline'" };
|
|
||||||
|
|
||||||
if (typeof obj.args.httpsstrict == 'number') {
|
|
||||||
// Set Strict-Transport-Security if we are using a trusted certificate or TLS offload.
|
|
||||||
headers = { 'Strict-Transport-Security': 'max-age=' + obj.args.httpsstrict + ';includeSubDomains' };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (parent.config.settings.accesscontrolalloworigin != null) { headers['Access-Control-Allow-Origin'] = parent.config.settings.accesscontrolalloworigin; }
|
|
||||||
res.set(headers);
|
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user