Lots of work on email notification of device connect/disconnect.

Ylian Saint-Hilaire committed Oct 10, 2021 at 12:43 UTC 44dec3bf877bc26274f3a8bfc58e5332f53be407
13 files changed +349 -97
amtmanager.js
+2 -2
@@ -820,7 +820,7 @@ module.exports.CreateAmtManager = function (parent) {
820 else if (response.Body.OSPowerSavingState == 3) { meshPowerState = 2; } // Modern standby (We are going to call this S1);
821
822 // Set OS power state
823 - if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState); }
823 + if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState, null, { name: dev.name }); }
824 });
825 } else {
826 // Convert the power state
@@ -830,7 +830,7 @@ module.exports.CreateAmtManager = function (parent) {
830 if (powerstate < powerConversionTable.length) { meshPowerState = powerConversionTable[powerstate]; } else { powerstate = 6; }
831
832 // Set power state
833 - if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState); }
833 + if (meshPowerState >= 0) { parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, meshPowerState, null, { name: dev.name }); }
834 }
835 });
836 }
amtprovisioningserver.js
+1 -1
@@ -263,7 +263,7 @@ module.exports.CreateAmtProvisioningServer = function (parent, config) {
263 // Setup TLS and commit.
264 attemptTlsSync(dev, function (dev) {
265 dev.consoleMsg('Intel AMT ACM activation completed.');
266 - parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, 7); // Report power state as "present" (7).
266 + parent.SetConnectivityState(dev.meshid, dev.nodeid, Date.now(), 4, 7, null, { name: dev.name }); // Report power state as "present" (7).
267 if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(dev.nodeid, 3, dev.aquired.host); } // Request that Intel AMT manager take a look at this device.
268 destroyDevice(dev); // We are done, clean up.
269 });
amtscanner.js
+3 -3
@@ -178,7 +178,7 @@ module.exports.CreateAmtScanner = function (parent) {
178 if ((scaninfo.state == 1) && (delta >= PeriodicScanTimeout)) {
179 // More than 2 minutes without a response, mark the node as unknown state
180 scaninfo.state = 0;
181 - obj.parent.ClearConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, 4); // Clear connectivity state
181 + obj.parent.ClearConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, 4, null, { name: doc.name }); // Clear connectivity state
182 if (obj.parent.amtManager != null) { obj.parent.amtManager.stopAmtManagement(scaninfo.nodeinfo._id, 3, scaninfo.nodeinfo.host); }
183 } else if ((scaninfo.tcp == null) && ((scaninfo.state == 0) || isNaN(delta) || (delta > PeriodicScanTime))) {
184 // More than 30 seconds without a response, try TCP detection
@@ -188,7 +188,7 @@ module.exports.CreateAmtScanner = function (parent) {
188 tag.lastpong = Date.now();
189 if (tag.state == 0) {
190 tag.state = 1;
191 - obj.parent.SetConnectivityState(tag.nodeinfo.meshid, tag.nodeinfo._id, tag.lastpong, 4, 7); // Report power state as "present" (7).
191 + obj.parent.SetConnectivityState(tag.nodeinfo.meshid, tag.nodeinfo._id, tag.lastpong, 4, 7, null, { name: doc.name }); // Report power state as "present" (7).
192 if (version != null) { obj.changeAmtState(tag.nodeinfo._id, version, 2, tag.nodeinfo.intelamt.tls); }
193 if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(tag.nodeinfo._id, 3, tag.nodeinfo.host); }
194 }
@@ -299,7 +299,7 @@ module.exports.CreateAmtScanner = function (parent) {
299 scaninfo.nodeinfo.intelamt.ver = majorVersion + '.' + minorVersion;
300 scaninfo.nodeinfo.intelamt.state = provisioningState;
301 }
302 - obj.parent.SetConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, scaninfo.lastpong, 4, 7); // Report power state as "present" (7).
302 + obj.parent.SetConnectivityState(scaninfo.nodeinfo.meshid, scaninfo.nodeinfo._id, scaninfo.lastpong, 4, 7, null, { name: scaninfo.nodeinfo.name }); // Report power state as "present" (7).
303 obj.changeAmtState(scaninfo.nodeinfo._id, scaninfo.nodeinfo.intelamt.ver, provisioningState, scaninfo.nodeinfo.intelamt.tls);
304 if (obj.parent.amtManager != null) { obj.parent.amtManager.startAmtManagement(scaninfo.nodeinfo._id, 3, scaninfo.nodeinfo.host); }
305 }
meshagent.js
+15 -13
@@ -64,7 +64,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
64 // Remove this agent from the webserver list
65 if (parent.wsagents[obj.dbNodeKey] == obj) {
66 delete parent.wsagents[obj.dbNodeKey];
67 - parent.parent.ClearConnectivityState(obj.dbMeshKey, obj.dbNodeKey, 1, null, { remoteaddrport: obj.remoteaddrport });
67 + parent.parent.ClearConnectivityState(obj.dbMeshKey, obj.dbNodeKey, 1, null, { remoteaddrport: obj.remoteaddrport, name: obj.name });
68 }
69
70 // Remove this agent from the list of agents with bad web certificates
@@ -119,17 +119,18 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
119 if (obj.pongtimer) { clearInterval(obj.pongtimer); delete obj.pongtimer; }
120
121 // Perform aggressive cleanup
122 - if (obj.nonce) { delete obj.nonce; }
123 - if (obj.nodeid) { delete obj.nodeid; }
124 - if (obj.unauth) { delete obj.unauth; }
125 - if (obj.remoteaddr) { delete obj.remoteaddr; }
126 - if (obj.remoteaddrport) { delete obj.remoteaddrport; }
127 - if (obj.meshid) { delete obj.meshid; }
128 - if (obj.dbNodeKey) { delete obj.dbNodeKey; }
129 - if (obj.dbMeshKey) { delete obj.dbMeshKey; }
130 - if (obj.connectTime) { delete obj.connectTime; }
131 - if (obj.agentInfo) { delete obj.agentInfo; }
132 - if (obj.agentExeInfo) { delete obj.agentExeInfo; }
122 + delete obj.name;
123 + delete obj.nonce;
124 + delete obj.nodeid;
125 + delete obj.unauth;
126 + delete obj.remoteaddr;
127 + delete obj.remoteaddrport;
128 + delete obj.meshid;
129 + delete obj.dbNodeKey;
130 + delete obj.dbMeshKey;
131 + delete obj.connectTime;
132 + delete obj.agentInfo;
133 + delete obj.agentExeInfo;
134 ws.removeAllListeners(['message', 'close', 'error']);
135 };
136
@@ -752,6 +753,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
753 return;
754 } else {
755 device = nodes[0];
756 + obj.name = device.name;
757
758 // This device exists, meshid given by the device must be ignored, use the server side one.
759 if ((device.meshid != null) && (device.meshid != obj.dbMeshKey)) {
@@ -888,7 +890,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
890 dupAgent.close(3);
891 } else {
892 // Indicate the agent is connected
891 - parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1, null, { remoteaddrport: obj.remoteaddrport });
893 + parent.parent.SetConnectivityState(obj.dbMeshKey, obj.dbNodeKey, obj.connectTime, 1, 1, null, { remoteaddrport: obj.remoteaddrport, name: device.name });
894 }
895
896 // We are done, ready to communicate with this agent
meshcentral.js
+54 -2
@@ -2081,6 +2081,46 @@ function CreateMeshCentralServer(config, args) {
2081 }
2082 };
2083
2084 + // See if we need to notifiy any user of device state change
2085 + obj.NotifyUserOfDeviceStateChange = function (meshid, nodeid, connectTime, connectType, powerState, serverid, stateSet, extraInfo) {
2086 + // Check if there is a email server for this domain
2087 + const meshSplit = meshid.split('/');
2088 + if (meshSplit.length != 3) return;
2089 + const domainId = meshSplit[1];
2090 + const mailserver = obj.config.domains[domainId].mailserver;;
2091 + if (mailserver == null) return;
2092 +
2093 + // Get the device group for this device
2094 + const mesh = obj.webserver.meshes[meshid];
2095 + if ((mesh == null) || (mesh.links == null)) return;
2096 +
2097 + // Check if any user needs email notification
2098 + for (var i in mesh.links) {
2099 + if (i.startsWith('user/')) {
2100 + const user = obj.webserver.users[i];
2101 + if ((user != null) && (user.email != null) && (user.emailVerified == true)) {
2102 + const meshLinks = user.links[meshid];
2103 + if ((meshLinks != null) && (meshLinks.notify != null) && ((meshLinks.notify & 48) != 0)) {
2104 + if (stateSet == true) {
2105 + if ((meshLinks.notify & 16) != 0) {
2106 + mailserver.notifyDeviceConnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
2107 + } else {
2108 + mailserver.cancelNotifyDeviceDisconnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
2109 + }
2110 + }
2111 + else if (stateSet == false) {
2112 + if ((meshLinks.notify & 32) != 0) {
2113 + mailserver.notifyDeviceDisconnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
2114 + } else {
2115 + mailserver.cancelNotifyDeviceConnect(user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo);
2116 + }
2117 + }
2118 + }
2119 + }
2120 + }
2121 + }
2122 + }
2123 +
2124 // Set the connectivity state of a node and setup the server so that messages can be routed correctly.
2125 // meshId: mesh identifier of format mesh/domain/meshidhex
2126 // nodeId: node identifier of format node/domain/nodeidhex
@@ -2091,7 +2131,7 @@ function CreateMeshCentralServer(config, args) {
2131 //var powerStateStrings = ['Unknown', 'Powered', 'Sleep', 'Sleep', 'Deep Sleep', 'Hibernating', 'Soft-Off', 'Present'];
2132 obj.SetConnectivityState = function (meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
2133 //console.log('SetConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + ', Power: ' + powerStateStrings[powerState] + (serverid == null ? ('') : (', ServerId: ' + serverid)));
2094 - if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'SetConnectivityState', meshid: meshid, nodeid: nodeid, connectTime: connectTime, connectType: connectType, powerState: powerState }); }
2134 + if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'SetConnectivityState', meshid: meshid, nodeid: nodeid, connectTime: connectTime, connectType: connectType, powerState: powerState, extraInfo: extraInfo }); }
2135
2136 if (obj.multiServer == null) {
2137 // Single server mode
@@ -2131,6 +2171,9 @@ function CreateMeshCentralServer(config, args) {
2171 const lc = { _id: 'lc' + nodeid, type: 'lastconnect', domain: nodeid.split('/')[1], meshid: meshid, time: Date.now(), cause: 1, connectType: connectType };
2172 if (extraInfo && extraInfo.remoteaddrport) { lc.addr = extraInfo.remoteaddrport; }
2173 obj.db.Set(lc);
2174 +
2175 + // Notify any users of device connection
2176 + obj.NotifyUserOfDeviceStateChange(meshid, nodeid, connectTime, connectType, powerState, serverid, true, extraInfo);
2177 }
2178 } else {
2179 // Multi server mode
@@ -2175,6 +2218,9 @@ function CreateMeshCentralServer(config, args) {
2218 if (extraInfo && extraInfo.remoteaddrport) { lc.addr = extraInfo.remoteaddrport; }
2219 obj.db.Set(lc);
2220 }
2221 +
2222 + // Notify any users of device connection
2223 + obj.NotifyUserOfDeviceStateChange(meshid, nodeid, connectTime, connectType, powerState, serverid, true, extraInfo);
2224 }
2225 }
2226 };
@@ -2185,7 +2231,7 @@ function CreateMeshCentralServer(config, args) {
2231 // connectType: Bitmask, 1 = MeshAgent, 2 = Intel AMT CIRA, 3 = Intel AMT local.
2232 obj.ClearConnectivityState = function (meshid, nodeid, connectType, serverid, extraInfo) {
2233 //console.log('ClearConnectivity for ' + nodeid.substring(0, 16) + ', Type: ' + connectTypeStrings[connectType] + (serverid == null?(''):(', ServerId: ' + serverid)));
2188 - if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'ClearConnectivityState', meshid: meshid, nodeid: nodeid, connectType: connectType }); }
2234 + if ((serverid == null) && (obj.multiServer != null)) { obj.multiServer.DispatchMessage({ action: 'ClearConnectivityState', meshid: meshid, nodeid: nodeid, connectType: connectType, extraInfo: extraInfo }); }
2235
2236 if (obj.multiServer == null) {
2237 // Single server mode
@@ -2223,6 +2269,9 @@ function CreateMeshCentralServer(config, args) {
2269 // Event the node connection change
2270 if (eventConnectChange == 1) {
2271 obj.DispatchEvent(obj.webserver.CreateNodeDispatchTargets(meshid, nodeid), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, domain: nodeid.split('/')[1], conn: state.connectivity, pwr: state.powerState, nolog: 1, nopeers: 1 });
2272 +
2273 + // Notify any users of device disconnection
2274 + obj.NotifyUserOfDeviceStateChange(meshid, nodeid, Date.now(), connectType, -1, serverid, false, extraInfo);
2275 }
2276 } else {
2277 // Multi server mode
@@ -2246,6 +2295,9 @@ function CreateMeshCentralServer(config, args) {
2295
2296 // If the node is completely disconnected, clean it up completely
2297 if (state.connectivity == 0) { delete obj.peerConnectivityByNode[serverid][nodeid]; state.powerState = 0; }
2298 +
2299 + // Notify any users of device disconnection
2300 + obj.NotifyUserOfDeviceStateChange(meshid, nodeid, Date.now(), connectType, -1, serverid, false, extraInfo);
2301 }
2302
2303 // Clear node power state
meshmail.js
+170
@@ -448,5 +448,175 @@ module.exports.CreateMeshMail = function (parent, domain) {
448 });
449 }
450
451 + //
452 + // Device connetion and disconnection notifications
453 + //
454 +
455 + obj.deviceNotifications = {}; // UserId --> { timer, nodes: nodeid --> connectType }
456 +
457 + // A device connected and a user needs to be notified about it.
458 + obj.notifyDeviceConnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
459 + const mesh = parent.webserver.meshes[meshid];
460 + if (mesh == null) return;
461 +
462 + // Add the user and start a timer
463 + if (obj.deviceNotifications[user._id] == null) {
464 + obj.deviceNotifications[user._id] = { nodes: {} };
465 + obj.deviceNotifications[user._id].timer = setTimeout(function () { sendDeviceNotifications(user._id); }, 20000);
466 + }
467 +
468 + // Add the device
469 + if (obj.deviceNotifications[user._id].nodes[nodeid] == null) {
470 + obj.deviceNotifications[user._id].nodes[nodeid] = { c: connectType }; // This device connection need to be added
471 + } else {
472 + const info = obj.deviceNotifications[user._id].nodes[nodeid];
473 + if ((info.d != null) && ((info.d & connectType) != 0)) {
474 + info.d -= connectType; // This device disconnect cancels out a device connection
475 + if (((info.c == null) || (info.c == 0)) && ((info.d == null) || (info.d == 0))) {
476 + // This device no longer needs a notification
477 + delete obj.deviceNotifications[user._id].nodes[nodeid];
478 + if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
479 + // This user no longer needs a notification
480 + clearTimeout(obj.deviceNotifications[user._id].timer);
481 + delete obj.deviceNotifications[user._id];
482 + }
483 + return;
484 + }
485 + } else {
486 + if (info.c != null) {
487 + info.c |= connectType; // This device disconnect needs to be added
488 + } else {
489 + info.c = connectType; // This device disconnect needs to be added
490 + }
491 + }
492 + }
493 +
494 + // Set the device group name
495 + if ((extraInfo != null) && (extraInfo.name != null)) { obj.deviceNotifications[user._id].nodes[nodeid].nn = extraInfo.name; }
496 + obj.deviceNotifications[user._id].nodes[nodeid].mn = mesh.name;
497 + }
498 +
499 + // Cancel a device disconnect notification
500 + obj.cancelNotifyDeviceDisconnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
501 + const mesh = parent.webserver.meshes[meshid];
502 + if (mesh == null) return;
503 +
504 + if ((obj.deviceNotifications[user._id] != null) && (obj.deviceNotifications[user._id].nodes[nodeid] != null)) {
505 + const info = obj.deviceNotifications[user._id].nodes[nodeid];
506 + if ((info.d != null) && ((info.d & connectType) != 0)) {
507 + info.d -= connectType; // This device disconnect cancels out a device connection
508 + if (((info.c == null) || (info.c == 0)) && ((info.d == null) || (info.d == 0))) {
509 + // This device no longer needs a notification
510 + delete obj.deviceNotifications[user._id].nodes[nodeid];
511 + if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
512 + // This user no longer needs a notification
513 + clearTimeout(obj.deviceNotifications[user._id].timer);
514 + delete obj.deviceNotifications[user._id];
515 + }
516 + }
517 + }
518 + }
519 + }
520 +
521 + // A device disconnected and a user needs to be notified about it.
522 + obj.notifyDeviceDisconnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
523 + const mesh = parent.webserver.meshes[meshid];
524 + if (mesh == null) return;
525 +
526 + // Add the user and start a timer
527 + if (obj.deviceNotifications[user._id] == null) {
528 + obj.deviceNotifications[user._id] = { nodes: {} };
529 + obj.deviceNotifications[user._id].timer = setTimeout(function () { sendDeviceNotifications(user._id); }, 20000);
530 + }
531 +
532 + // Add the device
533 + if (obj.deviceNotifications[user._id].nodes[nodeid] == null) {
534 + obj.deviceNotifications[user._id].nodes[nodeid] = { d: connectType }; // This device disconnect need to be added
535 + } else {
536 + const info = obj.deviceNotifications[user._id].nodes[nodeid];
537 + if ((info.c != null) && ((info.c & connectType) != 0)) {
538 + info.c -= connectType; // This device disconnect cancels out a device connection
539 + if (((info.d == null) || (info.d == 0)) && ((info.c == null) || (info.c == 0))) {
540 + // This device no longer needs a notification
541 + delete obj.deviceNotifications[user._id].nodes[nodeid];
542 + if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
543 + // This user no longer needs a notification
544 + clearTimeout(obj.deviceNotifications[user._id].timer);
545 + delete obj.deviceNotifications[user._id];
546 + }
547 + return;
548 + }
549 + } else {
550 + if (info.d != null) {
551 + info.d |= connectType; // This device disconnect needs to be added
552 + } else {
553 + info.d = connectType; // This device disconnect needs to be added
554 + }
555 + }
556 + }
557 +
558 + // Set the device group name
559 + if ((extraInfo != null) && (extraInfo.name != null)) { obj.deviceNotifications[user._id].nodes[nodeid].nn = extraInfo.name; }
560 + obj.deviceNotifications[user._id].nodes[nodeid].mn = mesh.name;
561 + }
562 +
563 + // Cancel a device connect notification
564 + obj.cancelNotifyDeviceConnect = function (user, meshid, nodeid, connectTime, connectType, powerState, serverid, extraInfo) {
565 + const mesh = parent.webserver.meshes[meshid];
566 + if (mesh == null) return;
567 +
568 + if ((obj.deviceNotifications[user._id] != null) && (obj.deviceNotifications[user._id].nodes[nodeid] != null)) {
569 + const info = obj.deviceNotifications[user._id].nodes[nodeid];
570 + if ((info.c != null) && ((info.c & connectType) != 0)) {
571 + info.c -= connectType; // This device disconnect cancels out a device connection
572 + if (((info.d == null) || (info.d == 0)) && ((info.c == null) || (info.c == 0))) {
573 + // This device no longer needs a notification
574 + delete obj.deviceNotifications[user._id].nodes[nodeid];
575 + if (Object.keys(obj.deviceNotifications[user._id].nodes).length == 0) {
576 + // This user no longer needs a notification
577 + clearTimeout(obj.deviceNotifications[user._id].timer);
578 + delete obj.deviceNotifications[user._id];
579 + }
580 + }
581 + }
582 + }
583 + }
584 +
585 + // Send a notification about device connections and disconnections to a user
586 + function sendDeviceNotifications(userid) {
587 + if (obj.deviceNotifications[userid] == null) return;
588 + clearTimeout(obj.deviceNotifications[userid].timer);
589 +
590 + var connections = [];
591 + var disconnections = [];
592 +
593 + for (var nodeid in obj.deviceNotifications[userid].nodes) {
594 + var info = obj.deviceNotifications[userid].nodes[nodeid];
595 + if ((info.c != null) && (info.c > 0) && (info.nn != null) && (info.mn != null)) {
596 + var c = [];
597 + if (info.c & 1) { c.push("Agent"); }
598 + if (info.c & 2) { c.push("CIRA"); }
599 + if (info.c & 4) { c.push("AMT"); }
600 + if (info.c & 8) { c.push("AMT-Relay"); }
601 + if (info.c & 16) { c.push("MQTT"); }
602 + connections.push(info.mn + ', ' + info.nn + ': ' + c.join(', '));
603 + }
604 + if ((info.d != null) && (info.d > 0) && (info.nn != null) && (info.mn != null)) {
605 + var d = [];
606 + if (info.d & 1) { d.push("Agent"); }
607 + if (info.d & 2) { d.push("CIRA"); }
608 + if (info.d & 4) { d.push("AMT"); }
609 + if (info.d & 8) { d.push("AMT-Relay"); }
610 + if (info.d & 16) { d.push("MQTT"); }
611 + disconnections.push(info.mn + ', ' + info.nn + ': ' + d.join(', '));
612 + }
613 + }
614 +
615 + // TODO: Send the email
616 + //console.log('sendDeviceNotifications', connections, disconnections);
617 +
618 + delete obj.deviceNotifications[userid];
619 + }
620 +
621 return obj;
622 };
\ No newline at end of file
meshuser.js
+6
@@ -2112,6 +2112,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2112 {
2113 if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
2114
2115 + // 2 = WebPage device connections
2116 + // 4 = WebPage device disconnections
2117 + // 8 = WebPage device desktop and serial events
2118 + // 16 = Email device connections
2119 + // 32 = Email device disconnections
2120 +
2121 var err = null;
2122 try {
2123 // Change the current user's notification flags for a meshid
mpsserver.js
+6 -4
@@ -164,10 +164,10 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
164 if ((ciraArray != null) && ((ciraArray.indexOf(setConnFunc.socket) >= 0))) { // Check if this connection is still present
165 if (setConnFunc.socket.tag.connType == 0) {
166 // Intel AMT CIRA connection. This connection indicates the remote device is present.
167 - obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 2, 7); // 7 = Present
167 + obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 2, 7, null, { name: socket.tag.name }); // 7 = Present
168 } else if (setConnFunc.socket.tag.connType == 1) {
169 // Intel AMT Relay connection. This connection does not give any information about the remote device's power state.
170 - obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 8, 0); // 0 = Unknown
170 + obj.parent.SetConnectivityState(setConnFunc.socket.tag.meshid, setConnFunc.socket.tag.nodeid, setConnFunc.socket.tag.connectTime, 8, 0, null, { name: socket.tag.name }); // 0 = Unknown
171 }
172 // Intel AMT LMS connection (connType == 2), we don't notify of these connections except telling the Intel AMT manager about them.
173 // If the AMT manager is present, start management of this device
@@ -201,9 +201,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
201
202 // Update connectivity state
203 if (socket.tag.connType == 0) {
204 - obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2); // CIRA
204 + obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2, null, { name: socket.tag.name }); // CIRA
205 } else if (socket.tag.connType == 1) {
206 - obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 8); // Relay
206 + obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 8, null, { name: socket.tag.name }); // Relay
207 }
208 }
209
@@ -520,6 +520,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
520 // Node is already present
521 var node = nodes[0];
522 socket.tag.meshid = node.meshid; // Correct the MeshID if the node has moved.
523 + socket.tag.name = node.name;
524 if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
525 }
526
@@ -727,6 +728,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
728 // Node is already present
729 var node = nodes[0];
730 socket.tag.meshid = node.meshid;
731 + socket.tag.name = node.name;
732 if ((node.intelamt != null) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
733 }
734
mqttbroker.js
+2 -2
@@ -69,7 +69,7 @@ module.exports.CreateMQTTBroker = function (parent, db, args) {
69
70 if (obj.connections[client.xdbNodeKey] == null) {
71 obj.connections[client.xdbNodeKey] = [client];
72 - parent.SetConnectivityState(client.xdbMeshKey, client.xdbNodeKey, Date.now(), 16, 7); // Indicate this node has a MQTT connection, 7 = Present state
72 + parent.SetConnectivityState(client.xdbMeshKey, client.xdbNodeKey, Date.now(), 16, 7, null, { name: nodes[0].name }); // Indicate this node has a MQTT connection, 7 = Present state
73 } else {
74 obj.connections[client.xdbNodeKey].push(client);
75 }
@@ -85,7 +85,7 @@ module.exports.CreateMQTTBroker = function (parent, db, args) {
85 if (i >= 0) {
86 if (clients.length == 1) {
87 delete obj.connections[this.parent.xdbNodeKey];
88 - parent.ClearConnectivityState(this.parent.xdbMeshKey, this.parent.xdbNodeKey, 16); // Remove the MQTT connection for this node
88 + parent.ClearConnectivityState(this.parent.xdbMeshKey, this.parent.xdbNodeKey, 16, null, { name: nodes[0].name }); // Remove the MQTT connection for this node
89 } else { clients.splice(i, 1); }
90 }
91 }
multiserver.js
+2 -2
@@ -517,11 +517,11 @@ module.exports.CreateMultiServer = function (parent, args) {
517 break;
518 }
519 case 'SetConnectivityState': {
520 - obj.parent.SetConnectivityState(msg.meshid, msg.nodeid, msg.connectTime, msg.connectType, msg.powerState, peerServerId);
520 + obj.parent.SetConnectivityState(msg.meshid, msg.nodeid, msg.connectTime, msg.connectType, msg.powerState, peerServerId, msg.extraInfo);
521 break;
522 }
523 case 'ClearConnectivityState': {
524 - obj.parent.ClearConnectivityState(msg.meshid, msg.nodeid, msg.connectType, peerServerId);
524 + obj.parent.ClearConnectivityState(msg.meshid, msg.nodeid, msg.connectType, peerServerId, msg.extraInfo);
525 break;
526 }
527 case 'relay': {
translate/translate.json
+58 -58
@@ -18334,21 +18334,21 @@
18334 {
18335 "cs": "Připojení zařízení",
18336 "de": "Geräteverbindungen",
18337 - "en": "Device connections.",
18338 - "es": "Conexiones de dispositivo.",
18339 - "fi": "Laiteyhteydet.",
18340 - "fr": "Connexions des appareils.",
18337 + "en": "Device connections",
18338 + "es": "Conexiones de dispositivo",
18339 + "fi": "Laiteyhteydet",
18340 + "fr": "Connexions des appareils",
18341 "hi": "डिवाइस कनेक्शन।",
18342 - "it": "Connessioni del dispositivo.",
18342 + "it": "Connessioni del dispositivo",
18343 "ja": "デバイス接続。",
18344 - "ko": "장치가 연결되었습니다.",
18345 - "nl": "Apparaat verbindingen.",
18346 - "pl": "Połączenia urządzenia.",
18347 - "pt": "Conexões de dispositivos.",
18348 - "pt-br": "Conexões de dispositivos.",
18349 - "ru": "Подключения устройств.",
18350 - "sv": "Enhetsanslutningar.",
18351 - "tr": "Cihaz bağlantıları.",
18344 + "ko": "장치가 연결되었습니다",
18345 + "nl": "Apparaat verbindingen",
18346 + "pl": "Połączenia urządzenia",
18347 + "pt": "Conexões de dispositivos",
18348 + "pt-br": "Conexões de dispositivos",
18349 + "ru": "Подключения устройств",
18350 + "sv": "Enhetsanslutningar",
18351 + "tr": "Cihaz bağlantıları",
18352 "zh-chs": "设备连接。",
18353 "zh-cht": "裝置連接。",
18354 "xloc": [
@@ -18359,21 +18359,21 @@
18359 {
18360 "cs": "Odpojení zařízení",
18361 "de": "Gerätetrennungen",
18362 - "en": "Device disconnections.",
18363 - "es": "Desconexiones de dispositivo.",
18364 - "fi": "Laitteen irtikytkennät.",
18365 - "fr": "Déconnexions des appareils.",
18362 + "en": "Device disconnections",
18363 + "es": "Desconexiones de dispositivo",
18364 + "fi": "Laitteen irtikytkennät",
18365 + "fr": "Déconnexions des appareils",
18366 "hi": "डिवाइस डिस्कनेक्ट।",
18367 - "it": "Disconnessioni del dispositivo.",
18367 + "it": "Disconnessioni del dispositivo",
18368 "ja": "デバイスの切断。",
18369 - "ko": "장치 연결이 끊어졌습니다.",
18370 - "nl": "Apparaat verbroken.",
18371 - "pl": "Odłączenia urządzenia.",
18372 - "pt": "Desconexões de dispositivos.",
18373 - "pt-br": "Desconexões de dispositivos.",
18374 - "ru": "Отключения устройств.",
18375 - "sv": "Avbrott av enhet.",
18376 - "tr": "Cihaz bağlantılarının kesilmesi.",
18369 + "ko": "장치 연결이 끊어졌습니다",
18370 + "nl": "Apparaat verbroken",
18371 + "pl": "Odłączenia urządzenia",
18372 + "pt": "Desconexões de dispositivos",
18373 + "pt-br": "Desconexões de dispositivos",
18374 + "ru": "Отключения устройств",
18375 + "sv": "Avbrott av enhet",
18376 + "tr": "Cihaz bağlantılarının kesilmesi",
18377 "zh-chs": "设备断开连接。",
18378 "zh-cht": "裝置斷開連接。",
18379 "xloc": [
@@ -29049,25 +29049,25 @@
29049 ]
29050 },
29051 {
29052 - "cs": "Události Intel&reg; AMT desktop a serial.",
29052 + "cs": "Události Intel&reg; AMT desktop a serial",
29053 "de": "Intel&reg; AMT Desktop- und Seriell-Ereignisse",
29054 - "en": "Intel&reg; AMT desktop and serial events.",
29055 - "es": "Eventos de escritorio y serial de Intel&reg; AMT.",
29056 - "fi": "Intel&reg; AMT työpöytä ja sarjaliikenne ilmoitukset.",
29057 - "fr": "Événements de bureau et série Intel&reg; AMT.",
29054 + "en": "Intel&reg; AMT desktop and serial events",
29055 + "es": "Eventos de escritorio y serial de Intel&reg; AMT",
29056 + "fi": "Intel&reg; AMT työpöytä ja sarjaliikenne ilmoitukset",
29057 + "fr": "Événements de bureau et série Intel&reg; AMT",
29058 "hi": "Intel&reg; AMT डेस्कटॉप और सीरियल इवेंट।",
29059 - "it": "ntel & reg; Desktop AMT e eventi seriali.",
29059 + "it": "ntel & reg; Desktop AMT e eventi seriali",
29060 "ja": "Intel&reg; AMTデスクトップおよびシリアルイベント。",
29061 - "ko": "Intel&reg; AMT 데스크탑 및 직렬 이벤트.",
29062 - "nl": "Intel&reg; AMT desktop- en seriële gebeurtenissen.",
29063 - "pl": "Zdarzenia pulpitu i połączeń przewodowych Intel® AMT.",
29064 - "pt": "Intel&reg; Área de trabalho AMT e eventos seriais.",
29065 - "pt-br": "Desktop Intel&reg; AMT e eventos seriais.",
29066 - "ru": "События Intel&reg; AMT desktop или serial.",
29067 - "sv": "Intel&reg; AMT stationära och seriella händelser.",
29068 - "tr": "Intel&reg; AMT masaüstü ve seri etkinlikler.",
29069 - "zh-chs": "英特尔&reg;AMT桌面和串行事件。",
29070 - "zh-cht": "Intel&reg; AMT桌面和串行事件。",
29061 + "ko": "Intel&reg; AMT 데스크탑 및 직렬 이벤트",
29062 + "nl": "Intel&reg; AMT desktop- en seriële gebeurtenissen",
29063 + "pl": "Zdarzenia pulpitu i połączeń przewodowych Intel® AMT",
29064 + "pt": "Intel&reg; Área de trabalho AMT e eventos seriais",
29065 + "pt-br": "Desktop Intel&reg; AMT e eventos seriais",
29066 + "ru": "События Intel&reg; AMT desktop или serial",
29067 + "sv": "Intel&reg; AMT stationära och seriella händelser",
29068 + "tr": "Intel&reg; AMT masaüstü ve seri etkinlikler",
29069 + "zh-chs": "英特尔&reg;AMT桌面和串行事件",
29070 + "zh-cht": "Intel&reg; AMT桌面和串行事件",
29071 "xloc": [
29072 "default.handlebars->37->1640",
29073 "default.handlebars->37->1944"
@@ -40258,25 +40258,25 @@
40258 ]
40259 },
40260 {
40261 - "cs": "Zvuk upozornění.",
40261 + "cs": "Zvuk upozornění",
40262 "de": "Benachrichtigungston",
40263 - "en": "Notification sound.",
40264 - "es": "Sonido de notificación.",
40265 - "fi": "Ilmoitusääni.",
40266 - "fr": "Notification sonore.",
40263 + "en": "Notification sound",
40264 + "es": "Sonido de notificación",
40265 + "fi": "Ilmoitusääni",
40266 + "fr": "Notification sonore",
40267 "hi": "सूचना ध्वनि।",
40268 - "it": "Suono di notifica.",
40269 - "ja": "通知音。",
40270 - "ko": "알림 소리.",
40271 - "nl": "Meldingsgeluid.",
40272 - "pl": "Powiadomienie dźwiękowe.",
40273 - "pt": "Som de notificação.",
40274 - "pt-br": "Som de notificação.",
40268 + "it": "Suono di notifica",
40269 + "ja": "通知音",
40270 + "ko": "알림 소리",
40271 + "nl": "Meldingsgeluid",
40272 + "pl": "Powiadomienie dźwiękowe",
40273 + "pt": "Som de notificação",
40274 + "pt-br": "Som de notificação",
40275 "ru": "Звук уведомления",
40276 - "sv": "Notifikations ljud.",
40277 - "tr": "Bilgilendirme sesi.",
40278 - "zh-chs": "通知音效。",
40279 - "zh-cht": "通知音效。",
40276 + "sv": "Notifikations ljud",
40277 + "tr": "Bilgilendirme sesi",
40278 + "zh-chs": "通知音效",
40279 + "zh-cht": "通知音效",
40280 "xloc": [
40281 "default.handlebars->37->1636"
40282 ]
views/default.handlebars
+29 -10
@@ -10931,11 +10931,11 @@
10931 function account_showAccountNotifySettings() {
10932 if (xxdialogMode) return false;
10933 var x = '';
10934 - x += '<div><label><input id=p2notifyPlayNotifySound type=checkbox />' + "Notification sound." + '</label></div>';
10934 + x += '<div><label><input id=p2notifyPlayNotifySound type=checkbox />' + "Notification sound" + '</label></div>';
10935 x += '<div><label><input id=p2notifyGroupName type=checkbox />' + "Display device group name" + '</label></div>';
10936 - x += '<div><label><input id=p2notifyIntelDeviceConnect type=checkbox />' + "Device connections." + '</label></div>';
10937 - x += '<div><label><input id=p2notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections." + '</label></div>';
10938 - x += '<div><label><input id=p2notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events." + '</label></div>';
10936 + x += '<div><label><input id=p2notifyIntelDeviceConnect type=checkbox />' + "Device connections" + '</label></div>';
10937 + x += '<div><label><input id=p2notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections" + '</label></div>';
10938 + x += '<div><label><input id=p2notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events" + '</label></div>';
10939 setDialogMode(2, "Notification Settings", 3, account_showAccountNotifySettingsEx, x);
10940 var n = getstore('notifications', 0);
10941 Q('p2notifyPlayNotifySound').checked = (n & 1);
@@ -11344,6 +11344,10 @@
11344 if (meshNotify & 2) { meshNotifyStr.push("Connect"); }
11345 if (meshNotify & 4) { meshNotifyStr.push("Disconnect"); }
11346 if (meshNotify & 8) { meshNotifyStr.push("Intel&reg; AMT"); }
11347 + if ((features2 & 0x00004000) && (userinfo.emailVerified)) {
11348 + if (meshNotify & 16) { meshNotifyStr.push("Email Connect"); }
11349 + if (meshNotify & 32) { meshNotifyStr.push("Email Disconnect"); }
11350 + }
11351 if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "None" + '</i>'); }
11352 x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
11353 }
@@ -12262,23 +12266,38 @@
12266 function p20editMeshNotify() {
12267 if (xxdialogMode) return false;
12268 var meshNotify = 0;
12269 + var emailNotify = ((features2 & 0x00004000) && (userinfo.emailVerified));
12270 if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
12266 - var x = "Notification settings must also be turned on in account settings." + '<br /><br />';
12267 - x += '<div><label><input id=p20notifyIntelDeviceConnect type=checkbox />' + "Device connections." + '</label></div>';
12268 - x += '<div><label><input id=p20notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections." + '</label></div>';
12269 - x += '<div><label><input id=p20notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events." + '</label></div>';
12270 - setDialogMode(2, "Notification Settings", 3, p20editMeshNotifyEx, x);
12271 + //var x = "Notification settings must also be turned on in account settings." + '<br /><br />';
12272 + var x = '<div style="border-bottom: 1px solid #888;margin-bottom:3px">Web Page Notifications</div>';
12273 + x += '<div><label><input id=p20notifyIntelDeviceConnect type=checkbox />' + "Device connections" + '</label></div>';
12274 + x += '<div><label><input id=p20notifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections" + '</label></div>';
12275 + x += '<div><label><input id=p20notifyIntelAmtKvmActions type=checkbox />' + "Intel&reg; AMT desktop and serial events" + '</label></div>';
12276 + if (emailNotify) {
12277 + x += '<br /><div style="border-bottom: 1px solid #888;margin-bottom:3px">Email Notifications</div>';
12278 + x += '<div><label><input id=p20enotifyIntelDeviceConnect type=checkbox />' + "Device connections" + '</label></div>';
12279 + x += '<div><label><input id=p20enotifyIntelDeviceDisconnect type=checkbox />' + "Device disconnections" + '</label></div>';
12280 + }
12281 + setDialogMode(2, "Notification Settings", 3, p20editMeshNotifyEx, x, emailNotify);
12282 Q('p20notifyIntelDeviceConnect').checked = (meshNotify & 2);
12283 Q('p20notifyIntelDeviceDisconnect').checked = (meshNotify & 4);
12284 Q('p20notifyIntelAmtKvmActions').checked = (meshNotify & 8);
12285 + if (emailNotify) {
12286 + Q('p20enotifyIntelDeviceConnect').checked = (meshNotify & 16);
12287 + Q('p20enotifyIntelDeviceDisconnect').checked = (meshNotify & 32);
12288 + }
12289 return false;
12290 }
12291
12277 - function p20editMeshNotifyEx() {
12292 + function p20editMeshNotifyEx(b, emailNotify) {
12293 var meshNotify = 0;
12294 meshNotify += Q('p20notifyIntelDeviceConnect').checked ? 2 : 0;
12295 meshNotify += Q('p20notifyIntelDeviceDisconnect').checked ? 4 : 0;
12296 meshNotify += Q('p20notifyIntelAmtKvmActions').checked ? 8 : 0;
12297 + if (emailNotify) {
12298 + meshNotify += Q('p20enotifyIntelDeviceConnect').checked ? 16 : 0;
12299 + meshNotify += Q('p20enotifyIntelDeviceDisconnect').checked ? 32 : 0;
12300 + }
12301 meshserver.send({ action: 'changemeshnotify', meshid: currentMesh._id, notify: meshNotify });
12302 }
12303
webserver.js
+1
@@ -2829,6 +2829,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2829 if (domain.clipboardget == false) { features2 += 0x00000800; } // Disable clipboard get
2830 if (domain.clipboardset == false) { features2 += 0x00001000; } // Disable clipboard set
2831 if ((typeof domain.desktop == 'object') && (domain.desktop.viewonly == true)) { features2 += 0x00002000; } // Indicates remote desktop is viewonly
2832 + if (domain.mailserver != null) { features2 += 0x00004000; } // Indicates email server is active
2833 return { features: features, features2: features2 };
2834 }
2835