Fixed user account delete with user manager.

This commit is contained in:
Ylian Saint-Hilaire 2020-03-17 17:17:04 -07:00
parent b761fde58e
commit b72f43c119
7 changed files with 217 additions and 156 deletions

View File

@ -72,7 +72,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
db.removeAllPowerEventsForNode(obj.dbNodeKey); // Remove all power events for this node db.removeAllPowerEventsForNode(obj.dbNodeKey); // Remove all power events for this node
// Event node deletion // Event node deletion
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, { etype: 'node', action: 'removenode', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 }); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, { etype: 'node', action: 'removenode', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 });
// Disconnect all connections if needed // Disconnect all connections if needed
const state = parent.parent.GetConnectivityState(obj.dbNodeKey); const state = parent.parent.GetConnectivityState(obj.dbNodeKey);
@ -555,12 +555,12 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if (adminUser.links == null) adminUser.links = {}; if (adminUser.links == null) adminUser.links = {};
adminUser.links[obj.dbMeshKey] = { rights: 0xFFFFFFFF }; adminUser.links[obj.dbMeshKey] = { rights: 0xFFFFFFFF };
db.SetUser(adminUser); db.SetUser(adminUser);
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [adminUser._id]), obj, { etype: 'mesh', username: adminUser.name, meshid: obj.dbMeshKey, name: meshname, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id }); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [adminUser._id, obj.dbNodeKey]), obj, { etype: 'mesh', username: adminUser.name, meshid: obj.dbMeshKey, name: meshname, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id });
} }
} else { } else {
if ((mesh != null) && (mesh.deleted != null) && (mesh.links)) { if ((mesh != null) && (mesh.deleted != null) && (mesh.links)) {
// Must un-delete this mesh // Must un-delete this mesh
var ids = parent.CreateMeshDispatchTargets(mesh._id); var ids = parent.CreateMeshDispatchTargets(mesh._id, [obj.dbNodeKey]);
// See if users still exists, if so, add links to the mesh // See if users still exists, if so, add links to the mesh
for (var userid in mesh.links) { for (var userid in mesh.links) {
@ -640,13 +640,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
mesh = { type: 'mesh', _id: obj.dbMeshKey, name: obj.meshid, mtype: 2, desc: '', domain: domain.id, links: links }; mesh = { type: 'mesh', _id: obj.dbMeshKey, name: obj.meshid, mtype: 2, desc: '', domain: domain.id, links: links };
db.Set(common.escapeLinksFieldName(mesh)); db.Set(common.escapeLinksFieldName(mesh));
parent.meshes[obj.meshid] = mesh; parent.meshes[obj.meshid] = mesh;
parent.parent.AddEventDispatch(parent.CreateMeshDispatchTargets(obj.meshid), ws); parent.parent.AddEventDispatch(parent.CreateMeshDispatchTargets(obj.meshid, [obj.dbNodeKey]), ws);
if (adminUser.links == null) user.links = {}; if (adminUser.links == null) user.links = {};
adminUser.links[obj.meshid] = { rights: 0xFFFFFFFF }; adminUser.links[obj.meshid] = { rights: 0xFFFFFFFF };
//adminUser.subscriptions = parent.subscribe(adminUser._id, ws); //adminUser.subscriptions = parent.subscribe(adminUser._id, ws);
db.SetUser(user); db.SetUser(user);
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(meshid, [user._id]), obj, { etype: 'mesh', username: user.name, meshid: obj.meshid, name: obj.meshid, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id }); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(meshid, [user._id, obj.dbNodeKey]), obj, { etype: 'mesh', username: user.name, meshid: obj.meshid, name: obj.meshid, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id });
} }
} }
@ -741,7 +741,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device) }; var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device) };
if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); }
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event);
} }
} }
@ -781,9 +781,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Event the new node // Event the new node
if (obj.agentInfo.capabilities & 0x20) { if (obj.agentInfo.capabilities & 0x20) {
// This is a temporary agent, don't log. // This is a temporary agent, don't log.
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 }); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 });
} else { } else {
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id }); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id });
} }
completeAgentConnection3(device, mesh); completeAgentConnection3(device, mesh);
@ -1114,7 +1114,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
} catch (ex) { } } catch (ex) { }
// Event the node interface information change (This is a lot of traffic, probably don't need this). // Event the node interface information change (This is a lot of traffic, probably don't need this).
//parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid), obj, { action: 'smBiosChange', nodeid: obj.dbNodeKey, domain: domain.id, smbios: command.value, nolog: 1 }); //parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid, [obj.dbNodeKey]), obj, { action: 'smBiosChange', nodeid: obj.dbNodeKey, domain: domain.id, smbios: command.value, nolog: 1 });
break; break;
} }
@ -1128,7 +1128,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
db.Set(command); db.Set(command);
// Event the node interface information change // Event the node interface information change
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid), obj, { action: 'ifchange', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 }); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid, [obj.dbNodeKey]), obj, { action: 'ifchange', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 });
break; break;
} }
@ -1167,7 +1167,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Event node deletion // Event node deletion
const change = 'Migrated device ' + node.name; const change = 'Migrated device ' + node.name;
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(node.meshid), obj, { etype: 'node', action: 'removenode', nodeid: node._id, msg: change, domain: node.domain }); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(node.meshid, [obj.dbNodeKey]), obj, { etype: 'node', action: 'removenode', nodeid: node._id, msg: change, domain: node.domain });
} }
}); });
break; break;
@ -1183,7 +1183,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Log a value in the event log // Log a value in the event log
if ((typeof command.msg == 'string') && (command.msg.length < 4096)) { if ((typeof command.msg == 'string') && (command.msg.length < 4096)) {
var event = { etype: 'node', action: 'agentlog', nodeid: obj.dbNodeKey, domain: domain.id, msg: command.msg }; var event = { etype: 'node', action: 'agentlog', nodeid: obj.dbNodeKey, domain: domain.id, msg: command.msg };
var targets = parent.CreateMeshDispatchTargets(obj.dbMeshKey); var targets = parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]);
if (typeof command.userid == 'string') { if (typeof command.userid == 'string') {
var loguser = parent.users[command.userid]; var loguser = parent.users[command.userid];
if (loguser) { event.userid = command.userid; event.username = loguser.name; targets.push(command.userid); } if (loguser) { event.userid = command.userid; event.username = loguser.name; targets.push(command.userid); }
@ -1227,7 +1227,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Log this activation event // Log this activation event
var event = { etype: 'node', action: 'amtactivate', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Device requested Intel AMT ACM activation, FQDN: ' + command.fqdn, ip: obj.remoteaddrport }; var event = { etype: 'node', action: 'amtactivate', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Device requested Intel AMT ACM activation, FQDN: ' + command.fqdn, ip: obj.remoteaddrport };
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, event);
// Update the device Intel AMT information // Update the device Intel AMT information
ChangeAgentCoreInfo({ "intelamt": { user: 'admin', pass: amtpassword, uuid: command.uuid, realm: command.realm } }); ChangeAgentCoreInfo({ "intelamt": { user: 'admin', pass: amtpassword, uuid: command.uuid, realm: command.realm } });
@ -1277,7 +1277,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if (((obj.agentInfo.capabilities & 0x40) != 0) && (typeof command.value.value == 'string') && (command.value.value.length < 256)) { if (((obj.agentInfo.capabilities & 0x40) != 0) && (typeof command.value.value == 'string') && (command.value.value.length < 256)) {
// If this is a diagnostic agent, log the event in the log of the main agent // If this is a diagnostic agent, log the event in the log of the main agent
var event = { etype: 'node', action: 'diagnostic', nodeid: obj.realNodeKey, domain: domain.id, msg: command.value.value }; var event = { etype: 'node', action: 'diagnostic', nodeid: obj.realNodeKey, domain: domain.id, msg: command.value.value };
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, event);
} }
break; break;
} }
@ -1295,7 +1295,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Event the new sysinfo hash, this will notify everyone that the sysinfo document was changed // Event the new sysinfo hash, this will notify everyone that the sysinfo document was changed
var event = { etype: 'node', action: 'sysinfohash', nodeid: obj.dbNodeKey, domain: domain.id, hash: command.data.hash, nolog: 1 }; var event = { etype: 'node', action: 'sysinfohash', nodeid: obj.dbNodeKey, domain: domain.id, hash: command.data.hash, nolog: 1 };
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, event);
} }
break; break;
} }
@ -1394,7 +1394,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); }
if ((log == 0) || ((obj.agentInfo) && (obj.agentInfo.capabilities) && (obj.agentInfo.capabilities & 0x20)) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes if ((log == 0) || ((obj.agentInfo) && (obj.agentInfo.capabilities) && (obj.agentInfo.capabilities & 0x20)) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event);
} }
} }
}); });
@ -1435,7 +1435,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), msg: 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', ') }; var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), msg: 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', ') };
if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event);
} }
} }
}); });
@ -1464,7 +1464,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Event the node change // Event the node change
var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), nolog: 1 }; var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), nolog: 1 };
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event);
} }
} }
}); });

