Added mesh screen to mobile web page
Ylian Saint-Hilaire committed
May 29, 2018 at 16:57 UTC
25b467b59212c4c773b4d87b58fa011880229f21
12 files changed
+444
-160
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/MeshService-signed.exe
Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ
agents/MeshService.exe
Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ
agents/MeshService64-signed.exe
Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ
agents/MeshService64.exe
Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ
meshcentral.js
+6
-2
@@ -99,7 +99,7 @@ function CreateMeshCentralServer(config, args) {
99
console.log(' --redirport [number] Creates an additional HTTP server to redirect users to the HTTPS server.');
100
console.log(' --exactports Server must run with correct ports or exit.');
101
console.log(' --noagentupdate Server will not update mesh agent native binaries.');
102
- console.log(' --cert [name], (country), (org) Create a web server certificate with [name]server name.');
102
+ console.log(' --cert [name], (country), (org) Create a web server certificate with [name] server name.');
103
console.log(' country and organization can optionaly be set.');
104
return;
105
}
@@ -1148,9 +1148,13 @@ function mainStart(args) {
1148
var config = getConfig();
1149
if (config == null) { process.exit(); }
1150
1151
+ // Check is Windows SSPI will be used
1152
+ var sspi = false;
1153
+ if (require('os').platform() == 'win32') { for (var i in config.domains) { if (config.domains[i].auth == 'sspi') { sspi = true; } } }
1154
+
1155
// Build the list of required modules
1156
var modules = ['ws', 'nedb', 'https', 'yauzl', 'xmldom', 'express', 'archiver', 'multiparty', 'node-forge', 'express-ws', 'compression', 'body-parser', 'connect-redis', 'express-session', 'express-handlebars'];
1153
- if (require('os').platform() == 'win32') { modules.push('node-sspi'); modules.push('node-windows'); } // Add Windows modules
1157
+ if (require('os').platform() == 'win32') { modules.push('node-windows'); if (sspi == true) { modules.push('node-sspi'); } } // Add Windows modules
1158
if (config.letsencrypt != null) { modules.push('greenlock'); modules.push('le-store-certbot'); modules.push('le-challenge-fs'); modules.push('le-acme-core'); } // Add Greenlock Modules
1159
if (config.settings.mongodb != null) { modules.push('mongojs'); } // Add MongoDB
1160
if (config.smtp != null) { modules.push('nodemailer'); } // Add SMTP support
meshuser.js
+1
-1
@@ -624,7 +624,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
624
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
625
626
if ((obj.common.validateString(command.meshname, 1, 64) == true) && (command.meshname != mesh.name)) { change = 'Mesh name changed from "' + mesh.name + '" to "' + command.meshname + '"'; mesh.name = command.meshname; }
627
- if ((obj.common.validateString(command.desc, 1, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Mesh "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
627
+ if ((obj.common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Mesh "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
628
if (change != '') { obj.db.Set(mesh); obj.parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, { etype: 'mesh', username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }) }
629
}
630
break;
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.1.7-s",
3
+ "version": "0.1.7-x",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
views/default-mobile.handlebars
+425
-145
@@ -20,58 +20,34 @@
20
text-decoration: underline;
21
}
22
23
- #footer a:hover {
24
- color: #fff;
25
- text-decoration: none;
26
- }
27
-
28
- .i1 {
29
- background: url(../images/icons50.png) 0px 0px;
30
- height: 50px;
31
- width: 50px;
32
- border: none;
33
- }
34
-
35
- .i2 {
36
- background: url(../images/icons50.png) -50px 0px;
37
- height: 50px;
38
- width: 50px;
39
- border: none;
40
- }
41
-
42
- .i3 {
43
- background: url(../images/icons50.png) -100px 0px;
44
- height: 50px;
45
- width: 50px;
46
- border: none;
47
- }
48
-
49
- .i4 {
50
- background: url(../images/icons50.png) -150px 0px;
51
- height: 50px;
52
- width: 50px;
53
- border: none;
54
- }
55
-
56
- .i5 {
57
- background: url(../images/icons50.png) -200px 0px;
58
- height: 50px;
59
- width: 50px;
60
- border: none;
23
+ #footer a:hover {
24
+ color: #fff;
25
+ text-decoration: none;
26
}
27
63
- .i6 {
64
- background: url(../images/icons50.png) -250px 0px;
65
- height: 50px;
66
- width: 50px;
67
- border: none;
68
- }
28
+ .i1 {background:url(../images/icons50.png) 0px 0px;height:50px;width:50px;border:none;}
29
+ .i2 {background:url(../images/icons50.png) -50px 0px;height:50px;width:50px;border:none;}
30
+ .i3 {background:url(../images/icons50.png) -100px 0px;height:50px;width:50px;border:none;}
31
+ .i4 {background:url(../images/icons50.png) -150px 0px;height:50px;width:50px;border:none;}
32
+ .i5 {background:url(../images/icons50.png) -200px 0px;height:50px;width:50px;border:none;}
33
+ .i6 {background:url(../images/icons50.png) -250px 0px; height:50px;width:50px; border:none; }
34
+ .m0 {background:url(../images/images16.png) -32px 0px; height:16px;width:16px; border:none;float:left }
35
+ .m1 {background:url(../images/images16.png) -16px 0px; height:16px;width:16px; border:none;float:left }
36
+ .m2 {background:url(../images/images16.png) -96px 0px; height:16px;width:16px; border:none;float:left }
37
+ .m3 {background:url(../images/images16.png) -112px 0px; height:16px;width:16px; border:none;float:left }
38
39
.gray {
40
/*filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");*/ /* Firefox 10+, Firefox on Android */
41
filter: gray; /* IE6-9 */
42
-webkit-filter: grayscale(100%) opacity(60%); /* Chrome 19+, Safari 6+, Safari 6+ iOS */
43
}
44
+
45
+ .DevSt {
46
+ padding-left:5px;
47
+ border-bottom-style: solid;
48
+ border-bottom-width: 1px;
49
+ border-bottom-color: #DDDDDD;
50
+ }
51
</style>
52
</head>
53
<body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif">
@@ -86,7 +62,7 @@
62
</div>
63
</div>
64
<div id=page_content style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
89
- <div id=column_l style="width:100%;height:calc(100hv - 82px)">
65
+ <div id=column_l style="width:100%;padding:0;position:absolute;bottom:0px;top:0px">
66
<div id=p0 style=display:none;width:100%;height:100%>
67
<div style="display:flex;align-items:center;width:100%;height:100%">
68
<div id=p0message style=text-align:center;width:100%>Server disconnected, <href onclick=reload() style=cursor:pointer><u>click to reconnect</u></href>.</div>
@@ -100,6 +76,51 @@
76
<div id=p2 style=display:none>
77
<div id=xdevices></div>
78
</div>
79
+ <div id=p10 style=display:none;position:absolute;bottom:0;top:0;width:100%>
80
+ <table cellspacing=0 style="margin:0;padding:0;border-spacing:0;border:0;">
81
+ <tr style=padding:0>
82
+ <td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width=60px valign=top onclick=goBack()>
83
+ <div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
84
+ <div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
85
+ </div>
86
+ <div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
87
+ </td>
88
+ <td>
89
+ <a id=MainComputerImage style=cursor:pointer onclick=p10showiconselector()></a>
90
+ </td>
91
+ <td>
92
+ <div style=margin-left:5px>
93
+ <strong><span id=p10deviceName></span></strong><br />
94
+ <span id=MainComputerState></span>
95
+ </div>
96
+ </td>
97
+ </tr>
98
+ </table>
99
+ <div id=p10html style="margin-left:8px;margin-right:8px"></div>
100
+ <div id=p10html2></div>
101
+ <div id=p10html3></div>
102
+ </div>
103
+ <div id=p20 style=display:none;position:absolute;bottom:0;top:0;width:100%>
104
+ <table cellspacing=0 style="margin:0;padding:0;border-spacing:0;border:0;">
105
+ <tr style=padding:0>
106
+ <td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width=60px valign=top onclick=goBack()>
107
+ <div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
108
+ <div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
109
+ </div>
110
+ <div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
111
+ </td>
112
+ <td onclick="p20editmesh(1)">
113
+ <img src="/images/meshicon50.png" width=50 height=50 />
114
+ </td>
115
+ <td onclick="p20editmesh(1)">
116
+ <div style=margin-left:5px>
117
+ <strong style="font-size:large"><span id=p20meshName></span></strong><br />
118
+ </div>
119
+ </td>
120
+ </tr>
121
+ </table>
122
+ <div id=p20info style="margin-left:8px;margin-right:8px"></div>
123
+ </div>
124
</div>
125
</div>
126
<div id=footer style="height:32px;width:100%;text-align:center;background-color:#113962;position:absolute;bottom:0px">
@@ -111,7 +132,7 @@
132
</table>
133
</div>
134
</div>
114
- <div id=dialog style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:180px;width:400px;display:none">
135
+ <div id=dialog style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:90px;width:300px;display:none">
136
<div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
137
<div id=id_dialogclose style=float:right;padding:5px;cursor:pointer onclick=setDialogMode()><b>X</b></div>
138
<div id=id_dialogtitle style=padding:5px></div>
@@ -225,9 +246,9 @@
246
break;
247
}
248
case 'files': {
228
- filetree = setupBackPointers(message.filetree);
229
- updateFiles();
230
- d3updatefiles();
249
+ //filetree = setupBackPointers(message.filetree);
250
+ //updateFiles();
251
+ //d3updatefiles();
252
break;
253
}
254
case 'nodes': {
@@ -401,12 +422,12 @@
422
if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; }
423
}
424
node.namel = node.name.toLowerCase();
404
- if (node.host) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
425
+ if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
426
if (message.event.node.icon) { node.icon = message.event.node.icon; }
427
428
//onSortSelectChange(true);
429
//drawNotifications();
409
- //refreshDevice(node._id);
430
+ refreshDevice(node._id);
431
//updateMapMarkers();
432
updateDevices();
433
@@ -422,8 +443,8 @@
443
var node = nodes[index];
444
445
// Change the node connection state
425
- //node.conn = message.event.conn;
426
- //node.pwr = message.event.pwr;
446
+ node.conn = message.event.conn;
447
+ node.pwr = message.event.pwr;
448
updateDevices();
449
//updateMapMarkers();
450
//refreshDevice(node._id);
@@ -462,19 +483,27 @@
483
// MY DEVICES
484
//
485
486
+ var backStack = [];
487
+ function goBack() { if (backStack.length == 0) { goMyDevices(); } else { gotoDevice(backStack.pop()); } }
488
+ function goMyDevices() { go(2); }
489
+
490
var sort = 0;
491
var deviceHeaderId = 0;
492
var deviceHeaderCount;
493
var deviceHeaders = {};
494
+ var showRealNames = false;
495
+ var deviceHeaderTotal = 0;
496
+ var deviceHeaders = {};
497
+ var deviceHeadersTitles = {};
498
function updateDevices() {
499
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, groups = {}, groupCount = {};
500
501
// 3 wide, list view or desktop view
502
deviceHeaderId = 0;
503
deviceHeaderCount = {};
475
- var deviceHeaderTotal = 0;
476
- var deviceHeaders = {};
477
- var deviceHeadersTitles = {};
504
+ deviceHeaderTotal = 0;
505
+ deviceHeaders = {};
506
+ deviceHeadersTitles = {};
507
var current;
508
509
// Go thru the list of nodes and display them
@@ -484,17 +513,17 @@
513
if (meshlinks == null) continue;
514
var meshrights = meshlinks.rights;
515
487
- /*
516
if (sort == 0) {
517
// Mesh header
518
+ nodes.sort(meshSort);
519
if (nodes[i].meshid != current) {
491
- //deviceHeaderSet();
520
+ deviceHeaderSet();
521
var extra = '';
493
- if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span class=devHeaderx>, Intel® AMT only</span>'; }
522
+ if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span style=color:lightgray>, Intel® AMT only</span>'; }
523
if (current != null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
495
- r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
524
+ r += '<div class=DevSt style=padding-top:4px><span style=float:right>';
525
//r += getMeshActions(mesh2, meshrights);
497
- r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span></div>';
526
+ r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
527
current = nodes[i].meshid;
528
displayedMeshes[current] = 1;
529
c = 0;
@@ -502,9 +531,9 @@
531
} else if (sort == 1) {
532
// Power header
533
if (nodes[i].pwr !== current) {
505
- //deviceHeaderSet();
534
+ deviceHeaderSet();
535
if (current !== null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
507
- r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></div>';
536
+ r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
537
current = nodes[i].pwr;
538
c = 0;
539
}
@@ -512,29 +541,23 @@
541
// Device header
542
if (current == null) { current = '1'; }
543
}
515
- */
516
-
544
545
count++;
546
var title = EscapeHtml(nodes[i].name);
547
if (title.length == 0) { title = '<i>None</i>'; }
548
if ((nodes[i].rname != null) && (nodes[i].rname.length > 0)) { title += " / " + EscapeHtml(nodes[i].rname); }
549
var name = EscapeHtml(nodes[i].name);
523
- //if (showRealNames == true && nodes[i].rname != null) name = EscapeHtml(nodes[i].rname);
550
+ if (showRealNames == true && nodes[i].rname != null) name = EscapeHtml(nodes[i].rname);
551
if (name.length == 0) { name = '<i>None</i>'; }
552
553
// Node
527
- var icon = nodes[i].icon;
528
- var nodestate = NodeStateStr(nodes[i]);
554
+ var icon = nodes[i].icon, nodestate = NodeStateStr(nodes[i]);
555
if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
530
- //var title = '';
531
- //r += '<div id=devs style=display:inline-block;width:301px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 title="' + title + '">' + name + '</div><div>' + nodestate + '</div></div><div class=g2></div></div></div></div>';
532
- r += '<div>';
556
+ r += '<div style=cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')>';
557
r += '<div class="i' + icon + '" style="float:left;margin-left:4px"></div>';
534
- r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;cursor:pointer;border-radius:8px 0px 0px 8px">';
558
+ r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">';
559
r += '<div><div style=padding-left:12px;padding-top:2px><b>' + name + '</b></div><div style=padding-left:12px;padding-top:3px;color:gray>' + nodestate + '</div></div>';
536
- r += '</div>';
537
- r += '</div>';
560
+ r += '</div></div>';
561
562
// If we are displaying devices by group, put the device in the right group.
563
/*
@@ -554,9 +577,39 @@
577
if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
578
}
579
580
+ // Display all empty meshes, we need to do this because users can add devices to these at any time.
581
+ if (sort == 0) {
582
+ for (var i in meshes) {
583
+ var mesh = meshes[i], meshlink = mesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
584
+ if (meshlink != null) {
585
+ var meshrights = meshlink.rights;
586
+ if (displayedMeshes[mesh._id] == null) {
587
+ if ((current != '') && (r != '')) { r += '</tr></table>'; }
588
+ r += '<div><div colspan=3 class=DevSt><span style=float:right>';
589
+ //r += getMeshActions(mesh, meshrights);
590
+ r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></div>';
591
+ if (mesh.mtype == 1) { r += '<div style=padding:10px><i>No Intel® AMT devices in this mesh'; }
592
+ if (mesh.mtype == 2) { r += '<div style=padding:10px><i>No devices in this mesh'; }
593
+ r += '.</i></div></div>';
594
+ current = mesh._id;
595
+ count++;
596
+ }
597
+ }
598
+ }
599
+ }
600
+
601
QH('xdevices', r);
602
+ deviceHeaderSet();
603
+ for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
604
+ for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
605
+ }
606
+
607
+ function gotoMeshStack(meshid) {
608
+ backStack.push(currentNode._id);
609
+ gotoMesh(meshid);
610
}
611
612
+ var powerStatetable = ['', 'Powered', 'Sleep', 'Sleep', 'Sleep', 'Hibernating', 'Power off', 'Present'];
613
var powerStateStrings = ['', '<span title="Device is powered on.">Powered</span>', '<span title="Device is in sleep state (S1).">Sleeping</span>', '<span title="Device is in sleep state (S2).">Sleeping</span>', '<span title="Device is in deep sleep state (S3).">Deep Sleep</span>', '<span title="Device is in hibernating state (S4).">Hibernating</span>', '<span title="Device is in powered off state (S5).">Soft-Off</span>', '<span title="Device is detected but power state could not be obtained.">Present</span>'];
614
var powerStateStrings2 = ['', 'Device is powered', 'Device is in sleep state (S1)', 'Device is in sleep state (S2)', 'Device is in deep sleep state (S3)', 'Device is hibernating (S4)', 'Device is in soft-off state (S5)', 'Device is present, but power state cannot be determined'];
615
var powerColorTable = ['#00000000', 'black', 'blue', 'blue', 'lightblue', 'blueviolet', 'darkgreen', 'lightseagreen', 'lightseagreen'];
@@ -583,6 +636,31 @@
636
return 'Unknown';
637
}
638
639
+ function onSortSelectChange(skipsave) {
640
+ sort = document.getElementById("sortselect").selectedIndex;
641
+ if (!skipsave) { putstore("sort", sort); }
642
+ if (sort == 0) { nodes.sort(meshSort); }
643
+ if (sort == 1) { nodes.sort(powerSort); }
644
+ if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
645
+ updateDevices();
646
+ }
647
+
648
+ function deviceHeaderSet() {
649
+ if (deviceHeaderId == 0) { deviceHeaderId = 1; return; }
650
+ deviceHeaders["DevxHeader" + deviceHeaderId] = ', ' + deviceHeaderTotal + ((deviceHeaderTotal == 1) ? ' node' : ' nodes');
651
+ var title = '';
652
+ for (x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); }
653
+ deviceHeadersTitles["DevxHeader" + deviceHeaderId] = title;
654
+ deviceHeaderId++;
655
+ deviceHeaderCount = {};
656
+ deviceHeaderTotal = 0;
657
+ }
658
+
659
+ function meshSort(a, b) { if (a.meshnamel > b.meshnamel) return 1; if (a.meshnamel < b.meshnamel) return -1; if (a.meshid == b.meshid) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } return 0; }
660
+ function powerSort(a, b) { var ap = a.pwr?a.pwr:0; var bp = b.pwr?b.pwr:0; if (ap == bp) { if (showRealNames == true) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; } else { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; } } if (ap > bp) return 1; if (ap < bp) return -1; return 0; }
661
+ function deviceSort(a, b) { if (a.namel > b.namel) return 1; if (a.namel < b.namel) return -1; return 0; }
662
+ function deviceHostSort(a, b) { if (a.rnamel > b.rnamel) return 1; if (a.rnamel < b.rnamel) return -1; return 0; }
663
+
664
//
665
// MY DEVICE
666
//
@@ -604,9 +682,7 @@
682
var powerTimeline = null;
683
function getCurrentNode() { return currentNode; };
684
function gotoDevice(nodeid, panel, refresh) {
607
- //disconnectAllKvmFunction();
608
- var node = getNodeFromId(nodeid);
609
- var mesh = meshes[node.meshid];
685
+ var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
686
var meshrights = mesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
687
if (!currentNode || currentNode._id != node._id || refresh == true) {
688
currentNode = node;
@@ -616,18 +692,20 @@
692
if (nname.length == 0) { nname = '<i>None</i>'; }
693
if ((meshrights & 4) != 0) { nname = '<span onclick=showEditNodeValueDialog(0) style=cursor:pointer>' + nname + '</span>'; }
694
QH('p10deviceName', nname);
695
+ /*
696
QH('p11deviceName', nname);
697
QH('p12deviceName', nname);
698
QH('p13deviceName', nname);
699
QH('p14deviceName', nname);
700
QH('p15deviceName', nname);
701
QH('p16deviceName', nname);
702
+ */
703
704
// Node attributes
705
var x = '<table style=width:100%>';
706
707
// Attribute: Mesh
630
- x += addDeviceAttribute('<span title="The name of the administrative group this computer belong to">Mesh</span>', '<a title="The name of the group this computer belong to" onclick=gotoMesh("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
708
+ x += addDeviceAttribute('<span title="The name of the administrative group this computer belong to">Mesh</span>', '<a title="The name of the group this computer belong to" onclick=gotoMeshStack("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
709
710
// Attribute: Name
711
if (node.rname != null) { x += addDeviceAttribute('<span title="The name of this computer as set in the operating system">Name</span>', '<span title="The name of this computer as set in the operating system">' + EscapeHtml(node.rname) + '</span>'); }
@@ -676,12 +754,12 @@
754
if (node.intelamt.state == 2) {
755
if (node.intelamt.user == null || node.intelamt.user == '') {
756
if ((meshrights & 4) != 0) {
679
- str += ', <i style=color:#FF0000;cursor:pointer title="Edit Intel® AMT credentials" onclick=editDeviceAmtSettings("' + node._id + '")>No Credentials</i>';
757
+ str += ', <i style=color:#FF0000;cursor:pointer title="Edit Intel® AMT credentials" onclick=editDeviceAmtSettings("' + node._id + '")>No Credentials</i>';
758
} else {
681
- str += ', <i style=color:#FF0000>No Credentials</i>';
759
+ str += ', <i style=color:#FF0000>No Credentials</i>';
760
}
761
}
684
- str += ' ';
762
+ str += ' ';
763
if ((meshrights & 4) != 0) {
764
str += '<img src=images/link4.png height=10 width=10 title="Edit Intel® AMT credentials" style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
765
}
@@ -717,31 +795,20 @@
795
796
x += '</table><br />';
797
// Show action button, only show if we have permissions 4, 8, 64
720
- if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
721
- x += '<input type=button value=Notes title="View notes about this device" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
798
+ //if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
799
+ //x += '<input type=button value=Notes title="View notes about this device" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
800
//if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="Display a text message of the remote device" onclick=deviceToastFunction() />'; }
801
QH('p10html', x);
802
803
// Show node last 7 days timeline
726
- drawDeviceTimeline();
804
+ //drawDeviceTimeline();
805
806
// Show bottom buttons
807
x = '<div style=float:right;font-size:x-small>';
730
- if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '") title="Remove this device">Delete Device</a>';
808
+ //if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '") title="Remove this device">Delete Device</a>';
809
x += '</div><div style=font-size:x-small>';
732
- if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '") title="Show device network interface information">Interfaces</a> ';
733
- if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '") title="Show device locations information">Location</a> ';
734
-
735
- if (((meshrights & 8) != 0) && (mesh.mtype == 2)) x += '<a style=cursor:pointer onclick=p10showMeshCmdDialog(1,"' + node._id + '") title="Traffic router used to connect to a device thru this server.">Router</a> ';
736
-
737
- // RDP link, show this link only of the remote machine is Windows.
738
- if (((connectivity & 1) != 0) && (clickOnce == true) && (mesh.mtype == 2) && ((meshrights & 8) != 0)) {
739
- if ((node.agent.id > 0) && (node.agent.id < 5)) { x += '<a style=cursor:pointer onclick=p10clickOnce("' + node._id + '","RDP2",3389) title="Requires Microsoft ClickOnce support in your browser.">RDP</a> '; }
740
- if (node.agent.id > 4) {
741
- x += '<a style=cursor:pointer onclick=p10clickOnce("' + node._id + '","PSSH",22) title="Requires Microsoft ClickOnce support in your browser.">Putty</a> ';
742
- x += '<a style=cursor:pointer onclick=p10clickOnce("' + node._id + '","WSCP",22) title="Requires Microsoft ClickOnce support in your browser.">WinSCP</a> ';
743
- }
744
- }
810
+ //if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '") title="Show device network interface information">Interfaces</a> ';
811
+ //if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '") title="Show device locations information">Location</a> ';
812
x += '</div><br>'
813
814
QH('p10html3', x);
@@ -749,60 +816,269 @@
816
// Set the node power state
817
powerstate = PowerStateStr(node.state);
818
//if (node.state == 0) { powerstate = 'Unknown State'; }
752
- if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title="Agent connected">Agent connected</span>'; }
753
- if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title="Intel® AMT connected">Intel® AMT connected</span>'; }
754
- if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += '<br/>'; } powerstate += '<span style=font-size:12px title="Intel® AMT detected">Intel® AMT detected</span>'; }
819
+ if ((connectivity & 1) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px title="Agent connected">Mesh Agent</span>'; }
820
+ if ((connectivity & 2) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px title="Intel® AMT connected">Intel® AMT connected</span>'; } else
821
+ if ((connectivity & 4) != 0) { if (powerstate.length > 0) { powerstate += ', '; } powerstate += '<span style=font-size:10px title="Intel® AMT detected">Intel® AMT detected</span>'; }
822
QH('MainComputerState', powerstate);
823
824
// Set the node icon
758
- Q('MainComputerImage').setAttribute("src", "images/icons200-" + node.icon + "-1.png");
759
- Q('MainComputerImage').className = ((!node.conn) || (node.conn == 0)?'gray':'');
760
-
761
- // Setup/Refresh the desktop tab
762
- setupTerminal();
763
- setupFiles();
764
- var consoleRights = ((meshrights & 16) != 0);
765
- if (consoleRights) { setupConsole(); } else { if (panel == 15) { panel = 10; } }
766
-
767
- // Show or hide the tabs
768
- // mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent
769
- // node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console
770
- QV('MainDevDesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0)) && (meshrights & 8));
771
- QV('MainDevTerminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0)) && (meshrights & 8));
772
- QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8));
773
- QV('MainDevAmt', (node.intelamt != null) && (node.intelamt.state == 2) && (meshrights & 8));
774
- QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
775
- QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0) && (userinfo.siteadmin == 0xFFFFFFFF));
776
- QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
777
-
778
- // Setup/Refresh Intel AMT tab
779
- var amtFrameNode = Q('p14iframe').contentWindow.getCurrentMeshNode();
780
- if ((amtFrameNode != null) && (amtFrameNode._id != currentNode._id)) { Q('p14iframe').contentWindow.disconnect(); }
781
- var online = ((node.conn & 6) != 0)?true:false; // If CIRA (2) or AMT (4) connected, enable Commander
782
- Q('p14iframe').contentWindow.setConnectionState(online);
783
- Q('p14iframe').contentWindow.setFrameHeight('650px');
784
- Q('p14iframe').contentWindow.setAuthCallback(updateAmtCredentials);
785
-
786
- // Display "action" button on desktop/terminal/files
787
- QV('deskActionsBtn', (meshrights & 72) != 0); // 72 = Wake-up + Remote Control permissions
788
- QV('termActionsBtn', (meshrights & 72) != 0);
789
- QV('filesActionsBtn', (meshrights & 72) != 0);
790
-
791
- // Request the power timeline
792
- if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
793
-
794
- // Reset the desktop tools
795
- QV('DeskTools', false);
796
- showDeskToolsProcesses();
797
-
798
- // Ask for device events
799
- //refreshDeviceEvents();
825
+ QH('MainComputerImage', '<div class="i' + node.icon + '"></div>');
826
}
801
- setupDesktop(); // Always refresh the desktop, even if we are on the same device, we need to do some canvas switching.
827
if (!panel) panel = 10;
828
go(panel);
829
}
830
831
+ function addDeviceAttribute(name, value) {
832
+ return '<tr><td style=width:100px;color:gray>' + name + '</td><td style=overflow:hidden>' + value + '</td></tr>';
833
+ }
834
+
835
+ function p10showiconselector() {
836
+ if (xxdialogMode) return;
837
+ var mesh = meshes[currentNode.meshid];
838
+ var meshrights = mesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
839
+ if ((meshrights & 4) == 0) return;
840
+
841
+ var x = '<table align=center><td>';
842
+ x += '<div style=display:inline-block class=i1 onclick=p10setIcon(1)></div>';
843
+ x += '<div style=display:inline-block class=i2 onclick=p10setIcon(2)></div>';
844
+ x += '<div style=display:inline-block class=i3 onclick=p10setIcon(3)></div><br>';
845
+ x += '<div style=display:inline-block class=i4 onclick=p10setIcon(4)></div>';
846
+ x += '<div style=display:inline-block class=i5 onclick=p10setIcon(5)></div>';
847
+ x += '<div style=display:inline-block class=i6 onclick=p10setIcon(6)></div></table>';
848
+ setDialogMode(2, "Icon Selection", 0, null, x);
849
+ QV('id_dialogclose', true);
850
+ }
851
+
852
+ function p10setIcon(icon) {
853
+ setDialogMode(0);
854
+ meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
855
+ }
856
+
857
+ var showEditNodeValueDialog_modes = ['Device Name', 'Hostname', 'Description', 'Groups'];
858
+ var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
859
+ var showEditNodeValueDialog_modes3 = ['', '', '', 'Group1, Group2, Group3'];
860
+ function showEditNodeValueDialog(mode) {
861
+ if (xxdialogMode) return;
862
+ var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue style=width:170px maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
863
+ setDialogMode(2, "Edit Device", 3, showEditNodeValueDialogEx, x, mode);
864
+ var v = currentNode[showEditNodeValueDialog_modes2[mode]];
865
+ if (v == null) v = '';
866
+ if (Array.isArray(v)) { v = v.join(', '); }
867
+ Q('dp10devicevalue').value = v;
868
+ p10editdevicevalueValidate();
869
+ Q('dp10devicevalue').focus();
870
+ }
871
+
872
+ function showEditNodeValueDialogEx(button, mode) {
873
+ var x = { action: 'changedevice', nodeid: currentNode._id };
874
+ x[showEditNodeValueDialog_modes2[mode]] = Q('dp10devicevalue').value;
875
+ meshserver.send(x);
876
+ }
877
+
878
+ function p10editdevicevalueValidate(mode, e) {
879
+ var x = ((mode > 1) || (Q('dp10devicevalue').value.length > 0));
880
+ QE('idx_dlgOkButton', x);
881
+ if ((e != null) && (x == true) && (e.keyCode == 13)) { dialogclose(1); }
882
+ }
883
+
884
+ //
885
+ // MY ACCOUNT
886
+ //
887
+
888
+ function gotoMesh(meshid) {
889
+ currentMesh = meshes[meshid];
890
+ p20updateMesh();
891
+ go(20);
892
+ }
893
+
894
+
895
+ //
896
+ // MY MESHS
897
+ //
898
+
899
+ var currentMesh;
900
+ function p20updateMesh() {
901
+ QH('p20meshName', EscapeHtml(currentMesh.name));
902
+ var meshtype = 'Unknown #' + currentMesh.mtype;
903
+ var meshrights = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
904
+ if (currentMesh.mtype == 1) meshtype = 'Intel® AMT group';
905
+ if (currentMesh.mtype == 2) meshtype = 'Mesh agent group';
906
+
907
+ var x = '';
908
+ x += addHtmlValue('Name', addLinkConditional(EscapeHtml(currentMesh.name), 'p20editmesh(1)', (meshrights & 1) != 0));
909
+ x += addHtmlValue('Description', addLinkConditional(((currentMesh.desc && currentMesh.desc != '')?EscapeHtml(currentMesh.desc):'<i>None</i>'), 'p20editmesh(2)', (meshrights & 1) != 0));
910
+ x += addHtmlValue('Type', meshtype);
911
+ //x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
912
+
913
+ //x += '<br><input type=button value=Notes title="View notes about this mesh" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />';
914
+
915
+ x += '<br style=clear:both><br>';
916
+ var currentMeshLinks = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
917
+ if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a onclick=p20showAddMeshUserDialog() style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Add User</a>'; }
918
+
919
+ /*
920
+ if ((meshrights & 4) != 0) {
921
+ if (currentMesh.mtype == 1) {
922
+ x += '<a onclick=addCiraDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px title="Add a new Intel® AMT computer that is located on the internet."><img src=images/icon-installmesh.png border=0 height=12 width=12> Install CIRA</a>';
923
+ x += '<a onclick=addDeviceToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px title="Add a new Intel® AMT computer that is located on the local network."><img src=images/icon-installmesh.png border=0 height=12 width=12> Install local</a>';
924
+ }
925
+ if (currentMesh.mtype == 2) {
926
+ x += '<a onclick=addAgentToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px title="Add a new computer to this mesh by installing the mesh agent."><img src=images/icon-addnew.png border=0 height=12 width=12> Install</a>';
927
+ }
928
+ }
929
+ */
930
+
931
+ /*
932
+ function getMeshActions(mesh, meshrights) {
933
+ if ((meshrights & 4) == 0) return '';
934
+ var r = '';
935
+ if (mesh.mtype == 1) {
936
+ r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel® AMT computer that is located on the internet." onclick=addCiraDeviceToMesh(\"' + mesh._id + '\")>Add CIRA</a>';
937
+ r += ' <a style=cursor:pointer;font-size:10px title="Add a new Intel® AMT computer that is located on the local network." onclick=addDeviceToMesh(\"' + mesh._id + '\")>Add Local</a>';
938
+ }
939
+ if (mesh.mtype == 2) {
940
+ r += ' <a style=cursor:pointer;font-size:10px title="Add a new computer to this mesh by installing the mesh agent." onclick=addAgentToMesh(\"' + mesh._id + '\")>Add Agent</a>';
941
+ }
942
+ return r;
943
+ }
944
+ */
945
+
946
+ 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>User Authorizations</th><th scope=col style=text-align:left></th></tr>';
947
+
948
+ // Sort the users for this mesh
949
+ var count = 1, sortedusers = [];
950
+ for (var i in currentMesh.links) { sortedusers.push({ id: i, name: i.split('/')[2], rights: currentMesh.links[i].rights }); }
951
+ sortedusers.sort(function(a, b) { if (a.name > b.name) return 1; if (a.name < b.name) return -1; return 0; });
952
+
953
+ // Display all users for this mesh
954
+ for (var i in sortedusers) {
955
+ var trash = '', rights = 'Partial Rights', r = sortedusers[i].rights;
956
+ if (r == 0xFFFFFFFF) rights = 'Full Administrator'; else if (r == 0) rights = 'No Rights';
957
+ if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") title="Remote user rights to this mesh" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
958
+ x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=height:32px;cursor:pointer' + (((count % 2) == 0)?';background-color:#DDD':'') + '><td>';
959
+ x += '<div style=float:right>' + trash + '</div><div style=float:right;padding-right:4px>' + rights + '</div><div class=m2></div><div> ' + sortedusers[i].name + '<div></div></div>';
960
+ x += '</td></tr>';
961
+ ++count;
962
+ }
963
+
964
+ x += '</tbody></table>';
965
+
966
+ // If we are full administrator on this mesh, allow deletion of the mesh
967
+ if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:x-small;text-align:right><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>Delete Mesh</a></span></div>'; }
968
+
969
+ QH('p20info', x);
970
+ }
971
+
972
+
973
+ function p20showDeleteMeshDialog() {
974
+ if (xxdialogMode) return;
975
+ var x = "Are you sure you want to delete mesh \"" + EscapeHtml(currentMesh.name) + "\"? Deleting the mesh will also delete all information about computers within this mesh.<br /><br />";
976
+ x += "<input id=p20check type=checkbox onchange=p20validateDeleteMeshDialog() />Confirm";
977
+ setDialogMode(2, "Delete Mesh", 3, p20showDeleteMeshDialogEx, x);
978
+ p20validateDeleteMeshDialog();
979
+ }
980
+
981
+ function p20validateDeleteMeshDialog() {
982
+ QE('idx_dlgOkButton', Q('p20check').checked);
983
+ }
984
+
985
+ function p20showDeleteMeshDialogEx(buttons, tag) {
986
+ meshserver.send({ action: 'deletemesh', meshid: currentMesh._id, meshname: currentMesh.name });
987
+ }
988
+
989
+ function p20editmesh(focus) {
990
+ if (xxdialogMode) return;
991
+ var x = addHtmlValue('Name', '<input id=dp20meshname style=width:170px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
992
+ x += addHtmlValue('Description', '<input id=dp20meshdesc style=width:170px maxlength=1024 onkeyup=p20editmeshValidate() />');
993
+ setDialogMode(2, "Edit Mesh", 3, p20editmeshEx, x);
994
+ Q('dp20meshname').value = currentMesh.name;
995
+ if (currentMesh.desc) Q('dp20meshdesc').value = currentMesh.desc;
996
+ p20editmeshValidate();
997
+ if (focus == 2) { Q('dp20meshdesc').focus(); } else { Q('dp20meshname').focus(); }
998
+ }
999
+
1000
+ function p20editmeshEx() {
1001
+ meshserver.send({ action: 'editmesh', meshid: currentMesh._id, meshname: Q('dp20meshname').value, desc: Q('dp20meshdesc').value });
1002
+ }
1003
+
1004
+ function p20editmeshValidate() {
1005
+ QE('idx_dlgOkButton', Q('dp20meshname').value.length > 0);
1006
+ }
1007
+
1008
+ function p20showAddMeshUserDialog() {
1009
+ if (xxdialogMode) return;
1010
+ var x = addHtmlValue('User', '<input id=dp20username style=width:170px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />');
1011
+ x += '<div style="border:2px groove gray;background-color:white;max-height:80px;overflow-y:scroll">';
1012
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Full Administrator<br>';
1013
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>Edit Mesh<br>';
1014
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20manageusers>Manage Mesh Users<br>';
1015
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20managecomputers>Manage Mesh Computers<br>';
1016
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20remotecontrol>Remote Control<br>';
1017
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>Mesh Agent Console<br>';
1018
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>Server Files<br>';
1019
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Wake Devices<br>';
1020
+ x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Device Notes<br>';
1021
+ x += '</div>';
1022
+ setDialogMode(2, "Add User to Mesh", 3, p20showAddMeshUserDialogEx, x);
1023
+ p20validateAddMeshUserDialog();
1024
+ Q('dp20username').focus();
1025
+ }
1026
+
1027
+ function p20validateAddMeshUserDialog() {
1028
+ var meshrights = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
1029
+ QE('idx_dlgOkButton', (Q('dp20username').value.length > 0));
1030
+ QE('p20fulladmin', meshrights == 0xFFFFFFFF);
1031
+ QE('p20editmesh', (!Q('p20fulladmin').checked) && (meshrights == 0xFFFFFFFF));
1032
+ QE('p20manageusers', !Q('p20fulladmin').checked);
1033
+ QE('p20managecomputers', !Q('p20fulladmin').checked);
1034
+ QE('p20remotecontrol', !Q('p20fulladmin').checked);
1035
+ QE('p20meshagentconsole', !Q('p20fulladmin').checked);
1036
+ QE('p20meshserverfiles', !Q('p20fulladmin').checked);
1037
+ QE('p20wakedevices', !Q('p20fulladmin').checked);
1038
+ QE('p20editnotes', !Q('p20fulladmin').checked);
1039
+ }
1040
+
1041
+ function p20showAddMeshUserDialogEx() {
1042
+ var meshadmin = 0;
1043
+ if (Q('p20fulladmin').checked == true) { meshadmin = 0xFFFFFFFF; } else {
1044
+ if (Q('p20editmesh').checked == true) meshadmin += 1;
1045
+ if (Q('p20manageusers').checked == true) meshadmin += 2;
1046
+ if (Q('p20managecomputers').checked == true) meshadmin += 4;
1047
+ if (Q('p20remotecontrol').checked == true) meshadmin += 8;
1048
+ if (Q('p20meshagentconsole').checked == true) meshadmin += 16;
1049
+ if (Q('p20meshserverfiles').checked == true) meshadmin += 32;
1050
+ if (Q('p20wakedevices').checked == true) meshadmin += 64;
1051
+ if (Q('p20editnotes').checked == true) meshadmin += 128;
1052
+ }
1053
+ meshserver.send({ action: 'addmeshuser', meshid: currentMesh._id, meshname: currentMesh.name, username: Q('dp20username').value , meshadmin: meshadmin});
1054
+ }
1055
+
1056
+ function p20viewuser(userid) {
1057
+ if (xxdialogMode) return;
1058
+ userid = decodeURIComponent(userid);
1059
+ var r = '', cmeshrights = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights, meshrights = currentMesh.links[userid].rights;
1060
+ if (meshrights == 0xFFFFFFFF) r = ', Full Administrator'; else {
1061
+ if ((meshrights & 1) != 0) r += ', Edit Mesh';
1062
+ if ((meshrights & 2) != 0) r += ', Manage Mesh Users';
1063
+ if ((meshrights & 4) != 0) r += ', Manage Mesh Computers';
1064
+ if ((meshrights & 8) != 0) r += ', Remote Control';
1065
+ if ((meshrights & 16) != 0) r += ', Agent Console';
1066
+ if ((meshrights & 32) != 0) r += ', Server Files';
1067
+ if ((meshrights & 64) != 0) r += ', Wake Devices';
1068
+ if ((meshrights & 128) != 0) r += ', Edit Notes';
1069
+ }
1070
+ r = r.substring(2);
1071
+ if (r == '') { r = 'No Rights'; }
1072
+ var buttons = 1, x = addHtmlValue('User', userid.split('/')[2]);
1073
+ x += addHtmlValue('Permissions', r);
1074
+ if ((('user/{{{domain}}}/' + userinfo.name.toLowerCase()) != userid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) buttons += 4;
1075
+ setDialogMode(2, "Mesh User", buttons, p20viewuserEx, x, userid);
1076
+ }
1077
+
1078
+ function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, "Confirm removal of user " + userid.split('/')[2] + "?", userid); }
1079
+ function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
1080
+ function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid}); }
1081
+
1082
//
1083
// PANELS
1084
//
@@ -852,7 +1128,7 @@
1128
if (((b & 8) || x) && f) f(x, t);
1129
}
1130
855
- function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + "px"); }
1131
+ function center() { QS('dialog').left = ((((getDocWidth() - 300) / 2)) + "px"); }
1132
function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
1133
function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
1134
function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
@@ -861,6 +1137,10 @@
1137
function validateEmail(v) { var emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; return emailReg.test(v); }
1138
function reload() { window.location.href = window.location.href; }
1139
function getNodeFromId(id) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } return null; }
1140
+ function addHtmlValue(t, v) { return '<table><td style=width:120px>' + t + '<td><b>' + v + '</b></table>'; }
1141
+ function addHtmlValue2(t, v) { return '<div><div style=display:inline-block;float:right>' + v + '</div><div style=display:inline-block>' + t + '</div></div>'; }
1142
+ function addLink(x, f) { return "<a style=cursor:pointer;color:darkblue;text-decoration:none onclick='" + f + "'>♦ " + x + "</a>"; }
1143
+ function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
1144
1145
</script>
1146
</body>
views/default.handlebars
+3
-4
@@ -1304,7 +1304,7 @@
1304
if (message.event.node.intelamt.state != null) { node.intelamt.state = message.event.node.intelamt.state; }
1305
}
1306
node.namel = node.name.toLowerCase();
1307
- if (node.host) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1307
+ if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
1308
if (message.event.node.icon) { node.icon = message.event.node.icon; }
1309
1310
onSortSelectChange(true);
@@ -4742,8 +4742,7 @@
4742
4743
function p20editmesh(focus) {
4744
if (xxdialogMode) return;
4745
- x = "Create a new mesh computer group using the options below.<br /><br />";
4746
- x += addHtmlValue('Mesh Name', '<input id=dp20meshname style=width:230px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
4745
+ var x = addHtmlValue('Mesh Name', '<input id=dp20meshname style=width:230px maxlength=32 onchange=p20editmeshValidate() onkeyup=p20editmeshValidate() />');
4746
x += addHtmlValue('Description', '<div style=width:230px;margin:0;padding:0><textarea id=dp20meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
4747
setDialogMode(2, "Edit Mesh", 3, p20editmeshEx, x);
4748
Q('dp20meshname').value = currentMesh.name;
@@ -4762,7 +4761,7 @@
4761
4762
function p20showAddMeshUserDialog() {
4763
if (xxdialogMode) return;
4765
- x = "Allow a user to manage the mesh and computers on this mesh<br /><br />";
4764
+ var x = "Allow a user to manage the mesh and computers on this mesh<br /><br />";
4765
x += addHtmlValue('User Name', '<input id=dp20username style=width:230px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />');
4766
x += '<br><div>';
4767
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Full Administrator<br>';
webserver.js
+8
-7
@@ -712,14 +712,14 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
712
// Send the master web application
713
if ((!obj.args.user) && (obj.args.nousers != true) && (nologout == false)) { logoutcontrol += ' <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>'; } // If a default user is in use or no user mode, don't display the logout button
714
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
715
- res.render(obj.path.join(__dirname, isModuleBrowser(req) ? 'views/default-mobile' : 'views/default'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, mpspass: args.mpspass, webcerthash: obj.webCertificateHashBase64, footer: (domain.footer == null) ? '' : domain.footer });
715
+ res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/default-mobile' : 'views/default'), { viewmode: viewmode, currentNode: currentNode, logoutControl: logoutcontrol, title: domain.title, title2: domain.title2, domainurl: domain.url, domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, mpspass: args.mpspass, webcerthash: obj.webCertificateHashBase64, footer: (domain.footer == null) ? '' : domain.footer });
716
} else {
717
// Send back the login application
718
var loginmode = req.session.loginmode, features = 0;
719
delete req.session.loginmode; // Clear this state, if the user hits refresh, we want to go back to the login page.
720
if ((parent.config != null) && (parent.config.settings != null) && (parent.config.settings.allowframing == true)) { features += 32; } // Allow site within iframe
721
var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
722
- res.render(obj.path.join(__dirname, isModuleBrowser(req) ? 'views/login-mobile' : 'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, footer: (domain.footer == null) ? '' : domain.footer });
722
+ res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/login-mobile' : 'views/login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: obj.parent.mailserver != null, features: features, footer: (domain.footer == null) ? '' : domain.footer });
723
}
724
}
725
@@ -738,9 +738,9 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
738
if (req.session && req.session.userid) {
739
if (req.session.domainid != domain.id) { req.session.destroy(function () { res.redirect(domain.url); }); return; } // Check is the session is for the correct domain
740
var user = obj.users[req.session.userid];
741
- res.render(obj.path.join(__dirname, isModuleBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2, logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' });
741
+ res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2, logoutControl: 'Welcome ' + user.name + '. <a href=' + domain.url + 'logout?' + Math.random() + ' style=color:white>Logout</a>' });
742
} else {
743
- res.render(obj.path.join(__dirname, isModuleBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2 });
743
+ res.render(obj.path.join(__dirname, isMobileBrowser(req) ? 'views/terms-mobile' : 'views/terms'), { title: domain.title, title2: domain.title2 });
744
}
745
}
746
@@ -1873,9 +1873,10 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
1873
1874
// Return true if a mobile browser is detected.
1875
// This code comes from "http://detectmobilebrowsers.com/" and was modified, This is free and unencumbered software released into the public domain. For more information, please refer to the http://unlicense.org/
1876
- function isModuleBrowser(req) {
1877
- var ua = req.headers['user-agent'].toLowerCase();
1878
- return (/(android|bb\d+|meego).+mobile|mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0, 4)));
1876
+ function isMobileBrowser(req) {
1877
+ //var ua = req.headers['user-agent'].toLowerCase();
1878
+ //return (/(android|bb\d+|meego).+mobile|mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0, 4)));
1879
+ return (req.headers['user-agent'].toLowerCase().indexOf('mobile') >= 0);
1880
}
1881
1882
return obj;