Added relay device groups support in UI.

This commit is contained in:
Ylian Saint-Hilaire 2022-04-13 15:53:04 -07:00
parent 7bae5663e8
commit 40ef17d071
3 changed files with 101 additions and 8 deletions

View File

@ -1955,6 +1955,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Add KVM information if needed // Add KVM information if needed
if (command.meshtype == 4) { mesh.kvm = { model: command.kvmmodel, host: command.kvmhost, user: command.kvmuser, pass: command.kvmpass }; } if (command.meshtype == 4) { mesh.kvm = { model: command.kvmmodel, host: command.kvmhost, user: command.kvmuser, pass: command.kvmpass }; }
// If this is device group that requires a relay device, store that now
if ((parent.args.lanonly != true) && (command.meshtype == 3) && (typeof command.relayid == 'string')) {
// Check the relay id
var relayIdSplit = command.relayid.split('/');
if ((relayIdSplit[0] == 'node') && (relayIdSplit[1] == domain.id)) { mesh.relayid = command.relayid; }
}
// Save the new device group // Save the new device group
db.Set(mesh); db.Set(mesh);
parent.meshes[meshid] = mesh; parent.meshes[meshid] = mesh;
@ -2120,6 +2127,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if ((common.validateInt(command.consent) == true) && (command.consent != mesh.consent)) { if (change != '') change += ' and consent changed'; else change += 'Device group "' + mesh.name + '" consent changed'; changesids.push(4); mesh.consent = command.consent; } if ((common.validateInt(command.consent) == true) && (command.consent != mesh.consent)) { if (change != '') change += ' and consent changed'; else change += 'Device group "' + mesh.name + '" consent changed'; changesids.push(4); mesh.consent = command.consent; }
if ((common.validateInt(command.expireDevs, 0, 2000) == true) && (command.expireDevs != mesh.expireDevs)) { if (change != '') change += ' and auto-remove changed'; else change += 'Device group "' + mesh.name + '" auto-remove changed'; changesids.push(5); if (command.expireDevs == 0) { delete mesh.expireDevs; } else { mesh.expireDevs = command.expireDevs; } } if ((common.validateInt(command.expireDevs, 0, 2000) == true) && (command.expireDevs != mesh.expireDevs)) { if (change != '') change += ' and auto-remove changed'; else change += 'Device group "' + mesh.name + '" auto-remove changed'; changesids.push(5); if (command.expireDevs == 0) { delete mesh.expireDevs; } else { mesh.expireDevs = command.expireDevs; } }
if ((typeof command.relayid == 'string') && (mesh.mtype == 3) && (mesh.relayid != null) && (command.relayid != mesh.relayid)) {
var relayIdSplit = command.relayid.split('/');
if ((relayIdSplit.length == 3) && (relayIdSplit[0] = 'node') && (relayIdSplit[1] == domain.id)) { if (change != '') { change += ' and device relay changed'; } else { change = 'Device relay changed'; } changesids.push(7); mesh.relayid = command.relayid; }
}
// See if we need to change device group invitation codes // See if we need to change device group invitation codes
if (mesh.mtype == 2) { if (mesh.mtype == 2) {
if (command.invite === '*') { if (command.invite === '*') {
@ -2152,7 +2164,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if (change != '') { if (change != '') {
db.Set(mesh); db.Set(mesh);
var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msgid: 142, msgArgs: [ mesh.name, changesids ], msg: change, domain: domain.id, invite: mesh.invite, expireDevs: command.expireDevs }; var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msgid: 142, msgArgs: [mesh.name, changesids], msg: change, domain: domain.id, invite: mesh.invite, expireDevs: command.expireDevs, relayid: mesh.relayid };
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(parent.CreateMeshDispatchTargets(mesh, [user._id]), obj, event); parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id]), obj, event);
} }

View File