View File

@ -1250,7 +1250,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
deluser = parent.users[deluserid]; deluser = parent.users[deluserid];
if (deluser == null) { err = 'User does not exists'; } if (deluser == null) { err = 'User does not exists'; }
else if ((delusersplit.length != 3) || (delusersplit[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain else if ((delusersplit.length != 3) || (delusersplit[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
else if ((deluser.siteadmin != null) && (deluser.siteadmin > 0) && (user.siteadmin != 0xFFFFFFFF)) { err = 'Permission denied'; } // Need full admin to remote another administrator else if ((deluser.siteadmin == 0xFFFFFFFF) && (user.siteadmin != 0xFFFFFFFF)) { err = 'Permission denied'; } // Need full admin to remote another administrator
else if ((user.groups != null) && (user.groups.length > 0) && ((deluser.groups == null) || (findOne(deluser.groups, user.groups) == false))) { err = 'Invalid user group'; } // Can only perform this operation on other users of our group. else if ((user.groups != null) && (user.groups.length > 0) && ((deluser.groups == null) || (findOne(deluser.groups, user.groups) == false))) { err = 'Invalid user group'; } // Can only perform this operation on other users of our group.
} }
} catch (ex) { err = 'Validation exception: ' + ex; } } catch (ex) { err = 'Validation exception: ' + ex; }
@ -2547,7 +2547,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
db.Set(device); db.Set(device);
// Event the new node // Event the new node
parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msg: 'Added device ' + command.devicename + ' to mesh ' + mesh.name, domain: domain.id }); parent.parent.DispatchEvent(['*', command.meshid, nodeid], obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msg: 'Added device ' + command.devicename + ' to mesh ' + mesh.name, domain: domain.id });
}); });
} }
break; break;
@ -2616,7 +2616,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
var newMesh = parent.meshes[command.meshid]; var newMesh = parent.meshes[command.meshid];
var event = { etype: 'node', userid: user._id, username: user.name, action: 'nodemeshchange', nodeid: node._id, node: node, oldMeshId: oldMeshId, newMeshId: command.meshid, msg: 'Moved device ' + node.name + ' to group ' + newMesh.name, domain: domain.id }; var event = { etype: 'node', userid: user._id, username: user.name, action: 'nodemeshchange', nodeid: node._id, node: node, oldMeshId: oldMeshId, newMeshId: command.meshid, msg: 'Moved device ' + node.name + ' to group ' + newMesh.name, domain: domain.id };
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
parent.parent.DispatchEvent(['*', oldMeshId, command.meshid], obj, event); parent.parent.DispatchEvent(['*', oldMeshId, command.meshid, node._id], obj, event);
}); });
} }
break; break;
@ -2648,7 +2648,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
var event = { etype: 'node', userid: user._id, username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from group ' + parent.meshes[node.meshid].name, domain: domain.id }; var event = { etype: 'node', userid: user._id, username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from group ' + parent.meshes[node.meshid].name, domain: domain.id };
// TODO: We can't use the changeStream for node delete because we will not know the meshid the device was in. // TODO: We can't use the changeStream for node delete because we will not know the meshid the device was in.
//if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to remove the node. Another event will come. //if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to remove the node. Another event will come.
parent.parent.DispatchEvent(['*', node.meshid], obj, event); parent.parent.DispatchEvent(['*', node.meshid, node._id], obj, event);
// Disconnect all connections if needed // Disconnect all connections if needed
var state = parent.parent.GetConnectivityState(nodeid); var state = parent.parent.GetConnectivityState(nodeid);
@ -2849,7 +2849,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
event.msg = 'Changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', '); event.msg = 'Changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', ');
event.node = parent.CloneSafeNode(node); event.node = parent.CloneSafeNode(node);
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
parent.parent.DispatchEvent(['*', node.meshid, user._id], obj, event); parent.parent.DispatchEvent(['*', node.meshid, user._id, node._id], obj, event);
} }
}); });
break; break;
@ -2970,7 +2970,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if (rights == 0) return; if (rights == 0) return;
// Add an event for this device // Add an event for this device
var targets = ['*', 'server-users', user._id, node.meshid]; var targets = ['*', 'server-users', user._id, node.meshid, node._id];
var event = { etype: 'node', userid: user._id, username: user.name, nodeid: node._id, action: 'manual', msg: decodeURIComponent(command.msg), domain: domain.id }; var event = { etype: 'node', userid: user._id, username: user.name, nodeid: node._id, action: 'manual', msg: decodeURIComponent(command.msg), domain: domain.id };
parent.parent.DispatchEvent(targets, obj, event); parent.parent.DispatchEvent(targets, obj, event);
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.5.0-i", "version": "0.5.0-j",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

View File

