mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 06:05:53 -05:00
Bug fixes and fixed database performance problem.
This commit is contained in:
parent
b7df070bd2
commit
b824499b40
47
db.js
47
db.js
@ -41,6 +41,13 @@ module.exports.CreateDB = function (parent) {
|
|||||||
var dbcollection = 'meshcentral';
|
var dbcollection = 'meshcentral';
|
||||||
if (obj.parent.args.mongodbcol) { dbcollection = obj.parent.args.mongodbcol; }
|
if (obj.parent.args.mongodbcol) { dbcollection = obj.parent.args.mongodbcol; }
|
||||||
obj.file = db.collection(dbcollection);
|
obj.file = db.collection(dbcollection);
|
||||||
|
|
||||||
|
// Setup MongoDB indexes
|
||||||
|
obj.file.createIndex({ type: 1, domain: 1, meshid: 1 }, { sparse: 1 }); // Speeds up GetAllTypeNoTypeField() and GetAllTypeNoTypeFieldMeshFiltered()
|
||||||
|
obj.file.createIndex({ email: 1 }, { sparse: 1 }); // Speeds up GetUserWithEmail() and GetUserWithVerifiedEmail()
|
||||||
|
obj.file.createIndex({ ids: 1, time: -1 }, { sparse: 1 }); // Speeds up GetEvents() and GetEventsWithLimit()
|
||||||
|
obj.file.createIndex({ type: 1, node: 1, time: -1 }, { sparse: 1 }); // Speeds up getPowerTimeline()
|
||||||
|
obj.file.createIndex({ mesh: 1 }, { sparse: 1 }); // Speeds up RemoveMesh()
|
||||||
} else {
|
} else {
|
||||||
// Use NeDB (The default)
|
// Use NeDB (The default)
|
||||||
obj.databaseType = 1;
|
obj.databaseType = 1;
|
||||||
@ -72,6 +79,13 @@ module.exports.CreateDB = function (parent) {
|
|||||||
// Start NeDB
|
// Start NeDB
|
||||||
obj.file = new Datastore(datastoreOptions);
|
obj.file = new Datastore(datastoreOptions);
|
||||||
obj.file.persistence.setAutocompactionInterval(3600);
|
obj.file.persistence.setAutocompactionInterval(3600);
|
||||||
|
|
||||||
|
// Setup NeDB indexes
|
||||||
|
obj.file.ensureIndex({ fieldName: 'type' });
|
||||||
|
obj.file.ensureIndex({ fieldName: 'domain' });
|
||||||
|
obj.file.ensureIndex({ fieldName: 'meshid' });
|
||||||
|
obj.file.ensureIndex({ fieldName: 'node' });
|
||||||
|
obj.file.ensureIndex({ fieldName: 'email' });
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.SetupDatabase = function (func) {
|
obj.SetupDatabase = function (func) {
|
||||||
@ -232,27 +246,30 @@ module.exports.CreateDB = function (parent) {
|
|||||||
} catch (ex) { return null; }
|
} catch (ex) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the number of records in the database for various types, this is the slow NeDB way. TODO: MongoDB can use group() to do this faster.
|
// Get the number of records in the database for various types, this is the slow NeDB way.
|
||||||
|
// WARNING: This is a terrible query for database performance. Only do this when needed. This query will look at almost every document in the database.
|
||||||
obj.getStats = function (func) {
|
obj.getStats = function (func) {
|
||||||
obj.file.count({ type: 'node' }, function (err, nodeCount) {
|
if (obj.databaseType == 2) {
|
||||||
obj.file.count({ type: 'mesh' }, function (err, meshCount) {
|
// MongoDB version
|
||||||
obj.file.count({ type: 'power' }, function (err, powerCount) {
|
obj.file.aggregate([{ "$group": { _id: "$type", count: { $sum: 1 } } }], function (err, docs) {
|
||||||
obj.file.count({ type: 'user' }, function (err, userCount) {
|
var counters = {}, totalCount = 0;
|
||||||
obj.file.count({ type: 'ifinfo' }, function (err, nodeInterfaceCount) {
|
for (var i in docs) { if (docs[i]._id != null) { counters[docs[i]._id] = docs[i].count; totalCount += docs[i].count; } }
|
||||||
obj.file.count({ type: 'note' }, function (err, noteCount) {
|
func({ nodes: counters['node'], meshes: counters['mesh'], powerEvents: counters['power'], users: counters['user'], total: totalCount });
|
||||||
obj.file.count({ type: 'smbios' }, function (err, nodeSmbiosCount) {
|
})
|
||||||
obj.file.count({ type: 'lastconnect' }, function (err, nodeLastConnectCount) {
|
} else {
|
||||||
obj.file.count({ }, function (err, totalCount) {
|
// NeDB version
|
||||||
func({ nodes: nodeCount, meshes: meshCount, powerEvents: powerCount, users: userCount, nodeInterfaces: nodeInterfaceCount, notes: noteCount, connectEvent: nodeLastConnectCount, smbios: nodeSmbiosCount, total: totalCount });
|
obj.file.count({ type: 'node' }, function (err, nodeCount) {
|
||||||
});
|
obj.file.count({ type: 'mesh' }, function (err, meshCount) {
|
||||||
});
|
obj.file.count({ type: 'power' }, function (err, powerCount) {
|
||||||
});
|
obj.file.count({ type: 'user' }, function (err, userCount) {
|
||||||
|
obj.file.count({}, function (err, totalCount) {
|
||||||
|
func({ nodes: nodeCount, meshes: meshCount, powerEvents: powerCount, users: userCount, nodeInterfaces: nodeInterfaceCount, notes: noteCount, connectEvent: nodeLastConnectCount, smbios: nodeSmbiosCount, total: totalCount });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used to rate limit a number of operation per day. Returns a startValue each new days, but you can substract it and save the value in the db.
|
// This is used to rate limit a number of operation per day. Returns a startValue each new days, but you can substract it and save the value in the db.
|
||||||
|
91
meshuser.js
91
meshuser.js
@ -178,15 +178,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
|
|
||||||
// Send current server statistics
|
// Send current server statistics
|
||||||
obj.SendServerStats = function () {
|
obj.SendServerStats = function () {
|
||||||
obj.db.getStats(function (data) {
|
var os = require('os');
|
||||||
var os = require('os');
|
var stats = { action: 'serverstats', totalmem: os.totalmem(), freemem: os.freemem() };
|
||||||
var stats = { action: 'serverstats', totalmem: os.totalmem(), freemem: os.freemem() };
|
if (obj.parent.parent.platform != 'win32') { stats.cpuavg = os.loadavg(); } // else { stats.cpuavg = [ 0.2435345, 0.523234234, 0.6435345345 ]; }
|
||||||
if (obj.parent.parent.platform != 'win32') { stats.cpuavg = os.loadavg(); } // else { stats.cpuavg = [ 0.2435345, 0.523234234, 0.6435345345 ]; }
|
var serverStats = { "User Accounts": Object.keys(obj.parent.users).length, "Device Groups": Object.keys(obj.parent.meshes).length, "Connected Agents": Object.keys(obj.parent.wsagents).length, "Connected Users": Object.keys(obj.parent.wssessions2).length };
|
||||||
var serverStats = { "User Accounts": Object.keys(obj.parent.users).length, "Device Groups": Object.keys(obj.parent.meshes).length, "Connected Agents": Object.keys(obj.parent.wsagents).length, "Connected Users": Object.keys(obj.parent.wssessions2).length };
|
if (obj.parent.parent.mpsserver != null) { serverStats['Connected Intel® AMT'] = Object.keys(obj.parent.parent.mpsserver.ciraConnections).length; }
|
||||||
if (obj.parent.parent.mpsserver != null) { serverStats['Connected Intel® AMT'] = Object.keys(obj.parent.parent.mpsserver.ciraConnections).length; }
|
stats.values = { "Server State": serverStats }
|
||||||
stats.values = { "Server State": serverStats, "Database": { "Records": data.total, "Users": data.users, "Device Groups": data.meshes, "Devices": data.nodes, "Device NetInfo": data.nodeInterfaces, "Device Power Event": data.powerEvents, "Notes": data.notes, "Connection Records": data.connectEvents, "SMBios": data.smbios } }
|
try { ws.send(JSON.stringify(stats)); } catch (ex) { }
|
||||||
try { ws.send(JSON.stringify(stats)); } catch (ex) { }
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When data is received from the web socket
|
// When data is received from the web socket
|
||||||
@ -256,7 +254,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
}
|
}
|
||||||
case 'serverstats':
|
case 'serverstats':
|
||||||
{
|
{
|
||||||
if ((user.siteadmin) != 0) {
|
if ((user.siteadmin & 21) != 0) { // Only site administrators with "site backup" or "site restore" or "site update" permissions can use this.
|
||||||
if (obj.common.validateInt(command.interval, 1000, 1000000) == false) {
|
if (obj.common.validateInt(command.interval, 1000, 1000000) == false) {
|
||||||
// Clear the timer
|
// Clear the timer
|
||||||
if (obj.serverStatsTimer != null) { clearInterval(obj.serverStatsTimer); obj.serverStatsTimer = null; }
|
if (obj.serverStatsTimer != null) { clearInterval(obj.serverStatsTimer); obj.serverStatsTimer = null; }
|
||||||
@ -1438,38 +1436,65 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
}
|
}
|
||||||
case 'uploadagentcore':
|
case 'uploadagentcore':
|
||||||
{
|
{
|
||||||
if (user.siteadmin != 0xFFFFFFFF) break;
|
|
||||||
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
if (obj.common.validateString(command.type, 1, 40) == false) break; // Check path
|
if (obj.common.validateString(command.type, 1, 40) == false) break; // Check path
|
||||||
if (command.type == 'default') {
|
|
||||||
// Send the default core to the agent
|
// Change the device
|
||||||
obj.parent.parent.updateMeshCore(function () { obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'default'); });
|
obj.db.Get(command.nodeid, function (err, nodes) {
|
||||||
} else if (command.type == 'clear') {
|
if (nodes.length != 1) return;
|
||||||
// Clear the mesh agent core on the mesh agent
|
var node = nodes[0];
|
||||||
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'clear');
|
|
||||||
} else if (command.type == 'recovery') {
|
// Get the mesh for this device
|
||||||
// Send the recovery core to the agent
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'recovery');
|
if (mesh) {
|
||||||
} else if ((command.type == 'custom') && (obj.common.validateString(command.path, 1, 2048) == true)) {
|
// Check if this user has rights to do this
|
||||||
// Send a mesh agent core to the mesh agent
|
if (mesh.links[user._id] == null || (((mesh.links[user._id].rights & 16) == 0) && (user.siteadmin != 0xFFFFFFFF))) { return; }
|
||||||
var file = obj.parent.getServerFilePath(user, domain, command.path);
|
|
||||||
if (file != null) {
|
if (command.type == 'default') {
|
||||||
obj.parent.parent.fs.readFile(file.fullpath, 'utf8', function (err, data) {
|
// Send the default core to the agent
|
||||||
if (err != null) {
|
obj.parent.parent.updateMeshCore(function () { obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'default'); });
|
||||||
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
|
} else if (command.type == 'clear') {
|
||||||
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'custom', data);
|
// Clear the mesh agent core on the mesh agent
|
||||||
|
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'clear');
|
||||||
|
} else if (command.type == 'recovery') {
|
||||||
|
// Send the recovery core to the agent
|
||||||
|
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'recovery');
|
||||||
|
} else if ((command.type == 'custom') && (obj.common.validateString(command.path, 1, 2048) == true)) {
|
||||||
|
// Send a mesh agent core to the mesh agent
|
||||||
|
var file = obj.parent.getServerFilePath(user, domain, command.path);
|
||||||
|
if (file != null) {
|
||||||
|
obj.parent.parent.fs.readFile(file.fullpath, 'utf8', function (err, data) {
|
||||||
|
if (err != null) {
|
||||||
|
data = obj.common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
|
||||||
|
obj.parent.sendMeshAgentCore(user, domain, command.nodeid, 'custom', data);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'agentdisconnect':
|
case 'agentdisconnect':
|
||||||
{
|
{
|
||||||
// Force mesh agent disconnection
|
|
||||||
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||||
if (obj.common.validateInt(command.disconnectMode) == false) break; // Check disconnect mode
|
if (obj.common.validateInt(command.disconnectMode) == false) return; // Check disconnect mode
|
||||||
obj.parent.forceMeshAgentDisconnect(user, domain, command.nodeid, command.disconnectMode);
|
|
||||||
|
// Change the device
|
||||||
|
obj.db.Get(command.nodeid, function (err, nodes) {
|
||||||
|
if (nodes.length != 1) return;
|
||||||
|
var node = nodes[0];
|
||||||
|
|
||||||
|
// Get the mesh for this device
|
||||||
|
mesh = obj.parent.meshes[node.meshid];
|
||||||
|
if (mesh) {
|
||||||
|
// Check if this user has rights to do this
|
||||||
|
if (mesh.links[user._id] == null || (((mesh.links[user._id].rights & 16) == 0) && (user.siteadmin != 0xFFFFFFFF))) return;
|
||||||
|
|
||||||
|
// Force mesh agent disconnection
|
||||||
|
obj.parent.forceMeshAgentDisconnect(user, domain, command.nodeid, command.disconnectMode);
|
||||||
|
}
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'close':
|
case 'close':
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.2.8-m",
|
"version": "0.2.8-o",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -3539,7 +3539,7 @@
|
|||||||
QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8));
|
QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8));
|
||||||
QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
|
QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
|
||||||
QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
|
QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
|
||||||
QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0) && (userinfo.siteadmin == 0xFFFFFFFF));
|
QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0));
|
||||||
QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
|
QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
|
||||||
|
|
||||||
// Setup/Refresh Intel AMT tab
|
// Setup/Refresh Intel AMT tab
|
||||||
|
@ -2411,7 +2411,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
|
|
||||||
// Check we have agent rights
|
// Check we have agent rights
|
||||||
var rights = user.links[agent.dbMeshKey].rights;
|
var rights = user.links[agent.dbMeshKey].rights;
|
||||||
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); }
|
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send the core module to the mesh agent
|
// Send the core module to the mesh agent
|
||||||
@ -2426,7 +2426,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
|
|
||||||
// Check we have agent rights
|
// Check we have agent rights
|
||||||
var rights = user.links[agent.dbMeshKey].rights;
|
var rights = user.links[agent.dbMeshKey].rights;
|
||||||
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) && (user.siteadmin == 0xFFFFFFFF)) {
|
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) {
|
||||||
if (coretype == 'clear') {
|
if (coretype == 'clear') {
|
||||||
// Clear the mesh agent core
|
// Clear the mesh agent core
|
||||||
agent.agentCoreCheck = 1000; // Tell the agent object we are using a custom core.
|
agent.agentCoreCheck = 1000; // Tell the agent object we are using a custom core.
|
||||||
|
Loading…
Reference in New Issue
Block a user