@ -1796,7 +1796,7 @@
// This is a new mesh for us // This is a new mesh for us
if (add) { if (add) {
meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links }; meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links, relayid: message.event.relayid };
meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh). meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
} }
} else { } else {
@ -1807,6 +1807,7 @@
} }
meshes[message.event.meshid].desc = message.event.desc; meshes[message.event.meshid].desc = message.event.desc;
meshes[message.event.meshid].links = message.event.links; meshes[message.event.meshid].links = message.event.links;
if (message.event.relayid != null) { meshes[message.event.meshid].relayid = message.event.relayid; }
// Check if we lost rights to this mesh in this change. // Check if we lost rights to this mesh in this change.
if (IsMeshViewable(message.event.meshid) == false) { if (IsMeshViewable(message.event.meshid) == false) {
@ -6043,7 +6044,7 @@
var meshrights = GetMeshRights(currentMesh); var meshrights = GetMeshRights(currentMesh);
if (currentMesh.mtype == 1) meshtype = "Intel® AMT only, no agent"; if (currentMesh.mtype == 1) meshtype = "Intel® AMT only, no agent";
if (currentMesh.mtype == 2) meshtype = "Managed using a software agent"; if (currentMesh.mtype == 2) meshtype = "Managed using a software agent";
if (currentMesh.mtype == 3) meshtype = "Local devices, no agent"; if (currentMesh.mtype == 3) { if (currentMesh.relayid == null) { meshtype = "Local devices, no agent"; } else { meshtype = "No agent devices relayed thru agent"; } }
if (currentMesh.mtype == 4) { meshtype = "IP-KVM device"; if (currentMesh.kvm.model == 1) { meshtype += ', ' + 'Raritan KX III'; } } if (currentMesh.mtype == 4) { meshtype = "IP-KVM device"; if (currentMesh.kvm.model == 1) { meshtype += ', ' + 'Raritan KX III'; } }
var x = ''; var x = '';
@ -6052,6 +6053,14 @@
x += addHtmlValue("Type", meshtype); x += addHtmlValue("Type", meshtype);
//x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]); //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
// Display the relay device if applicable
if ((currentMesh.mtype == 3) && (currentMesh.relayid != null)) {
var relayName = '<i>' + "Unknown" + '</i>';
var relayNode = getNodeFromId(currentMesh.relayid);
if (relayNode != null) { relayName = EscapeHtml(relayNode.name); }
x += addHtmlValue("Relay Device", addLinkConditional(relayName, 'p20editmeshrelay()', (meshrights & 1) != 0));
}
// Display IP-KVM information if needed // Display IP-KVM information if needed
if (currentMesh.mtype == 4) { if (currentMesh.mtype == 4) {
x += addHtmlValue("Hostname", currentMesh.kvm.host); x += addHtmlValue("Hostname", currentMesh.kvm.host);
@ -6145,6 +6154,29 @@
meshserver.send({ action: 'deletemesh', meshid: currentMesh._id, meshname: currentMesh.name }); meshserver.send({ action: 'deletemesh', meshid: currentMesh._id, meshname: currentMesh.name });
} }
function p20editmeshrelay() {
if (xxdialogMode) return;
// Look for all relay devices
var relayDevices = [];
if ((features & 2) == 0) { for (var i in nodes) { var node = nodes[i]; if ((node.mtype == 2) && (node.agent != null) && (GetNodeRights(node) == 0xFFFFFFFF)) { relayDevices.push(node); } } }
relayDevices.sort(nameSort);
if (relayDevices.length == 0) {
// Relay relay devices available
setDialogMode(2, "Edit Device Group", 1, null, "No relay devices available.");
} else {
var relayDevices2 = [];
for (var i in relayDevices) { relayDevices2.push('<option value="' + (relayDevices[i]._id + '"' + ((currentMesh.relayid == relayDevices[i]._id) ? ' selected' : '')) + '>' + EscapeHtml(relayDevices[i].name) + '</option>'); }
var x = addHtmlValue("Relay Device", '<div style=width:170px><select id=d2devrelay style=width:100%>' + relayDevices2.join('') + '</select></div>');
setDialogMode(2, "Edit Device Group", 3, p20editmeshrelayEx, x);
}
}
function p20editmeshrelayEx() {
meshserver.send({ action: 'editmesh', meshid: currentMesh._id, relayid: Q('d2devrelay').value });
}
function p20editmesh(focus) { function p20editmesh(focus) {
if (xxdialogMode) return; if (xxdialogMode) return;
var x = addHtmlValue("Name", '<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />'); var x = addHtmlValue("Name", '<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
@ -6712,6 +6744,7 @@
// Generic Methods // Generic Methods
// //
function nameSort(a, b) { var aa = a.name.toLowerCase(), bb = b.name.toLowerCase(); return sortCollator.compare(aa, bb); }
function getNodeAmtVersion(node) { if ((node == null) || (node.intelamt == null) || (typeof node.intelamt.ver != 'string')) return 0; var verSplit = node.intelamt.ver.split('.'); if (verSplit.length < 2) return 0; return parseInt(verSplit[0]) + (parseInt(verSplit[1]) / 100); } function getNodeAmtVersion(node) { if ((node == null) || (node.intelamt == null) || (typeof node.intelamt.ver != 'string')) return 0; var verSplit = node.intelamt.ver.split('.'); if (verSplit.length < 2) return 0; return parseInt(verSplit[0]) + (parseInt(verSplit[1]) / 100); }
function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } } function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } } function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }

View File

@ -3045,7 +3045,7 @@
// This is a new mesh for us // This is a new mesh for us
if (add) { if (add) {
meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links }; meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links, amt: message.event.amt, invite: message.event.invite, expireDevs: message.event.expireDevs, relayid: message.event.relayid };
meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh). meshserver.send({ action: 'nodes' }); // Request a refresh of all nodes (TODO: We could optimize this to only request nodes for the new mesh).
} }
} else { } else {
@ -3061,6 +3061,7 @@
if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; } if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; }
if (message.event.invite != null) { meshes[message.event.meshid].invite = message.event.invite; } else { delete meshes[message.event.meshid].invite; } if (message.event.invite != null) { meshes[message.event.meshid].invite = message.event.invite; } else { delete meshes[message.event.meshid].invite; }
if (message.event.expireDevs != null) { if (message.event.expireDevs > 0) { meshes[message.event.meshid].expireDevs = message.event.expireDevs; } else { delete meshes[message.event.meshid].expireDevs; } } if (message.event.expireDevs != null) { if (message.event.expireDevs > 0) { meshes[message.event.meshid].expireDevs = message.event.expireDevs; } else { delete meshes[message.event.meshid].expireDevs; } }
if (message.event.relayid != null) { meshes[message.event.meshid].relayid = message.event.relayid; }
// Check if we lost rights to this mesh in this change. // Check if we lost rights to this mesh in this change.
if (IsMeshViewable(message.event.meshid) == false) { if (IsMeshViewable(message.event.meshid) == false) {
@ -11574,12 +11575,25 @@
// Remind the user to add two factor authentication // Remind the user to add two factor authentication
if ((features & 0x00040000) && (count2factoraAuths() == 0)) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" tab and look at the \"Account Security\" section."); return false; } if ((features & 0x00040000) && (count2factoraAuths() == 0)) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" tab and look at the \"Account Security\" section."); return false; }
// Look for all relay devices
var relayDevices = [];
if ((features & 2) == 0) { for (var i in nodes) { var node = nodes[i]; if ((node.mtype == 2) && (node.agent != null) && (GetNodeRights(node) == 0xFFFFFFFF)) { relayDevices.push(node); } } }
// We are allowed, let's prompt to information // We are allowed, let's prompt to information
var x = "Create a new device group using the options below." + '<br /><br />', localGroupType = ''; var x = "Create a new device group using the options below." + '<br /><br />', localGroupType = '';
x += addHtmlValue("Name", '<input id=dp2meshname style=width:230px maxlength=128 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,1) />'); x += addHtmlValue("Name", '<input id=dp2meshname style=width:230px maxlength=128 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,1) />');
if ((features & 1) == 0) { localGroupType += '<option value=3>' + "Local devices, no agent" + '</option>'; } if ((features & 1) == 0) { localGroupType += '<option value=3>' + "Local devices, no agent" + '</option>'; }
if (((features & 2) == 0) && (relayDevices.length > 0)) { localGroupType += '<option value=5>' + "No agent devices relayed thru agent" + '</option>'; }
if (features2 & 0x10000) { localGroupType += '<option value=4>' + "IP-KVM / Power device" + '</option>'; } if (features2 & 0x10000) { localGroupType += '<option value=4>' + "IP-KVM / Power device" + '</option>'; }
x += addHtmlValue("Type", '<div style=width:230px;margin:0;padding:0><select id=dp2meshtype style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=2>' + "Manage using a software agent" + '</option><option value=1>' + "Intel&reg; AMT only, no agent" + '</option>' + localGroupType + '</select></div>'); x += addHtmlValue("Type", '<div style=width:230px;margin:0;padding:0><select id=dp2meshtype style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=2>' + "Manage using a software agent" + '</option><option value=1>' + "Intel&reg; AMT only, no agent" + '</option>' + localGroupType + '</select></div>');
if (relayDevices.length > 0) {
x += '<div id=d2devrelaydiv style=display:none>';
relayDevices.sort(nameSort);
var relayDevices2 = [];
for (var i in relayDevices) { relayDevices2.push('<option value="' + relayDevices[i]._id + '">' + EscapeHtml(relayDevices[i].name) + '</option>'); }
x += addHtmlValue("Relay Device", '<div style=width:230px;margin:0;padding:0><select id=d2devrelay style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) >' + relayDevices2.join('') + '</select></div>');
x += '</div>';
}
x += addHtmlValue("Description", '<div style=width:230px;margin:0;padding:0><textarea id=dp2meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>'); x += addHtmlValue("Description", '<div style=width:230px;margin:0;padding:0><textarea id=dp2meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
x += '<div id=d2ipkvm style=display:none><hr />'; x += '<div id=d2ipkvm style=display:none><hr />';
x += addHtmlValue("Model", '<div style=width:230px;margin:0;padding:0><select id=dp2ipkvmmodel style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=1>' + "Raritan Dominion KX III" + '</option><option value=2>' + "Web Power Switch 7" + '</option></select></div>'); x += addHtmlValue("Model", '<div style=width:230px;margin:0;padding:0><select id=dp2ipkvmmodel style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=1>' + "Raritan Dominion KX III" + '</option><option value=2>' + "Web Power Switch 7" + '</option></select></div>');
@ -11599,9 +11613,8 @@
if ((x == 2) && (e != null) && (e.key == "Enter")) { Q('dp2meshdesc').focus(); } if ((x == 2) && (e != null) && (e.key == "Enter")) { Q('dp2meshdesc').focus(); }
var ok = (Q('dp2meshname').value.length > 0); var ok = (Q('dp2meshname').value.length > 0);
QV('d2ipkvm', meshtype == 4); QV('d2ipkvm', meshtype == 4);
if (meshtype == 4) { try { QV('d2devrelaydiv', meshtype == 5); } catch (ex) {}
if ((Q('dp2ipkvmhost').value.length == 0) && (Q('dp2ipkvmuser').value.length == 0) && (Q('dp2ipkvmpass').value.length == 0)) { ok = false; } if (meshtype == 4) { if ((Q('dp2ipkvmhost').value.length == 0) && (Q('dp2ipkvmuser').value.length == 0) && (Q('dp2ipkvmpass').value.length == 0)) { ok = false; } }
}
QE('idx_dlgOkButton', ok); QE('idx_dlgOkButton', ok);
} }
@ -11614,6 +11627,10 @@
cmd.kvmuser = Q('dp2ipkvmuser').value; cmd.kvmuser = Q('dp2ipkvmuser').value;
cmd.kvmpass = Q('dp2ipkvmpass').value; cmd.kvmpass = Q('dp2ipkvmpass').value;
} }
if (meshtype == 5) {
cmd.meshtype = 3;
cmd.relayid = Q('d2devrelay').value;
}
meshserver.send(cmd); meshserver.send(cmd);
} }
@ -11829,7 +11846,7 @@
var meshtype = format("Unknown #{0}", currentMesh.mtype); var meshtype = format("Unknown #{0}", currentMesh.mtype);
if (currentMesh.mtype == 1) meshtype = "Intel&reg; AMT only, no agent"; if (currentMesh.mtype == 1) meshtype = "Intel&reg; AMT only, no agent";
if (currentMesh.mtype == 2) meshtype = "Managed using a software agent"; if (currentMesh.mtype == 2) meshtype = "Managed using a software agent";
if (currentMesh.mtype == 3) meshtype = "Local devices, no agent"; if (currentMesh.mtype == 3) { if (currentMesh.relayid == null) { meshtype = "Local devices, no agent"; } else { meshtype = "No agent devices relayed thru agent"; } }
if (currentMesh.mtype == 4) { meshtype = "IP-KVM device"; if (currentMesh.kvm.model == 1) { meshtype += ', ' + 'Raritan KX III'; } } if (currentMesh.mtype == 4) { meshtype = "IP-KVM device"; if (currentMesh.kvm.model == 1) { meshtype += ', ' + 'Raritan KX III'; } }
var x = ''; var x = '';
@ -11840,6 +11857,14 @@
x += addHtmlValue("Type", meshtype); x += addHtmlValue("Type", meshtype);
//x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]); //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
// Display the relay device if applicable
if ((currentMesh.mtype == 3) && (currentMesh.relayid != null)) {
var relayName = '<i>' + "Unknown" + '</i>';
var relayNode = getNodeFromId(currentMesh.relayid);
if (relayNode != null) { relayName = EscapeHtml(relayNode.name); }
x += addHtmlValue("Relay Device", addLinkConditional(relayName, 'p20editmeshrelay()', (meshrights & 1) != 0));
}
// Display IP-KVM information if needed // Display IP-KVM information if needed
if (currentMesh.mtype == 4) { if (currentMesh.mtype == 4) {
x += addHtmlValue("Hostname", currentMesh.kvm.host); x += addHtmlValue("Hostname", currentMesh.kvm.host);
@ -12230,6 +12255,29 @@
meshserver.send({ action: 'deletemesh', meshid: currentMesh._id, meshname: currentMesh.name }); meshserver.send({ action: 'deletemesh', meshid: currentMesh._id, meshname: currentMesh.name });
} }
function p20editmeshrelay() {
if (xxdialogMode) return;
// Look for all relay devices
var relayDevices = [];
if ((features & 2) == 0) { for (var i in nodes) { var node = nodes[i]; if ((node.mtype == 2) && (node.agent != null) && (GetNodeRights(node) == 0xFFFFFFFF)) { relayDevices.push(node); } } }
relayDevices.sort(nameSort);
if (relayDevices.length == 0) {
// Relay relay devices available
setDialogMode(2, "Edit Device Group", 1, null, "No relay devices available.");
} else {
var relayDevices2 = [];
for (var i in relayDevices) { relayDevices2.push('<option value="' + (relayDevices[i]._id + '"' + ((currentMesh.relayid == relayDevices[i]._id) ? ' selected' : '')) + '>' + EscapeHtml(relayDevices[i].name) + '</option>'); }
var x = addHtmlValue("Relay Device", '<div style=width:230px;margin:0;padding:0><select id=d2devrelay style=width:100%>' + relayDevices2.join('') + '</select></div>');
setDialogMode(2, "Edit Device Group", 3, p20editmeshrelayEx, x);
}
}
function p20editmeshrelayEx() {
meshserver.send({ action: 'editmesh', meshid: currentMesh._id, relayid: Q('d2devrelay').value });
}
function p20editmesh(focus) { function p20editmesh(focus) {
if (xxdialogMode) return; if (xxdialogMode) return;
var x = addHtmlValue("Name", '<input id=dp20meshname style=width:230px maxlength=128 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate(event) />'); var x = addHtmlValue("Name", '<input id=dp20meshname style=width:230px maxlength=128 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate(event) />');