@ -542,7 +542,7 @@
"default-mobile.handlebars->9->246", "default-mobile.handlebars->9->246",
"default-mobile.handlebars->9->70", "default-mobile.handlebars->9->70",
"default.handlebars->27->1233", "default.handlebars->27->1233",
"default.handlebars->27->1469", "default.handlebars->27->1470",
"default.handlebars->27->653" "default.handlebars->27->653"
] ]
}, },
@ -1851,7 +1851,7 @@
"default.handlebars->27->1169", "default.handlebars->27->1169",
"default.handlebars->27->1171", "default.handlebars->27->1171",
"default.handlebars->27->1369", "default.handlebars->27->1369",
"default.handlebars->27->1446", "default.handlebars->27->1447",
"default.handlebars->27->187" "default.handlebars->27->187"
] ]
}, },
@ -1918,7 +1918,7 @@
"nl": "Lidmaatschap toevoegen", "nl": "Lidmaatschap toevoegen",
"ru": "Добавить участие", "ru": "Добавить участие",
"xloc": [ "xloc": [
"default.handlebars->27->1465" "default.handlebars->27->1466"
] ]
}, },
{ {
@ -1964,7 +1964,7 @@
"xloc": [ "xloc": [
"default.handlebars->27->1075", "default.handlebars->27->1075",
"default.handlebars->27->1170", "default.handlebars->27->1170",
"default.handlebars->27->1455" "default.handlebars->27->1456"
] ]
}, },
{ {
@ -2304,7 +2304,7 @@
"nl": "Agent fout tellers", "nl": "Agent fout tellers",
"ru": "Счетчик ошибок агента", "ru": "Счетчик ошибок агента",
"xloc": [ "xloc": [
"default.handlebars->27->1477" "default.handlebars->27->1478"
] ]
}, },
{ {
@ -2350,7 +2350,7 @@
"nl": "Agent Sessies", "nl": "Agent Sessies",
"ru": "Сессии агентов", "ru": "Сессии агентов",
"xloc": [ "xloc": [
"default.handlebars->27->1493" "default.handlebars->27->1494"
] ]
}, },
{ {
@ -2447,7 +2447,7 @@
"pt": "Agentes", "pt": "Agentes",
"ru": "Агенты", "ru": "Агенты",
"xloc": [ "xloc": [
"default.handlebars->27->1506" "default.handlebars->27->1507"
] ]
}, },
{ {
@ -3038,7 +3038,7 @@
"nl": "Weet u zeker dat u de plug-in {0} wilt gebruiken: {1}", "nl": "Weet u zeker dat u de plug-in {0} wilt gebruiken: {1}",
"ru": "Вы уверенны, что {0} плагин: {1}", "ru": "Вы уверенны, что {0} плагин: {1}",
"xloc": [ "xloc": [
"default.handlebars->27->1542" "default.handlebars->27->1543"
] ]
}, },
{ {
@ -3359,7 +3359,7 @@
"nl": "Ongeldige handtening", "nl": "Ongeldige handtening",
"ru": "Плохой ключ", "ru": "Плохой ключ",
"xloc": [ "xloc": [
"default.handlebars->27->1484" "default.handlebars->27->1485"
] ]
}, },
{ {
@ -3370,7 +3370,7 @@
"nl": "Onjuist webcertificaat", "nl": "Onjuist webcertificaat",
"ru": "Плохой веб-сертификат", "ru": "Плохой веб-сертификат",
"xloc": [ "xloc": [
"default.handlebars->27->1483" "default.handlebars->27->1484"
] ]
}, },
{ {
@ -3563,7 +3563,7 @@
"pt": "Servidor CIRA", "pt": "Servidor CIRA",
"ru": "CIRA Сервер", "ru": "CIRA Сервер",
"xloc": [ "xloc": [
"default.handlebars->27->1533" "default.handlebars->27->1534"
] ]
}, },
{ {
@ -3577,7 +3577,7 @@
"pt": "Comandos do servidor CIRA", "pt": "Comandos do servidor CIRA",
"ru": "CIRA Сервер команды", "ru": "CIRA Сервер команды",
"xloc": [ "xloc": [
"default.handlebars->27->1534" "default.handlebars->27->1535"
] ]
}, },
{ {
@ -3588,7 +3588,7 @@
"nl": "CPU gebruik", "nl": "CPU gebruik",
"ru": "Загрузка CPU", "ru": "Загрузка CPU",
"xloc": [ "xloc": [
"default.handlebars->27->1498" "default.handlebars->27->1499"
] ]
}, },
{ {
@ -3602,7 +3602,7 @@
"pt": "Carga da CPU nos últimos 15 minutos", "pt": "Carga da CPU nos últimos 15 minutos",
"ru": "Загрузка CPU за последние 15 минут", "ru": "Загрузка CPU за последние 15 минут",
"xloc": [ "xloc": [
"default.handlebars->27->1501" "default.handlebars->27->1502"
] ]
}, },
{ {
@ -3616,7 +3616,7 @@
"pt": "Carga da CPU nos últimos 5 minutos", "pt": "Carga da CPU nos últimos 5 minutos",
"ru": "Загрузка CPU за последние 5 минут", "ru": "Загрузка CPU за последние 5 минут",
"xloc": [ "xloc": [
"default.handlebars->27->1500" "default.handlebars->27->1501"
] ]
}, },
{ {
@ -3630,7 +3630,7 @@
"pt": "Carga da CPU no último minuto", "pt": "Carga da CPU no último minuto",
"ru": "Загрузка CPU за последнюю минуту", "ru": "Загрузка CPU за последнюю минуту",
"xloc": [ "xloc": [
"default.handlebars->27->1499" "default.handlebars->27->1500"
] ]
}, },
{ {
@ -3676,7 +3676,7 @@
"pt": "Erro de chamada", "pt": "Erro de chamada",
"ru": "Ошибка вызова", "ru": "Ошибка вызова",
"xloc": [ "xloc": [
"default.handlebars->27->1543" "default.handlebars->27->1544"
] ]
}, },
{ {
@ -4018,7 +4018,7 @@
"pt": "Verificando ...", "pt": "Verificando ...",
"ru": "Проверка...", "ru": "Проверка...",
"xloc": [ "xloc": [
"default.handlebars->27->1539", "default.handlebars->27->1540",
"default.handlebars->27->778" "default.handlebars->27->778"
] ]
}, },
@ -4322,7 +4322,7 @@
"ru": "Общие группы устройств", "ru": "Общие группы устройств",
"xloc": [ "xloc": [
"default.handlebars->27->1370", "default.handlebars->27->1370",
"default.handlebars->27->1447" "default.handlebars->27->1448"
] ]
}, },
{ {
@ -4401,6 +4401,12 @@
"default.handlebars->27->380" "default.handlebars->27->380"
] ]
}, },
{
"en": "Confirm deletion of user {0}?",
"xloc": [
"default.handlebars->27->1446"
]
},
{ {
"cs": "Potvrdit přesun jednoho záznamu do tohoto umístění?", "cs": "Potvrdit přesun jednoho záznamu do tohoto umístění?",
"de": "Bestätigen Sie das Verschieben von 1 Eintrag an diesen Ort?", "de": "Bestätigen Sie das Verschieben von 1 Eintrag an diesen Ort?",
@ -4466,7 +4472,7 @@
"ru": "Подтвердить удаление группы устройств {0}?", "ru": "Подтвердить удаление группы устройств {0}?",
"xloc": [ "xloc": [
"default.handlebars->27->1380", "default.handlebars->27->1380",
"default.handlebars->27->1467" "default.handlebars->27->1468"
] ]
}, },
{ {
@ -4477,7 +4483,7 @@
"nl": "Bevestig het verwijderen van de groep {0}?", "nl": "Bevestig het verwijderen van de groep {0}?",
"ru": "Подтвердить удаление группы {0}?", "ru": "Подтвердить удаление группы {0}?",
"xloc": [ "xloc": [
"default.handlebars->27->1463" "default.handlebars->27->1464"
] ]
}, },
{ {
@ -4599,7 +4605,7 @@
"nl": "Verbonden Intel&reg; AMT", "nl": "Verbonden Intel&reg; AMT",
"ru": "Подключено Intel&reg; AMT", "ru": "Подключено Intel&reg; AMT",
"xloc": [ "xloc": [
"default.handlebars->27->1489" "default.handlebars->27->1490"
] ]
}, },
{ {
@ -4610,7 +4616,7 @@
"nl": "Verbonden gebruikers", "nl": "Verbonden gebruikers",
"ru": "Подключенные пользователи", "ru": "Подключенные пользователи",
"xloc": [ "xloc": [
"default.handlebars->27->1494" "default.handlebars->27->1495"
] ]
}, },
{ {
@ -4667,7 +4673,7 @@
"pt": "Contagem de conexões", "pt": "Contagem de conexões",
"ru": "Подключений ", "ru": "Подключений ",
"xloc": [ "xloc": [
"default.handlebars->27->1505" "default.handlebars->27->1506"
] ]
}, },
{ {
@ -4681,7 +4687,7 @@
"pt": "Encaminhador de conexão", "pt": "Encaminhador de conexão",
"ru": "Ретранслятор подключения", "ru": "Ретранслятор подключения",
"xloc": [ "xloc": [
"default.handlebars->27->1532" "default.handlebars->27->1533"
] ]
}, },
{ {
@ -4768,7 +4774,7 @@
"pt": "Codificador de cookies", "pt": "Codificador de cookies",
"ru": "Cookie-кодировщик", "ru": "Cookie-кодировщик",
"xloc": [ "xloc": [
"default.handlebars->27->1519" "default.handlebars->27->1520"
] ]
}, },
{ {
@ -4977,7 +4983,7 @@
"pt": "Servidor Core", "pt": "Servidor Core",
"ru": "Основной сервер", "ru": "Основной сервер",
"xloc": [ "xloc": [
"default.handlebars->27->1518" "default.handlebars->27->1519"
] ]
}, },
{ {
@ -5844,8 +5850,8 @@
"default.handlebars->27->1145", "default.handlebars->27->1145",
"default.handlebars->27->1147", "default.handlebars->27->1147",
"default.handlebars->27->1376", "default.handlebars->27->1376",
"default.handlebars->27->1453", "default.handlebars->27->1454",
"default.handlebars->27->1459" "default.handlebars->27->1460"
] ]
}, },
{ {
@ -5878,7 +5884,7 @@
"default.handlebars->27->1348", "default.handlebars->27->1348",
"default.handlebars->27->1361", "default.handlebars->27->1361",
"default.handlebars->27->1416", "default.handlebars->27->1416",
"default.handlebars->27->1492", "default.handlebars->27->1493",
"default.handlebars->container->column_l->p2->9" "default.handlebars->container->column_l->p2->9"
] ]
}, },
@ -6681,7 +6687,7 @@
"nl": "Duplicaat Agent", "nl": "Duplicaat Agent",
"ru": "Скопировать агент", "ru": "Скопировать агент",
"xloc": [ "xloc": [
"default.handlebars->27->1488" "default.handlebars->27->1489"
] ]
}, },
{ {
@ -7578,7 +7584,7 @@
"nl": "Extern", "nl": "Extern",
"ru": "Внешний", "ru": "Внешний",
"xloc": [ "xloc": [
"default.handlebars->27->1512" "default.handlebars->27->1513"
] ]
}, },
{ {
@ -7934,8 +7940,8 @@
"pt": "Livre", "pt": "Livre",
"ru": "Свободно", "ru": "Свободно",
"xloc": [ "xloc": [
"default.handlebars->27->1473", "default.handlebars->27->1474",
"default.handlebars->27->1475" "default.handlebars->27->1476"
] ]
}, },
{ {
@ -8114,7 +8120,7 @@
"xloc": [ "xloc": [
"default.handlebars->27->1090", "default.handlebars->27->1090",
"default.handlebars->27->1373", "default.handlebars->27->1373",
"default.handlebars->27->1450" "default.handlebars->27->1451"
] ]
}, },
{ {
@ -8610,7 +8616,7 @@
"es": "Heap Total", "es": "Heap Total",
"nl": "Heap Totaal", "nl": "Heap Totaal",
"xloc": [ "xloc": [
"default.handlebars->27->1514" "default.handlebars->27->1515"
] ]
}, },
{ {
@ -8620,7 +8626,7 @@
"es": "Heap Used", "es": "Heap Used",
"nl": "Heap gebruikt", "nl": "Heap gebruikt",
"xloc": [ "xloc": [
"default.handlebars->27->1513" "default.handlebars->27->1514"
] ]
}, },
{ {
@ -9142,8 +9148,8 @@
"xloc": [ "xloc": [
"default.handlebars->27->1222", "default.handlebars->27->1222",
"default.handlebars->27->1228", "default.handlebars->27->1228",
"default.handlebars->27->1510", "default.handlebars->27->1511",
"default.handlebars->27->1531" "default.handlebars->27->1532"
] ]
}, },
{ {
@ -9705,7 +9711,7 @@
"nl": "Ongeldige apparaatgroep type", "nl": "Ongeldige apparaatgroep type",
"ru": "Некорректный тип группы устройств", "ru": "Некорректный тип группы устройств",
"xloc": [ "xloc": [
"default.handlebars->27->1487" "default.handlebars->27->1488"
] ]
}, },
{ {
@ -9716,7 +9722,7 @@
"nl": "Onjuiste JSON", "nl": "Onjuiste JSON",
"ru": "Некорректный JSON", "ru": "Некорректный JSON",
"xloc": [ "xloc": [
"default.handlebars->27->1481" "default.handlebars->27->1482"
] ]
}, },
{ {
@ -9756,7 +9762,7 @@
"nl": "Onjuiste PKCS handtekening", "nl": "Onjuiste PKCS handtekening",
"ru": "Некорректная сигнатура PKCS", "ru": "Некорректная сигнатура PKCS",
"xloc": [ "xloc": [
"default.handlebars->27->1479" "default.handlebars->27->1480"
] ]
}, },
{ {
@ -9767,7 +9773,7 @@
"nl": "Ongeldige RSA handtekening", "nl": "Ongeldige RSA handtekening",
"ru": "Некорректная сигнатура RSA", "ru": "Некорректная сигнатура RSA",
"xloc": [ "xloc": [
"default.handlebars->27->1480" "default.handlebars->27->1481"
] ]
}, },
{ {
@ -10589,7 +10595,7 @@
"pt": "Menos", "pt": "Menos",
"ru": "Меньше", "ru": "Меньше",
"xloc": [ "xloc": [
"default.handlebars->27->1545" "default.handlebars->27->1546"
] ]
}, },
{ {
@ -11418,7 +11424,7 @@
"pt": "Mensagens do servidor principal", "pt": "Mensagens do servidor principal",
"ru": "Сообщения главного сервера", "ru": "Сообщения главного сервера",
"xloc": [ "xloc": [
"default.handlebars->27->1521" "default.handlebars->27->1522"
] ]
}, },
{ {
@ -11715,7 +11721,7 @@
"nl": "Max Sessies bereikt", "nl": "Max Sessies bereikt",
"ru": "Достигнуто максимальное число сессий", "ru": "Достигнуто максимальное число сессий",
"xloc": [ "xloc": [
"default.handlebars->27->1485" "default.handlebars->27->1486"
] ]
}, },
{ {
@ -11760,7 +11766,7 @@
"pt": "Megabytes", "pt": "Megabytes",
"ru": "Мегабайт", "ru": "Мегабайт",
"xloc": [ "xloc": [
"default.handlebars->27->1511" "default.handlebars->27->1512"
] ]
}, },
{ {
@ -11774,7 +11780,7 @@
"pt": "Memória", "pt": "Memória",
"ru": "ОЗУ", "ru": "ОЗУ",
"xloc": [ "xloc": [
"default.handlebars->27->1502", "default.handlebars->27->1503",
"default.handlebars->27->743", "default.handlebars->27->743",
"default.handlebars->container->column_l->p40->3->1->p40type->3" "default.handlebars->container->column_l->p40->3->1->p40type->3"
] ]
@ -11884,7 +11890,7 @@
"nl": "MeshAgent verkeer", "nl": "MeshAgent verkeer",
"ru": "Трафик MeshAgent", "ru": "Трафик MeshAgent",
"xloc": [ "xloc": [
"default.handlebars->27->1523" "default.handlebars->27->1524"
] ]
}, },
{ {
@ -11897,7 +11903,7 @@
"nl": "MeshAgent update", "nl": "MeshAgent update",
"ru": "Обновление MeshAgent", "ru": "Обновление MeshAgent",
"xloc": [ "xloc": [
"default.handlebars->27->1524" "default.handlebars->27->1525"
] ]
}, },
{ {
@ -11977,7 +11983,7 @@
"pt": "Peering do servidor MeshCentral", "pt": "Peering do servidor MeshCentral",
"ru": "Соединения сервера MeshCentral", "ru": "Соединения сервера MeshCentral",
"xloc": [ "xloc": [
"default.handlebars->27->1522" "default.handlebars->27->1523"
] ]
}, },
{ {
@ -12169,7 +12175,7 @@
"pt": "Despachante de mensagens", "pt": "Despachante de mensagens",
"ru": "Диспетчер сообщения", "ru": "Диспетчер сообщения",
"xloc": [ "xloc": [
"default.handlebars->27->1520" "default.handlebars->27->1521"
] ]
}, },
{ {
@ -12251,7 +12257,7 @@
"pt": "Mais", "pt": "Mais",
"ru": "Еще", "ru": "Еще",
"xloc": [ "xloc": [
"default.handlebars->27->1544" "default.handlebars->27->1545"
] ]
}, },
{ {
@ -12804,7 +12810,7 @@
"ru": "События не найдены", "ru": "События не найдены",
"xloc": [ "xloc": [
"default.handlebars->27->1269", "default.handlebars->27->1269",
"default.handlebars->27->1468", "default.handlebars->27->1469",
"default.handlebars->27->691" "default.handlebars->27->691"
] ]
}, },
@ -12951,7 +12957,7 @@
"default.handlebars->27->1091", "default.handlebars->27->1091",
"default.handlebars->27->1192", "default.handlebars->27->1192",
"default.handlebars->27->1374", "default.handlebars->27->1374",
"default.handlebars->27->1451" "default.handlebars->27->1452"
] ]
}, },
{ {
@ -13020,7 +13026,7 @@
"ru": "Нет общих групп устройств", "ru": "Нет общих групп устройств",
"xloc": [ "xloc": [
"default.handlebars->27->1377", "default.handlebars->27->1377",
"default.handlebars->27->1454" "default.handlebars->27->1455"
] ]
}, },
{ {
@ -13229,7 +13235,7 @@
"nl": "Geen gebruikersgroep lidmaatschap", "nl": "Geen gebruikersgroep lidmaatschap",
"ru": "Нет членства в группах пользователей", "ru": "Нет членства в группах пользователей",
"xloc": [ "xloc": [
"default.handlebars->27->1460" "default.handlebars->27->1461"
] ]
}, },
{ {
@ -13622,7 +13628,7 @@
"pt": "Ocorreu em {0}", "pt": "Ocorreu em {0}",
"ru": "Произошло в {0}", "ru": "Произошло в {0}",
"xloc": [ "xloc": [
"default.handlebars->27->1471" "default.handlebars->27->1472"
] ]
}, },
{ {
@ -13943,7 +13949,7 @@
"xloc": [ "xloc": [
"default.handlebars->27->1089", "default.handlebars->27->1089",
"default.handlebars->27->1371", "default.handlebars->27->1371",
"default.handlebars->27->1448" "default.handlebars->27->1449"
] ]
}, },
{ {
@ -14435,7 +14441,7 @@
"nl": "Plugin Actie", "nl": "Plugin Actie",
"ru": "Действие плагина", "ru": "Действие плагина",
"xloc": [ "xloc": [
"default.handlebars->27->1541", "default.handlebars->27->1542",
"default.handlebars->27->159" "default.handlebars->27->159"
] ]
}, },
@ -14978,7 +14984,7 @@
"pt": "RSS", "pt": "RSS",
"ru": "RSS", "ru": "RSS",
"xloc": [ "xloc": [
"default.handlebars->27->1515" "default.handlebars->27->1516"
] ]
}, },
{ {
@ -15121,7 +15127,7 @@
"nl": "Relay geteld", "nl": "Relay geteld",
"ru": "Число ретрансляций", "ru": "Число ретрансляций",
"xloc": [ "xloc": [
"default.handlebars->27->1497" "default.handlebars->27->1498"
] ]
}, },
{ {
@ -15132,7 +15138,7 @@
"nl": "Relay fouten", "nl": "Relay fouten",
"ru": "Ошибки ретранслятора", "ru": "Ошибки ретранслятора",
"xloc": [ "xloc": [
"default.handlebars->27->1490" "default.handlebars->27->1491"
] ]
}, },
{ {
@ -15145,8 +15151,8 @@
"pt": "Retransmissão de sessão ", "pt": "Retransmissão de sessão ",
"ru": "Сессии ретранслятора", "ru": "Сессии ретранслятора",
"xloc": [ "xloc": [
"default.handlebars->27->1496", "default.handlebars->27->1497",
"default.handlebars->27->1509" "default.handlebars->27->1510"
] ]
}, },
{ {
@ -15358,7 +15364,7 @@
"ru": "Удалить группу устройств.", "ru": "Удалить группу устройств.",
"xloc": [ "xloc": [
"default.handlebars->27->1379", "default.handlebars->27->1379",
"default.handlebars->27->1466" "default.handlebars->27->1467"
] ]
}, },
{ {
@ -15369,7 +15375,7 @@
"nl": "Verwijder gebruiker", "nl": "Verwijder gebruiker",
"ru": "Удалить пользователя", "ru": "Удалить пользователя",
"xloc": [ "xloc": [
"default.handlebars->27->1462" "default.handlebars->27->1463"
] ]
}, },
{ {
@ -15442,7 +15448,7 @@
"nl": "Verwijder de groepslidmaatschap", "nl": "Verwijder de groepslidmaatschap",
"ru": "Удалить членство пользователя в группе", "ru": "Удалить членство пользователя в группе",
"xloc": [ "xloc": [
"default.handlebars->27->1458" "default.handlebars->27->1459"
] ]
}, },
{ {
@ -15469,7 +15475,7 @@
"xloc": [ "xloc": [
"default.handlebars->27->1092", "default.handlebars->27->1092",
"default.handlebars->27->1366", "default.handlebars->27->1366",
"default.handlebars->27->1452" "default.handlebars->27->1453"
] ]
}, },
{ {
@ -16479,14 +16485,14 @@
"nl": "Server Certificaat", "nl": "Server Certificaat",
"ru": "Сертификат сервера", "ru": "Сертификат сервера",
"xloc": [ "xloc": [
"default.handlebars->27->1525" "default.handlebars->27->1526"
] ]
}, },
{ {
"en": "Server Database", "en": "Server Database",
"nl": "Server Database", "nl": "Server Database",
"xloc": [ "xloc": [
"default.handlebars->27->1526" "default.handlebars->27->1527"
] ]
}, },
{ {
@ -16571,7 +16577,7 @@
"nl": "Server Status", "nl": "Server Status",
"ru": "Состояние сервера", "ru": "Состояние сервера",
"xloc": [ "xloc": [
"default.handlebars->27->1476" "default.handlebars->27->1477"
] ]
}, },
{ {
@ -16599,7 +16605,7 @@
"pt": "Rastreamento de servidor", "pt": "Rastreamento de servidor",
"ru": "Трассировка сервера", "ru": "Трассировка сервера",
"xloc": [ "xloc": [
"default.handlebars->27->1535" "default.handlebars->27->1536"
] ]
}, },
{ {
@ -16707,7 +16713,7 @@
"pt": "ServerStats.csv", "pt": "ServerStats.csv",
"ru": "ServerStats.csv", "ru": "ServerStats.csv",
"xloc": [ "xloc": [
"default.handlebars->27->1517" "default.handlebars->27->1518"
] ]
}, },
{ {
@ -18291,7 +18297,7 @@
"pt": "Atualmente não há notificações", "pt": "Atualmente não há notificações",
"ru": "На данный момент уведомлений нет", "ru": "На данный момент уведомлений нет",
"xloc": [ "xloc": [
"default.handlebars->27->1470" "default.handlebars->27->1471"
] ]
}, },
{ {
@ -19176,7 +19182,7 @@
"default-mobile.handlebars->9->174", "default-mobile.handlebars->9->174",
"default-mobile.handlebars->9->175", "default-mobile.handlebars->9->175",
"default.handlebars->27->13", "default.handlebars->27->13",
"default.handlebars->27->1461", "default.handlebars->27->1462",
"default.handlebars->27->364", "default.handlebars->27->364",
"default.handlebars->27->41", "default.handlebars->27->41",
"default.handlebars->27->42", "default.handlebars->27->42",
@ -19209,7 +19215,7 @@
"nl": "Onbekende actie", "nl": "Onbekende actie",
"ru": "Неизвестное действие", "ru": "Неизвестное действие",
"xloc": [ "xloc": [
"default.handlebars->27->1482" "default.handlebars->27->1483"
] ]
}, },
{ {
@ -19221,8 +19227,8 @@
"ru": "Неизвестная группа устройств", "ru": "Неизвестная группа устройств",
"xloc": [ "xloc": [
"default.handlebars->27->1372", "default.handlebars->27->1372",
"default.handlebars->27->1449", "default.handlebars->27->1450",
"default.handlebars->27->1486" "default.handlebars->27->1487"
] ]
}, },
{ {
@ -19233,7 +19239,7 @@
"nl": "Onbekende groep", "nl": "Onbekende groep",
"ru": "Неизвестная группа", "ru": "Неизвестная группа",
"xloc": [ "xloc": [
"default.handlebars->27->1478" "default.handlebars->27->1479"
] ]
}, },
{ {
@ -19259,7 +19265,7 @@
"nl": "Onbekende gebruikersgroep", "nl": "Onbekende gebruikersgroep",
"ru": "Неизвестная группа пользователей", "ru": "Неизвестная группа пользователей",
"xloc": [ "xloc": [
"default.handlebars->27->1457" "default.handlebars->27->1458"
] ]
}, },
{ {
@ -19320,7 +19326,7 @@
"nl": "Bijgewerkt", "nl": "Bijgewerkt",
"ru": "Актуально", "ru": "Актуально",
"xloc": [ "xloc": [
"default.handlebars->27->1540" "default.handlebars->27->1541"
] ]
}, },
{ {
@ -19509,8 +19515,8 @@
"pt": "Usava", "pt": "Usava",
"ru": "Использовано", "ru": "Использовано",
"xloc": [ "xloc": [
"default.handlebars->27->1472", "default.handlebars->27->1473",
"default.handlebars->27->1474" "default.handlebars->27->1475"
] ]
}, },
{ {
@ -19568,7 +19574,7 @@
"nl": "Gebruikersaccounts", "nl": "Gebruikersaccounts",
"ru": "Учетные записи пользователей", "ru": "Учетные записи пользователей",
"xloc": [ "xloc": [
"default.handlebars->27->1491" "default.handlebars->27->1492"
] ]
}, },
{ {
@ -19609,7 +19615,7 @@
"xloc": [ "xloc": [
"default.handlebars->27->1146", "default.handlebars->27->1146",
"default.handlebars->27->1350", "default.handlebars->27->1350",
"default.handlebars->27->1464" "default.handlebars->27->1465"
] ]
}, },
{ {
@ -19631,7 +19637,7 @@
"nl": "Gebruikersgroeps lidmaatschap", "nl": "Gebruikersgroeps lidmaatschap",
"ru": "Членство в группах пользователей", "ru": "Членство в группах пользователей",
"xloc": [ "xloc": [
"default.handlebars->27->1456" "default.handlebars->27->1457"
] ]
}, },
{ {
@ -19713,7 +19719,7 @@
"pt": "Sessões de Usuário", "pt": "Sessões de Usuário",
"ru": "Сессии пользователя", "ru": "Сессии пользователя",
"xloc": [ "xloc": [
"default.handlebars->27->1508" "default.handlebars->27->1509"
] ]
}, },
{ {
@ -19841,7 +19847,7 @@
"xloc": [ "xloc": [
"default.handlebars->27->1349", "default.handlebars->27->1349",
"default.handlebars->27->1360", "default.handlebars->27->1360",
"default.handlebars->27->1507", "default.handlebars->27->1508",
"default.handlebars->container->topbar->1->1->UsersSubMenuSpan->UsersSubMenu->1->0->UsersGeneral" "default.handlebars->container->topbar->1->1->UsersSubMenuSpan->UsersSubMenu->1->0->UsersGeneral"
] ]
}, },
@ -19853,7 +19859,7 @@
"nl": "gebruikers Sessies", "nl": "gebruikers Sessies",
"ru": "Сессии пользователей", "ru": "Сессии пользователей",
"xloc": [ "xloc": [
"default.handlebars->27->1495" "default.handlebars->27->1496"
] ]
}, },
{ {
@ -20167,8 +20173,8 @@
"pt": "Servidor web", "pt": "Servidor web",
"ru": "Веб-сервер", "ru": "Веб-сервер",
"xloc": [ "xloc": [
"default.handlebars->27->1527", "default.handlebars->27->1528",
"default.handlebars->27->1528" "default.handlebars->27->1529"
] ]
}, },
{ {
@ -20182,7 +20188,7 @@
"pt": "Solicitações de servidor Web", "pt": "Solicitações de servidor Web",
"ru": "Запросы веб-сервера", "ru": "Запросы веб-сервера",
"xloc": [ "xloc": [
"default.handlebars->27->1529" "default.handlebars->27->1530"
] ]
}, },
{ {
@ -20196,7 +20202,7 @@
"pt": "Encaminhador de soquete da Web", "pt": "Encaminhador de soquete da Web",
"ru": "Ретранслятор Web Socket", "ru": "Ретранслятор Web Socket",
"xloc": [ "xloc": [
"default.handlebars->27->1530" "default.handlebars->27->1531"
] ]
}, },
{ {
@ -20862,7 +20868,7 @@
"pt": "\\\\'", "pt": "\\\\'",
"ru": "\\\\'", "ru": "\\\\'",
"xloc": [ "xloc": [
"default.handlebars->27->1538" "default.handlebars->27->1539"
] ]
}, },
{ {
@ -21053,7 +21059,7 @@
"pt": "livre", "pt": "livre",
"ru": "свободно", "ru": "свободно",
"xloc": [ "xloc": [
"default.handlebars->27->1503" "default.handlebars->27->1504"
] ]
}, },
{ {
@ -21287,7 +21293,7 @@
"pt": "servertrace.csv", "pt": "servertrace.csv",
"ru": "servertrace.csv", "ru": "servertrace.csv",
"xloc": [ "xloc": [
"default.handlebars->27->1537" "default.handlebars->27->1538"
] ]
}, },
{ {
@ -21324,7 +21330,7 @@
"pt": "tempo, conn.agente, conn.usuários.usersessions, conn.relaysession, conn.intelamt, mem.externo mem.amontoado, mem.heaptotal, mem.rss", "pt": "tempo, conn.agente, conn.usuários.usersessions, conn.relaysession, conn.intelamt, mem.externo mem.amontoado, mem.heaptotal, mem.rss",
"ru": "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss", "ru": "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss",
"xloc": [ "xloc": [
"default.handlebars->27->1516" "default.handlebars->27->1517"
] ]
}, },
{ {
@ -21336,7 +21342,7 @@
"pt": "hora, fonte, mensagem", "pt": "hora, fonte, mensagem",
"ru": "time, source, message", "ru": "time, source, message",
"xloc": [ "xloc": [
"default.handlebars->27->1536" "default.handlebars->27->1537"
] ]
}, },
{ {
@ -21359,7 +21365,7 @@
"pt": "total", "pt": "total",
"ru": "всего", "ru": "всего",
"xloc": [ "xloc": [
"default.handlebars->27->1504" "default.handlebars->27->1505"
] ]
}, },
{ {
@ -22063,4 +22069,4 @@
] ]
} }
] ]
} }

View File

@ -3458,14 +3458,14 @@
if (typeof mesh == 'string') { mesh = meshes[mesh] } if (typeof mesh == 'string') { mesh = meshes[mesh] }
if ((mesh == null) || (mesh.links == null)) { return 0; } if ((mesh == null) || (mesh.links == null)) { return 0; }
// Check if user user // Check if super user
if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF; if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF;
// Check direct link permission // Check device group link permission
var rights = 0, r = mesh.links[userid]; var rights = 0, r = mesh.links[userid];
if (r != null) { if (r != null) {
if (rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device group link, stop here.
rights = r.rights; rights = r.rights;
if (rights == 0xFFFFFFFF) { return rights; } // User has full rights thru a direct link, stop here.
} }
// Check permissions thru user groups // Check permissions thru user groups
@ -3476,7 +3476,7 @@
if (i.startsWith('ugrp/')) { if (i.startsWith('ugrp/')) {
r = mesh.links[i]; r = mesh.links[i];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { return r.rights; } // User has full rights thru a user group, stop here. if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a user group, stop here.
rights |= r.rights; // TODO: Deal with reverse permissions rights |= r.rights; // TODO: Deal with reverse permissions
} }
} }
@ -3514,7 +3514,19 @@
if (node == null) { return 0; } if (node == null) { return 0; }
if (userid == null) { userid = userinfo._id; } if (userid == null) { userid = userinfo._id; }
if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } } if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
return GetMeshRights(node.meshid, userid); var r = GetMeshRights(node.meshid, userid);
if (r != 0xFFFFFFFF) {
var user = null;
if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } }
if ((user != null) && (user.links != null)) {
var r2 = user.links[node._id];
if (r2 != null) {
if (r2.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device link, stop here.
r |= r2; // TODO: Deal with reverse permissions
}
}
}
return r;
} }
// //

View File

@ -2721,7 +2721,7 @@
go(parseInt('{{viewmode}}')); go(parseInt('{{viewmode}}'));
goBackStack.push(2); goBackStack.push(2);
} else if (args.gotouser != null) { } else if (args.gotouser != null) {
if (users['user/' + domain + '/' + args.gotouser] == null) return; // This user is not loaded yet if ((users == null) || (users['user/' + domain + '/' + args.gotouser] == null)) return; // This user is not loaded yet
gotoUser('user/' + domain + '/' + args.gotouser); gotoUser('user/' + domain + '/' + args.gotouser);
go(parseInt('{{viewmode}}')); go(parseInt('{{viewmode}}'));
goBackStack.push(4); goBackStack.push(4);
@ -3123,9 +3123,11 @@
// Display all empty device groups, we need to do this because users can add devices to these at any time. // Display all empty device groups, we need to do this because users can add devices to these at any time.
if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) { if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) {
var deviceHeaderId2 = deviceHeaderId; var deviceHeaderId2 = deviceHeaderId, sortedMeshes = [];
for (var i in meshes) { for (var i in meshes) { sortedMeshes.push(meshes[i]); }
var mesh = meshes[i], meshrights = GetMeshRights(mesh); sortedMeshes.sort(nameSort);
for (var i in sortedMeshes) {
var mesh = sortedMeshes[i], meshrights = GetMeshRights(mesh);
if (displayedMeshes[mesh._id] == null) { if (displayedMeshes[mesh._id] == null) {
if ((current != '') && (r != '')) { r += '</tr></table>'; } if ((current != '') && (r != '')) { r += '</tr></table>'; }
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt>'; r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt>';
@ -3141,8 +3143,7 @@
if (mesh.mtype == 1) { if (mesh.mtype == 1) {
r += '<td><div style=padding:10px><i>' + "No Intel&reg; AMT devices in this mesh"; r += '<td><div style=padding:10px><i>' + "No Intel&reg; AMT devices in this mesh";
if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; } if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh(\"' + mesh._id + '\")\'>' + "add one" + '</a>'; }
} } else if (mesh.mtype == 2) {
if (mesh.mtype == 2) {
r += '<td>'; r += '<td>';
r += '<div id=DevxCol' + deviceHeaderId2 + ((collapsed === true)?' style=display:none':'') + '>'; // Open collapse div r += '<div id=DevxCol' + deviceHeaderId2 + ((collapsed === true)?' style=display:none':'') + '>'; // Open collapse div
r += '<div style=padding:10px><i>' + "No devices in this group"; r += '<div style=padding:10px><i>' + "No devices in this group";
@ -10055,16 +10056,14 @@
// Draw the user timeline // Draw the user timeline
drawUserPermissions(); drawUserPermissions();
// Check if we can delete this user // Check if we can change password / delete this user
var deletePossible = true; var userAdminRights = (((userinfo.siteadmin != null) && (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF)) || (userinfo.siteadmin == 0xFFFFFFFF));
if (user._id == userinfo._id) deletePossible = false;
if (user.siteadmin && user.siteadmin > 0 && userinfo.siteadmin != 0xFFFFFFFF) deletePossible = false;
// Show bottom buttons // Show bottom buttons
x = '<div style=float:right;font-size:x-small>'; x = '<div style=float:right;font-size:x-small>';
if (deletePossible) x += '<a href=# style=cursor:pointer onclick=\'return p30showDeleteUserDialog()\' title="Remove this user">' + "Delete User" + '</a>'; if (userAdminRights) { x += '<a href=# style=cursor:pointer onclick=\'return p30showDeleteUserDialog()\' title="Remove this user">' + "Delete User" + '</a>'; }
x += '</div><div style=font-size:x-small>'; x += '</div><div style=font-size:x-small>';
if (((userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF)) || (userinfo.siteadmin == 0xFFFFFFFF)) x += '<a href=# style=cursor:pointer onclick=\'return p30showUserChangePassDialog(' + multiFactor + ')\' title="' + "Change the password for this user" + '">' + "Change Password" + '</a>'; if (userAdminRights) { x += '<a href=# style=cursor:pointer onclick=\'return p30showUserChangePassDialog(' + multiFactor + ')\' title="' + "Change the password for this user" + '">' + "Change Password" + '</a>'; }
x += '</div><br>' x += '</div><br>'
QH('p30html3', x); QH('p30html3', x);
@ -10160,7 +10159,7 @@
function p30showDeleteUserDialog() { function p30showDeleteUserDialog() {
if (xxdialogMode) return; if (xxdialogMode) return;
setDialogMode(2, format("Delete User {0}", EscapeHtml(currentUser.name)), 3, p30showDeleteUserDialogEx, format('Confirm deletion of user {0}?', EscapeHtml(currentUser.name))); setDialogMode(2, format("Delete User {0}", EscapeHtml(currentUser.name)), 3, p30showDeleteUserDialogEx, format("Confirm deletion of user {0}?", EscapeHtml(currentUser.name)));
} }
function p30showDeleteUserDialogEx() { function p30showDeleteUserDialogEx() {
@ -10170,6 +10169,29 @@
// Draw device power bars. The bars are 766px wide. // Draw device power bars. The bars are 766px wide.
function drawUserPermissions() { function drawUserPermissions() {
var count = 1, x = ''; var count = 1, x = '';
if (urlargs.dp == 1) { // For testing only
// Display common devices
x += '<a href=# onclick="return p20showAddMeshUserDialog(1)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device" + '</a>';
x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Devices" + '</th><th scope=col style=text-align:left></th></tr>';
if (currentUser.links) {
for (var i in currentUser.links) {
if (i.startsWith('node/')) {
var cr = 0, r = currentUser.links[i].rights, node = getNodeFromId(i), trash = '', rights = "Partial Device Rights";
if (node == null) { continue; }
if ((userinfo.links) && (userinfo.links[i] != null) && (userinfo.links[i].rights != null)) { cr = userinfo.links[i].rights; }
var nodename = node?EscapeHtml(node.name):('<i>' + "Unknown Device" + '</i>');
if (r == 0xFFFFFFFF) rights = "Full Device Rights"; else if (r == 0) rights = "No Rights";
if ((currentUser._id != userinfo._id) && ((cr & 2) != 0)) { trash = '<a href=# onclick=\'return p30removeNodeFromUser(event,"' + encodeURIComponent(node._id) + '")\' title=\"' + "Remove user rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td><div title=\"' + "Device Group" + '\" class=m99></div><div>&nbsp;' + nodename + '<div></div></div></td><td><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
}
}
}
if (count == 1) { x += '<tr><td><div style=padding:6px>&nbsp;<i>' + "No devices in common" + '</i><div></div></div></td><td></td></tr>'; }
x += '</tbody></table><br />';
}
// Display common device groups
var deviceGroupCount = 0, newDeviceGroup = false; var deviceGroupCount = 0, newDeviceGroup = false;
for (var i in meshes) { deviceGroupCount++; if ((currentUser.links == null) || (currentUser.links[i] == null)) { newDeviceGroup = true; } } for (var i in meshes) { deviceGroupCount++; if ((currentUser.links == null) || (currentUser.links[i] == null)) { newDeviceGroup = true; } }
if ((deviceGroupCount > 0) && (newDeviceGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(1)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device Group" + '</a>'; } if ((deviceGroupCount > 0) && (newDeviceGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(1)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device Group" + '</a>'; }
@ -10190,6 +10212,7 @@
if (count == 1) { x += '<tr><td><div style=padding:6px>&nbsp;<i>' + "No device groups in common" + '</i><div></div></div></td><td></td></tr>'; } if (count == 1) { x += '<tr><td><div style=padding:6px>&nbsp;<i>' + "No device groups in common" + '</i><div></div></div></td><td></td></tr>'; }
x += '</tbody></table>'; x += '</tbody></table>';
// Display user groups
if (usergroups != null) { if (usergroups != null) {
count = 1; count = 1;
x += '<br />'; x += '<br />';
@ -11169,14 +11192,14 @@
if (typeof mesh == 'string') { mesh = meshes[mesh] } if (typeof mesh == 'string') { mesh = meshes[mesh] }
if ((mesh == null) || (mesh.links == null)) { return 0; } if ((mesh == null) || (mesh.links == null)) { return 0; }
// Check if user user // Check if super user
if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF; if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF;
// Check direct link permission // Check device group link permission
var rights = 0, r = mesh.links[userid]; var rights = 0, r = mesh.links[userid];
if (r != null) { if (r != null) {
if (rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device group link, stop here.
rights = r.rights; rights = r.rights;
if (rights == 0xFFFFFFFF) { return rights; } // User has full rights thru a direct link, stop here.
} }
// Check permissions thru user groups // Check permissions thru user groups
@ -11187,7 +11210,7 @@
if (i.startsWith('ugrp/')) { if (i.startsWith('ugrp/')) {
r = mesh.links[i]; r = mesh.links[i];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { return r.rights; } // User has full rights thru a user group, stop here. if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a user group, stop here.
rights |= r.rights; // TODO: Deal with reverse permissions rights |= r.rights; // TODO: Deal with reverse permissions
} }
} }
@ -11219,13 +11242,25 @@
return false; return false;
} }
// Return the user rights for a given node // Return the user rights for a given node
function GetNodeRights(node, userid) { function GetNodeRights(node, userid) {
if (node == null) { return 0; } if (node == null) { return 0; }
if (userid == null) { userid = userinfo._id; } if (userid == null) { userid = userinfo._id; }
if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } } if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
return GetMeshRights(node.meshid, userid); var r = GetMeshRights(node.meshid, userid);
if (r != 0xFFFFFFFF) {
var user = null;
if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } }
if ((user != null) && (user.links != null)) {
var r2 = user.links[node._id];
if (r2 != null) {
if (r2.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device link, stop here.
r |= r2; // TODO: Deal with reverse permissions
}
}
}
return r;
} }
// //

View File

@ -4101,12 +4101,20 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
db.Get(nodeid, function (err, nodes) { db.Get(nodeid, function (err, nodes) {
if ((nodes == null) || (nodes.length != 1)) { func(null, 0, false); return; } // No such nodeid if ((nodes == null) || (nodes.length != 1)) { func(null, 0, false); return; } // No such nodeid
// Check direct link // Check device link
var rights = 0, visible = false, r = user.links[nodes[0].meshid]; var rights = 0, visible = false, r = user.links[nodeid];
if (r != null) { if (r != null) {
rights = r.rights; if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device link, stop here.
rights |= r.rights;
visible = true;
}
// Check device group link
r = user.links[nodes[0].meshid];
if (r != null) {
if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device group link, stop here.
rights |= r.rights;
visible = true; visible = true;
if (rights == 0xFFFFFFFF) { func(nodes[0], rights, true); return; } // User has full rights thru a direct link, stop here.
} }
// Check user group links // Check user group links
@ -4116,7 +4124,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (g && (g.links != null)) { if (g && (g.links != null)) {
r = g.links[nodes[0].meshid]; r = g.links[nodes[0].meshid];
if (r != null) { if (r != null) {
if (r.rights == 0xFFFFFFFF) { func(nodes[0], r.rights, true); return; } // User has full rights thru a user group link, stop here. if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a user group link, stop here.
rights |= r.rights; // TODO: Deal with reverse rights rights |= r.rights; // TODO: Deal with reverse rights
visible = true; visible = true;
} }
@ -4202,7 +4210,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
return r; return r;
} }
// Get the right of a user on a given device group // Get the rights of a user on a given device group
obj.GetMeshRights = function (user, mesh) { obj.GetMeshRights = function (user, mesh) {
if ((user == null) || (mesh == null)) { return 0; } if ((user == null) || (mesh == null)) { return 0; }
if (typeof user == 'string') { user = obj.users[user]; } if (typeof user == 'string') { user = obj.users[user]; }