Refactor for #2868
Ylian Saint-Hilaire committed
Jul 7, 2021 at 19:22 UTC
591d73cf64866b4571f0892e5c1633643ea5ba3e
1 file changed
+646
-546
meshuser.js
+646
-546
@@ -911,552 +911,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
911
const cmd = cmdargs[0].toLowerCase();
912
cmdargs = parseArgs(cmdargs);
913
914
- switch (cmd) {
915
- case 'help': {
916
- var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,trafficstats,trafficdelta,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager,amtpasswords,certexpire,email';
917
- if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; }
918
- availcommands = availcommands.split(',').sort();
919
- while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); }
920
- if (f != '') { fin += f; }
921
- if (cmdargs['_'].length == 0) {
922
- r = 'Available commands: \r\n' + fin + '\r\nType help <command> for details.';
923
- } else {
924
- var cmd2 = cmdargs['_'][0].toLowerCase();
925
- switch (cmd2) {
926
- case 'info': { r = "info: Returns the most immidiatly useful information about this server, including MeshCentral and NodeJS versions. This is often information required to file a bug."; break; }
927
- case 'versions': { r = "versions: Returns all internal versions for NodeJS running this server."; break; }
928
- case 'resetserver': { r = "resetserver: Causes the server to reset, this is sometimes useful is the config.json file was changed."; break; }
929
- case 'usersessions': { r = "usersessions: Returns a list of active sessions grouped by user."; break; }
930
- case 'closeusersessions': { r = "closeusersessions: Disconnects all sessions for a specified user."; break; }
931
- case 'tasklimiter': { r = "tasklimiter: Returns the internal status of the tasklimiter. This is a system used to smooth out work done by the server. It's used by, for example, agent updates so that not all agents are updated at the same time."; break; }
932
- case 'serverupdate': { r = "serverupdate: Updates server to latest version. Optional version argument to install specific version. Example: serverupdate 0.8.49"; break; }
933
- default: { r = 'No help information about this command.'; break; }
934
- }
935
- }
936
- break;
937
- }
938
- case 'certexpire': {
939
- const now = Date.now();
940
- for (var i in parent.webCertificateExpire) {
941
- const domainName = (i == '') ? '[Default]' : i;
942
- r += domainName + ', expires in ' + Math.floor((parent.webCertificateExpire[i] - now) / 86400000) + ' day(s)\r\n';
943
- }
944
- break;
945
- }
946
- case 'webpush': {
947
- if (parent.parent.webpush == null) {
948
- r = "Web push not supported.";
949
- } else {
950
- if (cmdargs['_'].length != 1) {
951
- r = "Usage: WebPush \"Message\"";
952
- } else {
953
- const pushSubscription = { "endpoint": "https://updates.push.services.mozilla.com/wpush/v2/gAAAAABgIkO9hjXHWhMPiuk-ppNRw7r_pUZitddwCEK4ykdzeIxOIjFnYhIt_nr-qUca2mpZziwQsSEhYTUCiuYrhWnVDRweMtiUj16yJJq8V5jneaEaUYjEIe5jp3DOMNpoTm1aHgX74gCR8uTXSITcM97bNi-hRxcQ4f6Ie4WSAmoXpd89B_g", "keys": { "auth": "UB2sbLVK7ALnSHw5P1dahg", "p256dh": "BIoRbcNSxBuTjN39CCCUCHo1f4NxBJ1YDdu_k4MbPW_q3NK1_RufnydUzLPDp8ibBVItSI72-s48QJvOjQ_S8Ok" } }
954
- parent.parent.webpush.sendNotification(pushSubscription, cmdargs['_'][0]).then(
955
- function (value) { try { ws.send(JSON.stringify({ action: 'OK', value: r, tag: command.tag })); } catch (ex) { } },
956
- function (error) { try { ws.send(JSON.stringify({ action: 'Error', value: r, tag: command.tag })); } catch (ex) { } }
957
- );
958
- }
959
- }
960
- break;
961
- }
962
- case 'amtmanager': {
963
- if (parent.parent.amtManager == null) { r = 'Intel AMT Manager not active.'; } else { r = parent.parent.amtManager.getStatusString(); }
964
- break;
965
- }
966
- case 'certhashes': {
967
- r += 'AgentCertHash: ' + parent.agentCertificateHashHex;
968
- for (var i in parent.webCertificateHashs) { r += '\r\nwebCertificateHash (' + i + '): ' + common.rstr2hex(parent.webCertificateHashs[i]); }
969
- for (var i in parent.webCertificateFullHashs) { r += '\r\nwebCertificateFullHash (' + i + '): ' + common.rstr2hex(parent.webCertificateFullHashs[i]); }
970
- r += '\r\ndefaultWebCertificateHash: ' + common.rstr2hex(parent.defaultWebCertificateHash);
971
- r += '\r\ndefaultWebCertificateFullHash: ' + common.rstr2hex(parent.defaultWebCertificateFullHash);
972
- break;
973
- }
974
- case 'amtacm': {
975
- if ((domain.amtacmactivation == null) || (domain.amtacmactivation.acmmatch == null) || (domain.amtacmactivation.acmmatch.length == 0)) {
976
- r = 'No Intel AMT activation certificates.';
977
- } else {
978
- if (domain.amtacmactivation.log != null) { r += '--- Activation Log ---\r\nFile : ' + domain.amtacmactivation.log + '\r\n'; }
979
- for (var i in domain.amtacmactivation.acmmatch) {
980
- var acmcert = domain.amtacmactivation.acmmatch[i];
981
- r += '--- Activation Certificate ' + (parseInt(i) + 1) + ' ---\r\nName : ' + acmcert.cn + '\r\nSHA1 : ' + acmcert.sha1 + '\r\nSHA256: ' + acmcert.sha256 + '\r\n';
982
- }
983
- }
984
- break;
985
- }
986
- case 'heapdump': {
987
- // Heapdump support, see example at:
988
- // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/
989
- if (parent.parent.config.settings.heapdump === true) {
990
- var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`);
991
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { }
992
- require('heapdump').writeSnapshot(dumpFileName, (err, filename) => {
993
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { }
994
- });
995
- } else {
996
- r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json.";
997
- }
998
- break;
999
- }
1000
- case 'sms': {
1001
- if (parent.parent.smsserver == null) {
1002
- r = "No SMS gateway in use.";
1003
- } else {
1004
- if (cmdargs['_'].length != 2) {
1005
- r = "Usage: SMS \"PhoneNumber\" \"Message\".";
1006
- } else {
1007
- parent.parent.smsserver.sendSMS(cmdargs['_'][0], cmdargs['_'][1], function (status, msg) {
1008
- if (typeof msg == 'string') {
1009
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? ('Success: ' + msg) : ('Failed: ' + msg), tag: command.tag })); } catch (ex) { }
1010
- } else {
1011
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? 'Success' : 'Failed', tag: command.tag })); } catch (ex) { }
1012
- }
1013
- });
1014
- }
1015
- }
1016
- break;
1017
- }
1018
- case 'email': {
1019
- if (domain.mailserver == null) {
1020
- r = "No email service enabled.";
1021
- } else {
1022
- if (cmdargs['_'].length != 3) {
1023
- r = "Usage: email \"user@sample.com\" \"Subject\" \"Message\".";
1024
- } else {
1025
- domain.mailserver.sendMail(cmdargs['_'][0], cmdargs['_'][1], cmdargs['_'][2]);
1026
- r = "Done.";
1027
- }
1028
- }
1029
- break;
1030
- }
1031
- case 'le': {
1032
- if (parent.parent.letsencrypt == null) {
1033
- r = "Let's Encrypt not in use.";
1034
- } else {
1035
- r = JSON.stringify(parent.parent.letsencrypt.getStats(), null, 4);
1036
- }
1037
- break;
1038
- }
1039
- case 'lecheck': {
1040
- if (parent.parent.letsencrypt == null) {
1041
- r = "Let's Encrypt not in use.";
1042
- } else {
1043
- r = ["CertOK", "Request:NoCert", "Request:Expire", "Request:MissingNames"][parent.parent.letsencrypt.checkRenewCertificate()];
1044
- }
1045
- break;
1046
- }
1047
- case 'leevents': {
1048
- if (parent.parent.letsencrypt == null) {
1049
- r = "Let's Encrypt not in use.";
1050
- } else {
1051
- r = parent.parent.letsencrypt.events.join('\r\n');
1052
- }
1053
- break;
1054
- }
1055
- case 'badlogins': {
1056
- if (parent.parent.config.settings.maxinvalidlogin == false) {
1057
- r = 'Bad login filter is disabled.';
1058
- } else {
1059
- if (cmdargs['_'] == 'reset') {
1060
- // Reset bad login table
1061
- parent.badLoginTable = {};
1062
- parent.badLoginTableLastClean = 0;
1063
- r = 'Done.'
1064
- } else if (cmdargs['_'] == '') {
1065
- // Show current bad login table
1066
- if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') {
1067
- r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n";
1068
- } else {
1069
- r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n";
1070
- }
1071
- var badLoginCount = 0;
1072
- parent.cleanBadLoginTable();
1073
- for (var i in parent.badLoginTable) {
1074
- badLoginCount++;
1075
- if (typeof parent.badLoginTable[i] == 'number') {
1076
- r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n";
1077
- } else {
1078
- if (parent.badLoginTable[i].length > 1) {
1079
- r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n");
1080
- } else {
1081
- r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n");
1082
- }
1083
- }
1084
- }
1085
- if (badLoginCount == 0) { r += 'No bad logins.'; }
1086
- } else {
1087
- r = 'Usage: badlogin [reset]';
1088
- }
1089
- }
1090
- break;
1091
- }
1092
- case 'dispatchtable': {
1093
- r = '';
1094
- for (var i in parent.parent.eventsDispatch) { r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n'); }
1095
- break;
1096
- }
1097
- case 'dupagents': {
1098
- for (var i in parent.duplicateAgentsLog) { r += JSON.stringify(parent.duplicateAgentsLog[i]) + '\r\n'; }
1099
- if (r == '') { r = 'No duplicate agents in log.'; }
1100
- break;
1101
- }
1102
- case 'agentstats': {
1103
- var stats = parent.getAgentStats();
1104
- for (var i in stats) {
1105
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1106
- }
1107
- break;
1108
- }
1109
- case 'agentissues': {
1110
- var stats = parent.getAgentIssues();
1111
- if (stats.length == 0) {
1112
- r = "No agent issues.";
1113
- } else {
1114
- for (var i in stats) { r += stats[i].join(', ') + '\r\n'; }
1115
- }
1116
- break;
1117
- }
1118
- case 'webstats': {
1119
- var stats = parent.getStats();
1120
- for (var i in stats) {
1121
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1122
- }
1123
- break;
1124
- }
1125
- case 'trafficstats': {
1126
- var stats = parent.getTrafficStats();
1127
- for (var i in stats) {
1128
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1129
- }
1130
- break;
1131
- }
1132
- case 'trafficdelta': {
1133
- const stats = parent.getTrafficDelta(obj.trafficStats);
1134
- obj.trafficStats = stats.current;
1135
- for (var i in stats.delta) {
1136
- if (typeof stats.delta[i] == 'object') { r += (i + ': ' + JSON.stringify(stats.delta[i]) + '\r\n'); } else { r += (i + ': ' + stats.delta[i] + '\r\n'); }
1137
- }
1138
- break;
1139
- }
1140
- case 'watchdog': {
1141
- if (parent.parent.watchdog == null) {
1142
- r = 'Server watchdog not active.';
1143
- } else {
1144
- r = 'Server watchdog active.\r\n';
1145
- if (parent.parent.watchdogmaxtime != null) { r += 'Largest timeout was ' + parent.parent.watchdogmax + 'ms on ' + parent.parent.watchdogmaxtime + '\r\n'; }
1146
- for (var i in parent.parent.watchdogtable) { r += parent.parent.watchdogtable[i] + '\r\n'; }
1147
- }
1148
- break;
1149
- }
1150
- case 'acceleratorsstats': {
1151
- var stats = parent.parent.certificateOperations.getAcceleratorStats();
1152
- for (var i in stats) {
1153
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1154
- }
1155
- break;
1156
- }
1157
- case 'mpsstats': {
1158
- if (parent.parent.mpsserver == null) {
1159
- r = 'MPS not enabled.';
1160
- } else {
1161
- var stats = parent.parent.mpsserver.getStats();
1162
- for (var i in stats) {
1163
- if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
1164
- }
1165
- }
1166
- break;
1167
- }
1168
- case 'mps': { // List all MPS connections and types.
1169
- if (parent.parent.mpsserver == null) {
1170
- r = 'MPS not enabled.';
1171
- } else {
1172
- const connectionTypes = ['CIRA', 'Relay', 'LMS'];
1173
- for (var nodeid in parent.parent.mpsserver.ciraConnections) {
1174
- r += nodeid;
1175
- var connections = parent.parent.mpsserver.ciraConnections[nodeid];
1176
- for (var i in connections) { r += ', ' + connectionTypes[connections[i].tag.connType]; }
1177
- r += '\r\n';
1178
- }
1179
- if (r == '') { r = 'MPS has not connections.'; }
1180
- }
1181
- break;
1182
- }
1183
- case 'dbstats': {
1184
- parent.parent.db.getStats(function (stats) {
1185
- var r2 = '';
1186
- for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); }
1187
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
1188
- });
1189
- break;
1190
- }
1191
- case 'dbcounters': {
1192
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: JSON.stringify(parent.parent.db.dbCounters, null, 2), tag: command.tag })); } catch (ex) { }
1193
- break;
1194
- }
1195
- case 'serverupdate': {
1196
- r = 'Performing server update...';
1197
- var version = null;
1198
-
1199
- if (cmdargs['_'].length > 0) {
1200
- version = cmdargs['_'][0];
1201
-
1202
- // This call is SLOW. We only want to validate version if we have to
1203
- if (version != 'stable' && version != 'latest') {
1204
- parent.parent.getServerVersions((data) => {
1205
- var versions = JSON.parse(data);
1206
-
1207
- if (versions.includes(version)) {
1208
- if (parent.parent.performServerUpdate(version) == false) {
1209
- try {
1210
- ws.send(JSON.stringify({ action: 'serverconsole',
1211
- value: 'Server self-update not possible.'}));
1212
- } catch (ex) { }
1213
- }
1214
- } else {
1215
- try {
1216
- ws.send(JSON.stringify({ action: 'serverconsole',
1217
- value: 'Invalid version. Aborting update'}));
1218
- } catch (ex) { }
1219
- }
1220
- });
1221
- } else {
1222
- if (parent.parent.performServerUpdate(version) == false) {
1223
- r = 'Server self-update not possible.';
1224
- }
1225
- }
1226
- } else {
1227
- if (parent.parent.performServerUpdate(version) == false) {
1228
- r = 'Server self-update not possible.';
1229
- }
1230
- }
1231
-
1232
- break;
1233
- }
1234
- case 'print': {
1235
- console.log(cmdargs['_'][0]);
1236
- break;
1237
- }
1238
- case 'amtpasswords': {
1239
- if (parent.parent.amtPasswords == null) {
1240
- r = "No Intel AMT password table."
1241
- } else {
1242
- for (var i in parent.parent.amtPasswords) { r += (i + ' - ' + parent.parent.amtPasswords[i].join(', ') + '\r\n'); }
1243
- }
1244
- break;
1245
- }
1246
- case 'updatecheck': {
1247
- parent.parent.getServerTags(function (tags, error) {
1248
- var r2 = '';
1249
- if (error != null) { r2 += 'Exception: ' + error + '\r\n'; }
1250
- else { for (var i in tags) { r2 += i + ': ' + tags[i] + '\r\n'; } }
1251
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
1252
- });
1253
- r = "Checking server update...";
1254
- break;
1255
- }
1256
- case 'maintenance': {
1257
- var arg = null, changed = false;
1258
- if ((cmdargs['_'] != null) && (cmdargs['_'][0] != null)) { arg = cmdargs['_'][0].toLowerCase(); }
1259
- if (arg == 'enabled') { parent.parent.config.settings.maintenancemode = 1; changed = true; }
1260
- else if (arg == 'disabled') { delete parent.parent.config.settings.maintenancemode; changed = true; }
1261
- r = 'Maintenance mode: ' + ((parent.parent.config.settings.maintenancemode == null) ? 'Disabled' : 'Enabled');
1262
- if (changed == false) { r += '\r\nTo change type: maintenance [enabled|disabled]'; }
1263
- break;
1264
- }
1265
- case 'info': {
1266
- var info = process.memoryUsage();
1267
- info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType];
1268
- try { if (parent.parent.multiServer != null) { info.serverId = parent.parent.multiServer.serverid; } } catch (ex) { }
1269
- if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; }
1270
- if (parent.parent.pluginHandler != null) { info.plugins = []; for (var i in parent.parent.pluginHandler.plugins) { info.plugins.push(i); } }
1271
- try { info.nodeVersion = process.version; } catch (ex) { }
1272
- try { info.meshVersion = parent.parent.currentVer; } catch (ex) { }
1273
- try { info.platform = process.platform; } catch (ex) { }
1274
- try { info.arch = process.arch; } catch (ex) { }
1275
- try { info.pid = process.pid; } catch (ex) { }
1276
- try { info.uptime = process.uptime(); } catch (ex) { }
1277
- try { info.cpuUsage = process.cpuUsage(); } catch (ex) { }
1278
- try { info.warnings = parent.parent.getServerWarnings(); } catch (ex) { }
1279
- try { info.database = ["Unknown", "NeDB", "MongoJS", "MongoDB", "MariaDB", "MySQL"][parent.parent.db.databaseType]; } catch (ex) { }
1280
- try { info.productionMode = ((process.env.NODE_ENV != null) && (process.env.NODE_ENV == 'production')); } catch (ex) { }
1281
- try { info.allDevGroupManagers = parent.parent.config.settings.managealldevicegroups; } catch (ex) { }
1282
- r = JSON.stringify(info, null, 4);
1283
- break;
1284
- }
1285
- case 'nodeconfig': {
1286
- r = JSON.stringify(process.config, null, 4);
1287
- break;
1288
- }
1289
- case 'versions': {
1290
- r = JSON.stringify(process.versions, null, 4);
1291
- break;
1292
- }
1293
- case 'args': {
1294
- r = cmd + ': ' + JSON.stringify(cmdargs);
1295
- break;
1296
- }
1297
- case 'usersessions': {
1298
- var userSessionCount = 0;
1299
- var filter = null;
1300
- var arg = cmdargs['_'][0];
1301
- if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
1302
- for (var i in parent.wssessions) {
1303
- if ((filter == null) || (filter == i)) {
1304
- userSessionCount++;
1305
- r += (i + ', ' + parent.wssessions[i].length + ' session' + ((parent.wssessions[i].length > 1) ? 's' : '') + '.\r\n');
1306
- for (var j in parent.wssessions[i]) {
1307
- r += ' ' + parent.wssessions[i][j].clientIp + ' --> ' + parent.wssessions[i][j].sessionId + '\r\n';
1308
- }
1309
- }
1310
- }
1311
- if (userSessionCount == 0) { r = 'None.'; }
1312
- break;
1313
- }
1314
- case 'closeusersessions': {
1315
- var userSessionCount = 0;
1316
- var filter = null;
1317
- var arg = cmdargs['_'][0];
1318
- if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
1319
- if (filter == null) {
1320
- r += "Usage: closeusersessions <username>";
1321
- } else {
1322
- r += "Closing user sessions for: " + filter + '\r\n';
1323
- for (var i in parent.wssessions) {
1324
- if (filter == i) {
1325
- userSessionCount++;
1326
- for (var j in parent.wssessions[i]) {
1327
- parent.wssessions[i][j].send(JSON.stringify({ action: 'stopped', msg: "Administrator forced disconnection" }));
1328
- parent.wssessions[i][j].close();
1329
- }
1330
- }
1331
- }
1332
- if (userSessionCount < 2) { r += 'Disconnected ' + userSessionCount + ' session.'; } else { r += 'Disconnected ' + userSessionCount + ' sessions.'; };
1333
- }
1334
- break;
1335
- }
1336
- case 'resetserver': {
1337
- console.log("Server restart...");
1338
- process.exit(0);
1339
- break;
1340
- }
1341
- case 'tasklimiter': {
1342
- if (parent.parent.taskLimiter != null) {
1343
- //var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null };
1344
- const tl = parent.parent.taskLimiter;
1345
- r += 'MaxTasks: ' + tl.maxTasks + ', NextTaskId: ' + tl.nextTaskId + '\r\n';
1346
- r += 'MaxTaskTime: ' + (tl.maxTaskTime / 1000) + ' seconds, Timer: ' + (tl.timer != null) + '\r\n';
1347
- var c = [];
1348
- for (var i in tl.current) { c.push(i); }
1349
- r += 'Current (' + tl.currentCount + '): [' + c.join(', ') + ']\r\n';
1350
- r += 'Pending (High/Med/Low): ' + tl.pending[0].length + ', ' + tl.pending[1].length + ', ' + tl.pending[2].length + '\r\n';
1351
- }
1352
- break;
1353
- }
1354
- case 'setmaxtasks': {
1355
- if ((cmdargs["_"].length != 1) || (parseInt(cmdargs["_"][0]) < 1) || (parseInt(cmdargs["_"][0]) > 1000)) {
1356
- r = 'Usage: setmaxtasks [1 to 1000]';
1357
- } else {
1358
- parent.parent.taskLimiter.maxTasks = parseInt(cmdargs["_"][0]);
1359
- r = 'MaxTasks set to ' + parent.parent.taskLimiter.maxTasks + '.';
1360
- }
1361
- break;
1362
- }
1363
- case 'cores': {
1364
- if (parent.parent.defaultMeshCores != null) { for (var i in parent.parent.defaultMeshCores) { r += i + ': ' + parent.parent.defaultMeshCores[i].length + ' bytes\r\n'; } }
1365
- break;
1366
- }
1367
- case 'showpaths': {
1368
- r = 'Parent: ' + parent.parent.parentpath + '\r\n';
1369
- r += 'Data: ' + parent.parent.datapath + '\r\n';
1370
- r += 'Files: ' + parent.parent.filespath + '\r\n';
1371
- r += 'Backup: ' + parent.parent.backuppath + '\r\n';
1372
- r += 'Record: ' + parent.parent.recordpath + '\r\n';
1373
- r += 'WebPublic: ' + parent.parent.webPublicPath + '\r\n';
1374
- r += 'WebViews: ' + parent.parent.webViewsPath + '\r\n';
1375
- if (parent.parent.webViewsOverridePath) { r += 'XWebPublic: ' + parent.parent.webViewsOverridePath + '\r\n'; }
1376
- if (parent.parent.webViewsOverridePath) { r += 'XWebViews: ' + parent.parent.webPublicOverridePath + '\r\n'; }
1377
- break;
1378
- }
1379
- case 'migrationagents': {
1380
- if (parent.parent.swarmserver == null) {
1381
- r = 'Swarm server not running.';
1382
- } else {
1383
- for (var i in parent.parent.swarmserver.migrationAgents) {
1384
- var arch = parent.parent.swarmserver.migrationAgents[i];
1385
- for (var j in arch) { var agent = arch[j]; r += 'Arch ' + agent.arch + ', Ver ' + agent.ver + ', Size ' + ((agent.binary == null) ? 0 : agent.binary.length) + '<br />'; }
1386
- }
1387
- }
1388
- break;
1389
- }
1390
- case 'swarmstats': {
1391
- if (parent.parent.swarmserver == null) {
1392
- r = 'Swarm server not running.';
1393
- } else {
1394
- for (var i in parent.parent.swarmserver.stats) {
1395
- if (typeof parent.parent.swarmserver.stats[i] == 'object') {
1396
- r += i + ': ' + JSON.stringify(parent.parent.swarmserver.stats[i]) + '\r\n';
1397
- } else {
1398
- r += i + ': ' + parent.parent.swarmserver.stats[i] + '\r\n';
1399
- }
1400
- }
1401
- }
1402
- break;
1403
- }
1404
- case 'heapdump': {
1405
- var heapdump = null;
1406
- try { heapdump = require('heapdump'); } catch (ex) { }
1407
- if (heapdump == null) {
1408
- r = 'Heapdump module not installed, run "npm install heapdump".';
1409
- } else {
1410
- heapdump.writeSnapshot(function (err, filename) {
1411
- if (err != null) {
1412
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Unable to write heapdump: ' + err })); } catch (ex) { }
1413
- } else {
1414
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Wrote heapdump at ' + filename })); } catch (ex) { }
1415
- }
1416
- });
1417
- }
1418
- break;
1419
- }
1420
- case 'relays': {
1421
- for (var i in parent.wsrelays) {
1422
- r += 'id: ' + i + ', ' + ((parent.wsrelays[i].state == 2) ? 'connected' : 'pending');
1423
- if (parent.wsrelays[i].peer1 != null) {
1424
- r += ', ' + cleanRemoteAddr(parent.wsrelays[i].peer1.req.clientIp);
1425
- if (parent.wsrelays[i].peer1.user) { r += ' (User:' + parent.wsrelays[i].peer1.user.name + ')' }
1426
- }
1427
- if (parent.wsrelays[i].peer2 != null) {
1428
- r += ' to ' + cleanRemoteAddr(parent.wsrelays[i].peer2.req.clientIp);
1429
- if (parent.wsrelays[i].peer2.user) { r += ' (User:' + parent.wsrelays[i].peer2.user.name + ')' }
1430
- }
1431
- r += '\r\n';
1432
- }
1433
- if (r == '') { r = 'No relays.'; }
1434
- break;
1435
- }
1436
- case 'autobackup': {
1437
- var backupResult = parent.db.performBackup(function (msg) {
1438
- try { ws.send(JSON.stringify({ action: 'serverconsole', value: msg, tag: command.tag })); } catch (ex) { }
1439
- });
1440
- if (backupResult == 0) { r = 'Starting auto-backup...'; } else { r = 'Backup alreay in progress.'; }
1441
- break;
1442
- }
1443
- case 'backupconfig': {
1444
- r = parent.db.getBackupConfig();
1445
- break;
1446
- }
1447
- case 'firebase': {
1448
- if (parent.parent.firebase == null) {
1449
- r = "Firebase push messaging not supported";
1450
- } else {
1451
- r = JSON.stringify(parent.parent.firebase.stats, null, 2);
1452
- }
1453
- break;
1454
- }
1455
- default: { // This is an unknown command, return an error message
1456
- r = 'Unknown command \"' + cmd + '\", type \"help\" for list of available commands.';
1457
- break;
1458
- }
1459
- }
914
+ var cmdData = serverUserCommand[cmd];
915
+ if (cmdData != null) { r = cmdData[0](cmdargs); } else { r = 'Unknown command \"' + cmd + '\", type \"help\" for list of available commands.'; }
916
917
if (r != '') { try { ws.send(JSON.stringify({ action: 'serverconsole', value: r, tag: command.tag })); } catch (ex) { } }
918
break;
@@ -6078,6 +5534,650 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5534
}
5535
}
5536
5537
+ const serverUserCommand = {
5538
+ 'acceleratorsstats': [serverUserCommandAcceleratorsStats, "Show data on work being offloaded to other CPU's"],
5539
+ 'agentissues': [serverUserCommandAgentIssues, ""],
5540
+ 'agentstats': [serverUserCommandAgentStats, ""],
5541
+ 'amtacm': [serverUserCommandAmtAcm, ""],
5542
+ 'amtmanager': [serverUserCommandAmtManager, ""],
5543
+ 'amtpasswords': [serverUserCommandAmtPasswords, ""],
5544
+ 'args': [serverUserCommandArgs, ""],
5545
+ 'autobackup': [serverUserCommandAutoBackup, ""],
5546
+ 'backupconfig': [serverUserCommandBackupConfig, ""],
5547
+ 'badlogins': [serverUserCommandBadLogins, ""],
5548
+ 'certexpire': [serverUserCommandCertExpire, ""],
5549
+ 'certhashes': [serverUserCommandCertHashes, ""],
5550
+ 'closeusersessions': [serverUserCommandCloseUserSessions, "Disconnects all sessions for a specified user."],
5551
+ 'cores': [serverUserCommandCores, ""],
5552
+ 'dbcounters': [serverUserCommandDbCounters, ""],
5553
+ 'dbstats': [serverUserCommandDbStats, ""],
5554
+ 'dispatchtable': [serverUserCommandDispatchTable, ""],
5555
+ 'dupagents': [serverUserCommandDupAgents, ""],
5556
+ 'email': [serverUserCommandEmail, ""],
5557
+ 'firebase': [serverUserCommandFirebase, ""],
5558
+ 'heapdump': [serverUserCommandHeapDump, ""],
5559
+ 'heapdump2': [serverUserCommandHeapDump2, ""],
5560
+ 'help': [serverUserCommandHelp, ""],
5561
+ 'info': [serverUserCommandInfo, "Returns the most immidiatly useful information about this server, including MeshCentral and NodeJS versions. This is often information required to file a bug."],
5562
+ 'le': [serverUserCommandLe, ""],
5563
+ 'lecheck': [serverUserCommandLeCheck, ""],
5564
+ 'leevents': [serverUserCommandLeEvents, ""],
5565
+ 'maintenance': [serverUserCommandMaintenance, ""],
5566
+ 'migrationagents': [serverUserCommandMigrationAgents, ""],
5567
+ 'mps': [serverUserCommandMps, ""],
5568
+ 'mpsstats': [serverUserCommandMpsStats, ""],
5569
+ 'nodeconfig': [serverUserCommandNodeConfig, ""],
5570
+ 'print': [serverUserCommandPrint, ""],
5571
+ 'relays': [serverUserCommandRelays, ""],
5572
+ 'resetserver': [serverUserCommandResetServer, "Causes the server to reset, this is sometimes useful is the config.json file was changed."],
5573
+ 'serverupdate': [serverUserCommandServerUpdate, "Updates server to latest version. Optional version argument to install specific version. Example: serverupdate 0.8.49"],
5574
+ 'setmaxtasks': [serverUserCommandSetMaxTasks, ""],
5575
+ 'showpaths': [serverUserCommandShowPaths, ""],
5576
+ 'sms': [serverUserCommandSMS, ""],
5577
+ 'swarmstats': [serverUserCommandSwarmStats, ""],
5578
+ 'tasklimiter': [serverUserCommandTaslkLimiter, "Returns the internal status of the tasklimiter. This is a system used to smooth out work done by the server. It's used by, for example, agent updates so that not all agents are updated at the same time."],
5579
+ 'trafficdelta': [serverUserCommandTrafficDelta, ""],
5580
+ 'trafficstats': [serverUserCommandTrafficStats, ""],
5581
+ 'updatecheck': [serverUserCommandUpdateCheck, ""],
5582
+ 'usersessions': [serverUserCommandUserSessions, "Returns a list of active sessions grouped by user."],
5583
+ 'versions': [serverUserCommandVersions, "Returns all internal versions for NodeJS running this server."],
5584
+ 'watchdog': [serverUserCommandWatchdog, ""],
5585
+ 'webpush': [serverUserCommandWebPush, ""],
5586
+ 'webstats': [serverUserCommandWebStats, ""]
5587
+ }
5588
+
5589
+ function serverUserCommandHelp(cmdargs) {
5590
+ var r, fin = '', f = '', availcommands = [];
5591
+ for (var i in serverUserCommand) { availcommands.push(i); }
5592
+ availcommands = availcommands.sort();
5593
+ while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); }
5594
+ if (f != '') { fin += f; }
5595
+ if (cmdargs['_'].length == 0) {
5596
+ r = 'Available commands: \r\n' + fin + '\r\nType help <command> for details.';
5597
+ } else {
5598
+ var cmd2 = cmdargs['_'][0].toLowerCase();
5599
+ var cmddata = serverUserCommand[cmd2];
5600
+ if (cmddata) { if (cmddata[1] == '') { r = "No help available for this command."; } else { r = cmddata[1]; } } else { r = "This command does not exist."; }
5601
+ }
5602
+ return r;
5603
+ }
5604
+
5605
+ function serverUserCommandCertExpire(cmdargs) {
5606
+ var r = '';
5607
+ const now = Date.now();
5608
+ for (var i in parent.webCertificateExpire) {
5609
+ const domainName = (i == '') ? '[Default]' : i;
5610
+ r += domainName + ', expires in ' + Math.floor((parent.webCertificateExpire[i] - now) / 86400000) + ' day(s)\r\n';
5611
+ }
5612
+ return r;
5613
+ }
5614
+
5615
+ function serverUserCommandWebPush(cmdargs) {
5616
+ if (parent.parent.webpush == null) {
5617
+ r = "Web push not supported.";
5618
+ } else {
5619
+ if (cmdargs['_'].length != 1) {
5620
+ r = "Usage: WebPush \"Message\"";
5621
+ } else {
5622
+ const pushSubscription = { "endpoint": "https://updates.push.services.mozilla.com/wpush/v2/gAAAAABgIkO9hjXHWhMPiuk-ppNRw7r_pUZitddwCEK4ykdzeIxOIjFnYhIt_nr-qUca2mpZziwQsSEhYTUCiuYrhWnVDRweMtiUj16yJJq8V5jneaEaUYjEIe5jp3DOMNpoTm1aHgX74gCR8uTXSITcM97bNi-hRxcQ4f6Ie4WSAmoXpd89B_g", "keys": { "auth": "UB2sbLVK7ALnSHw5P1dahg", "p256dh": "BIoRbcNSxBuTjN39CCCUCHo1f4NxBJ1YDdu_k4MbPW_q3NK1_RufnydUzLPDp8ibBVItSI72-s48QJvOjQ_S8Ok" } }
5623
+ parent.parent.webpush.sendNotification(pushSubscription, cmdargs['_'][0]).then(
5624
+ function (value) { try { ws.send(JSON.stringify({ action: 'OK', value: r, tag: command.tag })); } catch (ex) { } },
5625
+ function (error) { try { ws.send(JSON.stringify({ action: 'Error', value: r, tag: command.tag })); } catch (ex) { } }
5626
+ );
5627
+ }
5628
+ }
5629
+ return r;
5630
+ }
5631
+
5632
+ function serverUserCommandAmtManager(cmdargs) {
5633
+ if (parent.parent.amtManager == null) { return 'Intel AMT Manager not active.'; }
5634
+ return parent.parent.amtManager.getStatusString();
5635
+ }
5636
+
5637
+ function serverUserCommandCertHashes(cmdargs) {
5638
+ var r = 'AgentCertHash: ' + parent.agentCertificateHashHex;
5639
+ for (var i in parent.webCertificateHashs) { r += '\r\nwebCertificateHash (' + i + '): ' + common.rstr2hex(parent.webCertificateHashs[i]); }
5640
+ for (var i in parent.webCertificateFullHashs) { r += '\r\nwebCertificateFullHash (' + i + '): ' + common.rstr2hex(parent.webCertificateFullHashs[i]); }
5641
+ r += '\r\ndefaultWebCertificateHash: ' + common.rstr2hex(parent.defaultWebCertificateHash);
5642
+ r += '\r\ndefaultWebCertificateFullHash: ' + common.rstr2hex(parent.defaultWebCertificateFullHash);
5643
+ return r;
5644
+ }
5645
+
5646
+ function serverUserCommandAmtAcm(cmdargs) {
5647
+ var r = '';
5648
+ if ((domain.amtacmactivation == null) || (domain.amtacmactivation.acmmatch == null) || (domain.amtacmactivation.acmmatch.length == 0)) {
5649
+ r = 'No Intel AMT activation certificates.';
5650
+ } else {
5651
+ if (domain.amtacmactivation.log != null) { r += '--- Activation Log ---\r\nFile : ' + domain.amtacmactivation.log + '\r\n'; }
5652
+ for (var i in domain.amtacmactivation.acmmatch) {
5653
+ var acmcert = domain.amtacmactivation.acmmatch[i];
5654
+ r += '--- Activation Certificate ' + (parseInt(i) + 1) + ' ---\r\nName : ' + acmcert.cn + '\r\nSHA1 : ' + acmcert.sha1 + '\r\nSHA256: ' + acmcert.sha256 + '\r\n';
5655
+ }
5656
+ }
5657
+ return r;
5658
+ }
5659
+
5660
+ function serverUserCommandHeapDump(cmdargs) {
5661
+ var r = '';
5662
+ // Heapdump support, see example at:
5663
+ // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/
5664
+ if (parent.parent.config.settings.heapdump === true) {
5665
+ var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`);
5666
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { }
5667
+ require('heapdump').writeSnapshot(dumpFileName, (err, filename) => {
5668
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { }
5669
+ });
5670
+ } else {
5671
+ r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json.";
5672
+ }
5673
+ return r;
5674
+ }
5675
+
5676
+ function serverUserCommandHeapDump2(cmdargs) {
5677
+ var r = '';
5678
+ var heapdump = null;
5679
+ try { heapdump = require('heapdump'); } catch (ex) { }
5680
+ if (heapdump == null) {
5681
+ r = 'Heapdump module not installed, run "npm install heapdump".';
5682
+ } else {
5683
+ heapdump.writeSnapshot(function (err, filename) {
5684
+ if (err != null) {
5685
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Unable to write heapdump: ' + err })); } catch (ex) { }
5686
+ } else {
5687
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: 'Wrote heapdump at ' + filename })); } catch (ex) { }
5688
+ }
5689
+ });
5690
+ }
5691
+ break;
5692
+ }
5693
+
5694
+ function serverUserCommandSMS(cmdargs) {
5695
+ var r = '';
5696
+ if (parent.parent.smsserver == null) {
5697
+ r = "No SMS gateway in use.";
5698
+ } else {
5699
+ if (cmdargs['_'].length != 2) {
5700
+ r = "Usage: SMS \"PhoneNumber\" \"Message\".";
5701
+ } else {
5702
+ parent.parent.smsserver.sendSMS(cmdargs['_'][0], cmdargs['_'][1], function (status, msg) {
5703
+ if (typeof msg == 'string') {
5704
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? ('Success: ' + msg) : ('Failed: ' + msg), tag: command.tag })); } catch (ex) { }
5705
+ } else {
5706
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: status ? 'Success' : 'Failed', tag: command.tag })); } catch (ex) { }
5707
+ }
5708
+ });
5709
+ }
5710
+ }
5711
+ return r;
5712
+ }
5713
+
5714
+ function serverUserCommandEmail(cmdargs) {
5715
+ var r = '';
5716
+ if (domain.mailserver == null) {
5717
+ r = "No email service enabled.";
5718
+ } else {
5719
+ if (cmdargs['_'].length != 3) {
5720
+ r = "Usage: email \"user@sample.com\" \"Subject\" \"Message\".";
5721
+ } else {
5722
+ domain.mailserver.sendMail(cmdargs['_'][0], cmdargs['_'][1], cmdargs['_'][2]);
5723
+ r = "Done.";
5724
+ }
5725
+ }
5726
+ return r;
5727
+ }
5728
+
5729
+ function serverUserCommandLe(cmdargs) {
5730
+ if (parent.parent.letsencrypt == null) { return "Let's Encrypt not in use."; }
5731
+ return JSON.stringify(parent.parent.letsencrypt.getStats(), null, 4);
5732
+ }
5733
+
5734
+ function serverUserCommandLeCheck(cmdargs) {
5735
+ if (parent.parent.letsencrypt == null) { return "Let's Encrypt not in use."; }
5736
+ return ["CertOK", "Request:NoCert", "Request:Expire", "Request:MissingNames"][parent.parent.letsencrypt.checkRenewCertificate()];
5737
+ }
5738
+
5739
+ function serverUserCommandLeEvents(cmdargs) {
5740
+ if (parent.parent.letsencrypt == null) { return "Let's Encrypt not in use."; }
5741
+ return parent.parent.letsencrypt.events.join('\r\n');
5742
+ }
5743
+
5744
+ function serverUserCommandBadLogins(cmdargs) {
5745
+ var r = '';
5746
+ if (parent.parent.config.settings.maxinvalidlogin == false) {
5747
+ r = 'Bad login filter is disabled.';
5748
+ } else {
5749
+ if (cmdargs['_'] == 'reset') {
5750
+ // Reset bad login table
5751
+ parent.badLoginTable = {};
5752
+ parent.badLoginTableLastClean = 0;
5753
+ r = 'Done.'
5754
+ } else if (cmdargs['_'] == '') {
5755
+ // Show current bad login table
5756
+ if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') {
5757
+ r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n";
5758
+ } else {
5759
+ r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n";
5760
+ }
5761
+ var badLoginCount = 0;
5762
+ parent.cleanBadLoginTable();
5763
+ for (var i in parent.badLoginTable) {
5764
+ badLoginCount++;
5765
+ if (typeof parent.badLoginTable[i] == 'number') {
5766
+ r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n";
5767
+ } else {
5768
+ if (parent.badLoginTable[i].length > 1) {
5769
+ r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n");
5770
+ } else {
5771
+ r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n");
5772
+ }
5773
+ }
5774
+ }
5775
+ if (badLoginCount == 0) { r += 'No bad logins.'; }
5776
+ } else {
5777
+ r = 'Usage: badlogin [reset]';
5778
+ }
5779
+ }
5780
+ return r;
5781
+ }
5782
+
5783
+ function serverUserCommandDispatchTable(cmdargs) {
5784
+ var r = '';
5785
+ for (var i in parent.parent.eventsDispatch) { r += (i + ', ' + parent.parent.eventsDispatch[i].length + '\r\n'); }
5786
+ return r;
5787
+ }
5788
+
5789
+ function serverUserCommandDupAgents(cmdargs) {
5790
+ var r = '';
5791
+ for (var i in parent.duplicateAgentsLog) { r += JSON.stringify(parent.duplicateAgentsLog[i]) + '\r\n'; }
5792
+ if (r == '') { r = 'No duplicate agents in log.'; }
5793
+ return r;
5794
+ }
5795
+
5796
+ function serverUserCommandAgentStats(cmdargs) {
5797
+ var r = '', stats = parent.getAgentStats();
5798
+ for (var i in stats) {
5799
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
5800
+ }
5801
+ return r;
5802
+ }
5803
+
5804
+ function serverUserCommandAgentIssues(cmdargs) {
5805
+ var r = '', stats = parent.getAgentIssues();
5806
+ if (stats.length == 0) {
5807
+ r = "No agent issues.";
5808
+ } else {
5809
+ for (var i in stats) { r += stats[i].join(', ') + '\r\n'; }
5810
+ }
5811
+ return r;
5812
+ }
5813
+
5814
+ function serverUserCommandWebStats(cmdargs) {
5815
+ var r = '', stats = parent.getStats();
5816
+ for (var i in stats) {
5817
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
5818
+ }
5819
+ return r;
5820
+ }
5821
+
5822
+ function serverUserCommandTrafficStats(cmdargs) {
5823
+ var r = '';
5824
+ var stats = parent.getTrafficStats();
5825
+ for (var i in stats) {
5826
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
5827
+ }
5828
+ return r;
5829
+ }
5830
+
5831
+ function serverUserCommandTrafficDelta(cmdargs) {
5832
+ var r = '';
5833
+ const stats = parent.getTrafficDelta(obj.trafficStats);
5834
+ obj.trafficStats = stats.current;
5835
+ for (var i in stats.delta) {
5836
+ if (typeof stats.delta[i] == 'object') { r += (i + ': ' + JSON.stringify(stats.delta[i]) + '\r\n'); } else { r += (i + ': ' + stats.delta[i] + '\r\n'); }
5837
+ }
5838
+ return r;
5839
+ }
5840
+
5841
+ function serverUserCommandWatchdog(cmdargs) {
5842
+ var r = '';
5843
+ if (parent.parent.watchdog == null) {
5844
+ r = 'Server watchdog not active.';
5845
+ } else {
5846
+ r = 'Server watchdog active.\r\n';
5847
+ if (parent.parent.watchdogmaxtime != null) { r += 'Largest timeout was ' + parent.parent.watchdogmax + 'ms on ' + parent.parent.watchdogmaxtime + '\r\n'; }
5848
+ for (var i in parent.parent.watchdogtable) { r += parent.parent.watchdogtable[i] + '\r\n'; }
5849
+ }
5850
+ return r;
5851
+ }
5852
+
5853
+ function serverUserCommandAcceleratorsStats(cmdargs) {
5854
+ var r = '', stats = parent.parent.certificateOperations.getAcceleratorStats();
5855
+ for (var i in stats) {
5856
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
5857
+ }
5858
+ return r;
5859
+ }
5860
+
5861
+ function serverUserCommandMpsStats(cmdargs) {
5862
+ var r = '';
5863
+ if (parent.parent.mpsserver == null) {
5864
+ r = 'MPS not enabled.';
5865
+ } else {
5866
+ var stats = parent.parent.mpsserver.getStats();
5867
+ for (var i in stats) {
5868
+ if (typeof stats[i] == 'object') { r += (i + ': ' + JSON.stringify(stats[i]) + '\r\n'); } else { r += (i + ': ' + stats[i] + '\r\n'); }
5869
+ }
5870
+ }
5871
+ return r;
5872
+ }
5873
+
5874
+ // List all MPS connections and types.
5875
+ function serverUserCommandMps(cmdargs) {
5876
+ var r = '';
5877
+ if (parent.parent.mpsserver == null) {
5878
+ r = 'MPS not enabled.';
5879
+ } else {
5880
+ const connectionTypes = ['CIRA', 'Relay', 'LMS'];
5881
+ for (var nodeid in parent.parent.mpsserver.ciraConnections) {
5882
+ r += nodeid;
5883
+ var connections = parent.parent.mpsserver.ciraConnections[nodeid];
5884
+ for (var i in connections) { r += ', ' + connectionTypes[connections[i].tag.connType]; }
5885
+ r += '\r\n';
5886
+ }
5887
+ if (r == '') { r = 'MPS has not connections.'; }
5888
+ }
5889
+ return r;
5890
+ }
5891
+
5892
+ function serverUserCommandDbStats(cmdargs) {
5893
+ parent.parent.db.getStats(function (stats) {
5894
+ var r2 = '';
5895
+ for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); }
5896
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
5897
+ });
5898
+ }
5899
+
5900
+ function serverUserCommandDbCounters(cmdargs) {
5901
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: JSON.stringify(parent.parent.db.dbCounters, null, 2), tag: command.tag })); } catch (ex) { }
5902
+ }
5903
+
5904
+ function serverUserCommandServerUpdate(cmdargs) {
5905
+ var r = 'Performing server update...';
5906
+ var version = null;
5907
+ if (cmdargs['_'].length > 0) {
5908
+ version = cmdargs['_'][0];
5909
+
5910
+ // This call is SLOW. We only want to validate version if we have to
5911
+ if (version != 'stable' && version != 'latest') {
5912
+ parent.parent.getServerVersions((data) => {
5913
+ var versions = JSON.parse(data);
5914
+
5915
+ if (versions.includes(version)) {
5916
+ if (parent.parent.performServerUpdate(version) == false) {
5917
+ try {
5918
+ ws.send(JSON.stringify({
5919
+ action: 'serverconsole',
5920
+ value: 'Server self-update not possible.'
5921
+ }));
5922
+ } catch (ex) { }
5923
+ }
5924
+ } else {
5925
+ try {
5926
+ ws.send(JSON.stringify({
5927
+ action: 'serverconsole',
5928
+ value: 'Invalid version. Aborting update'
5929
+ }));
5930
+ } catch (ex) { }
5931
+ }
5932
+ });
5933
+ } else {
5934
+ if (parent.parent.performServerUpdate(version) == false) {
5935
+ r = 'Server self-update not possible.';
5936
+ }
5937
+ }
5938
+ } else {
5939
+ if (parent.parent.performServerUpdate(version) == false) {
5940
+ r = 'Server self-update not possible.';
5941
+ }
5942
+ }
5943
+ return r;
5944
+ }
5945
+
5946
+ function serverUserCommandPrint(cmdargs) {
5947
+ console.log(cmdargs['_'][0]);
5948
+ }
5949
+
5950
+ function serverUserCommandAmtPasswords(cmdargs) {
5951
+ var r = '';
5952
+ if (parent.parent.amtPasswords == null) {
5953
+ r = "No Intel AMT password table."
5954
+ } else {
5955
+ for (var i in parent.parent.amtPasswords) { r += (i + ' - ' + parent.parent.amtPasswords[i].join(', ') + '\r\n'); }
5956
+ }
5957
+ return r;
5958
+ }
5959
+
5960
+ function serverUserCommandUpdateCheck(cmdargs) {
5961
+ parent.parent.getServerTags(function (tags, error) {
5962
+ var r2 = '';
5963
+ if (error != null) { r2 += 'Exception: ' + error + '\r\n'; }
5964
+ else { for (var i in tags) { r2 += i + ': ' + tags[i] + '\r\n'; } }
5965
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { }
5966
+ });
5967
+ return "Checking server update...";
5968
+ }
5969
+
5970
+ function serverUserCommandMaintenance(cmdargs) {
5971
+ var arg = null, changed = false, r = '';
5972
+ if ((cmdargs['_'] != null) && (cmdargs['_'][0] != null)) { arg = cmdargs['_'][0].toLowerCase(); }
5973
+ if (arg == 'enabled') { parent.parent.config.settings.maintenancemode = 1; changed = true; }
5974
+ else if (arg == 'disabled') { delete parent.parent.config.settings.maintenancemode; changed = true; }
5975
+ r = 'Maintenance mode: ' + ((parent.parent.config.settings.maintenancemode == null) ? 'Disabled' : 'Enabled');
5976
+ if (changed == false) { r += '\r\nTo change type: maintenance [enabled|disabled]'; }
5977
+ return r;
5978
+ }
5979
+
5980
+ function serverUserCommandInfo(cmdargs) {
5981
+ var info = process.memoryUsage();
5982
+ info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType];
5983
+ try { if (parent.parent.multiServer != null) { info.serverId = parent.parent.multiServer.serverid; } } catch (ex) { }
5984
+ if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; }
5985
+ if (parent.parent.pluginHandler != null) { info.plugins = []; for (var i in parent.parent.pluginHandler.plugins) { info.plugins.push(i); } }
5986
+ try { info.nodeVersion = process.version; } catch (ex) { }
5987
+ try { info.meshVersion = parent.parent.currentVer; } catch (ex) { }
5988
+ try { info.platform = process.platform; } catch (ex) { }
5989
+ try { info.arch = process.arch; } catch (ex) { }
5990
+ try { info.pid = process.pid; } catch (ex) { }
5991
+ try { info.uptime = process.uptime(); } catch (ex) { }
5992
+ try { info.cpuUsage = process.cpuUsage(); } catch (ex) { }
5993
+ try { info.warnings = parent.parent.getServerWarnings(); } catch (ex) { }
5994
+ try { info.database = ["Unknown", "NeDB", "MongoJS", "MongoDB", "MariaDB", "MySQL"][parent.parent.db.databaseType]; } catch (ex) { }
5995
+ try { info.productionMode = ((process.env.NODE_ENV != null) && (process.env.NODE_ENV == 'production')); } catch (ex) { }
5996
+ try { info.allDevGroupManagers = parent.parent.config.settings.managealldevicegroups; } catch (ex) { }
5997
+ return JSON.stringify(info, null, 4);
5998
+ }
5999
+
6000
+ function serverUserCommandNodeConfig(cmdargs) {
6001
+ return JSON.stringify(process.config, null, 4);
6002
+ }
6003
+
6004
+ function serverUserCommandVersions(cmdargs) {
6005
+ return JSON.stringify(process.versions, null, 4);
6006
+ }
6007
+
6008
+ function serverUserCommandArgs(cmdargs) {
6009
+ return cmd + ': ' + JSON.stringify(cmdargs);
6010
+ }
6011
+
6012
+ function serverUserCommandUserSessions(cmdargs) {
6013
+ var r = '';
6014
+ var userSessionCount = 0;
6015
+ var filter = null;
6016
+ var arg = cmdargs['_'][0];
6017
+ if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
6018
+ for (var i in parent.wssessions) {
6019
+ if ((filter == null) || (filter == i)) {
6020
+ userSessionCount++;
6021
+ r += (i + ', ' + parent.wssessions[i].length + ' session' + ((parent.wssessions[i].length > 1) ? 's' : '') + '.\r\n');
6022
+ for (var j in parent.wssessions[i]) {
6023
+ r += ' ' + parent.wssessions[i][j].clientIp + ' --> ' + parent.wssessions[i][j].sessionId + '\r\n';
6024
+ }
6025
+ }
6026
+ }
6027
+ if (userSessionCount == 0) { r = 'None.'; }
6028
+ break;
6029
+ }
6030
+
6031
+ function serverUserCommandCloseUserSessions(cmdargs) {
6032
+ var r = '';
6033
+ var userSessionCount = 0;
6034
+ var filter = null;
6035
+ var arg = cmdargs['_'][0];
6036
+ if (typeof arg == 'string') { if (arg.indexOf('/') >= 0) { filter = arg; } else { filter = ('user/' + domain.id + '/' + arg); } }
6037
+ if (filter == null) {
6038
+ r += "Usage: closeusersessions <username>";
6039
+ } else {
6040
+ r += "Closing user sessions for: " + filter + '\r\n';
6041
+ for (var i in parent.wssessions) {
6042
+ if (filter == i) {
6043
+ userSessionCount++;
6044
+ for (var j in parent.wssessions[i]) {
6045
+ parent.wssessions[i][j].send(JSON.stringify({ action: 'stopped', msg: "Administrator forced disconnection" }));
6046
+ parent.wssessions[i][j].close();
6047
+ }
6048
+ }
6049
+ }
6050
+ if (userSessionCount < 2) { r += 'Disconnected ' + userSessionCount + ' session.'; } else { r += 'Disconnected ' + userSessionCount + ' sessions.'; };
6051
+ }
6052
+ break;
6053
+ }
6054
+
6055
+ function serverUserCommandResetServer(cmdargs) {
6056
+ var r = '';
6057
+ console.log("Server restart...");
6058
+ process.exit(0);
6059
+ break;
6060
+ }
6061
+
6062
+ function serverUserCommandTaslkLimiter(cmdargs) {
6063
+ var r = '';
6064
+ if (parent.parent.taskLimiter != null) {
6065
+ //var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null };
6066
+ const tl = parent.parent.taskLimiter;
6067
+ r += 'MaxTasks: ' + tl.maxTasks + ', NextTaskId: ' + tl.nextTaskId + '\r\n';
6068
+ r += 'MaxTaskTime: ' + (tl.maxTaskTime / 1000) + ' seconds, Timer: ' + (tl.timer != null) + '\r\n';
6069
+ var c = [];
6070
+ for (var i in tl.current) { c.push(i); }
6071
+ r += 'Current (' + tl.currentCount + '): [' + c.join(', ') + ']\r\n';
6072
+ r += 'Pending (High/Med/Low): ' + tl.pending[0].length + ', ' + tl.pending[1].length + ', ' + tl.pending[2].length + '\r\n';
6073
+ }
6074
+ break;
6075
+ }
6076
+
6077
+ function serverUserCommandSetMaxTasks(cmdargs) {
6078
+ var r = '';
6079
+ if ((cmdargs["_"].length != 1) || (parseInt(cmdargs["_"][0]) < 1) || (parseInt(cmdargs["_"][0]) > 1000)) {
6080
+ r = 'Usage: setmaxtasks [1 to 1000]';
6081
+ } else {
6082
+ parent.parent.taskLimiter.maxTasks = parseInt(cmdargs["_"][0]);
6083
+ r = 'MaxTasks set to ' + parent.parent.taskLimiter.maxTasks + '.';
6084
+ }
6085
+ break;
6086
+ }
6087
+
6088
+ function serverUserCommandCores(cmdargs) {
6089
+ var r = '';
6090
+ if (parent.parent.defaultMeshCores != null) { for (var i in parent.parent.defaultMeshCores) { r += i + ': ' + parent.parent.defaultMeshCores[i].length + ' bytes\r\n'; } }
6091
+ break;
6092
+ }
6093
+
6094
+ function serverUserCommandShowPaths(cmdargs) {
6095
+ var r = '';
6096
+ r = 'Parent: ' + parent.parent.parentpath + '\r\n';
6097
+ r += 'Data: ' + parent.parent.datapath + '\r\n';
6098
+ r += 'Files: ' + parent.parent.filespath + '\r\n';
6099
+ r += 'Backup: ' + parent.parent.backuppath + '\r\n';
6100
+ r += 'Record: ' + parent.parent.recordpath + '\r\n';
6101
+ r += 'WebPublic: ' + parent.parent.webPublicPath + '\r\n';
6102
+ r += 'WebViews: ' + parent.parent.webViewsPath + '\r\n';
6103
+ if (parent.parent.webViewsOverridePath) { r += 'XWebPublic: ' + parent.parent.webViewsOverridePath + '\r\n'; }
6104
+ if (parent.parent.webViewsOverridePath) { r += 'XWebViews: ' + parent.parent.webPublicOverridePath + '\r\n'; }
6105
+ break;
6106
+ }
6107
+
6108
+ function serverUserCommandMigrationAgents(cmdargs) {
6109
+ var r = '';
6110
+ if (parent.parent.swarmserver == null) {
6111
+ r = 'Swarm server not running.';
6112
+ } else {
6113
+ for (var i in parent.parent.swarmserver.migrationAgents) {
6114
+ var arch = parent.parent.swarmserver.migrationAgents[i];
6115
+ for (var j in arch) { var agent = arch[j]; r += 'Arch ' + agent.arch + ', Ver ' + agent.ver + ', Size ' + ((agent.binary == null) ? 0 : agent.binary.length) + '<br />'; }
6116
+ }
6117
+ }
6118
+ break;
6119
+ }
6120
+
6121
+ function serverUserCommandSwarmStats(cmdargs) {
6122
+ var r = '';
6123
+ if (parent.parent.swarmserver == null) {
6124
+ r = 'Swarm server not running.';
6125
+ } else {
6126
+ for (var i in parent.parent.swarmserver.stats) {
6127
+ if (typeof parent.parent.swarmserver.stats[i] == 'object') {
6128
+ r += i + ': ' + JSON.stringify(parent.parent.swarmserver.stats[i]) + '\r\n';
6129
+ } else {
6130
+ r += i + ': ' + parent.parent.swarmserver.stats[i] + '\r\n';
6131
+ }
6132
+ }
6133
+ }
6134
+ break;
6135
+ }
6136
+
6137
+ function serverUserCommandRelays(cmdargs) {
6138
+ var r = '';
6139
+ for (var i in parent.wsrelays) {
6140
+ r += 'id: ' + i + ', ' + ((parent.wsrelays[i].state == 2) ? 'connected' : 'pending');
6141
+ if (parent.wsrelays[i].peer1 != null) {
6142
+ r += ', ' + cleanRemoteAddr(parent.wsrelays[i].peer1.req.clientIp);
6143
+ if (parent.wsrelays[i].peer1.user) { r += ' (User:' + parent.wsrelays[i].peer1.user.name + ')' }
6144
+ }
6145
+ if (parent.wsrelays[i].peer2 != null) {
6146
+ r += ' to ' + cleanRemoteAddr(parent.wsrelays[i].peer2.req.clientIp);
6147
+ if (parent.wsrelays[i].peer2.user) { r += ' (User:' + parent.wsrelays[i].peer2.user.name + ')' }
6148
+ }
6149
+ r += '\r\n';
6150
+ }
6151
+ if (r == '') { r = 'No relays.'; }
6152
+ break;
6153
+ }
6154
+
6155
+ function serverUserCommandAutoBackup(cmdargs) {
6156
+ var r = '';
6157
+ var backupResult = parent.db.performBackup(function (msg) {
6158
+ try { ws.send(JSON.stringify({ action: 'serverconsole', value: msg, tag: command.tag })); } catch (ex) { }
6159
+ });
6160
+ if (backupResult == 0) { r = 'Starting auto-backup...'; } else { r = 'Backup alreay in progress.'; }
6161
+ break;
6162
+ }
6163
+
6164
+ function serverUserCommandBackupConfig(cmdargs) {
6165
+ var r = '';
6166
+ r = parent.db.getBackupConfig();
6167
+ break;
6168
+ }
6169
+
6170
+ function serverUserCommandFirebase(cmdargs) {
6171
+ var r = '';
6172
+ if (parent.parent.firebase == null) {
6173
+ r = "Firebase push messaging not supported";
6174
+ } else {
6175
+ r = JSON.stringify(parent.parent.firebase.stats, null, 2);
6176
+ }
6177
+ break;
6178
+ }
6179
+
6180
+
6181
function csvClean(s) { return '\"' + s.split('\"').join('').split(',').join('').split('\r').join('').split('\n').join('') + '\"'; }
6182
6183
// Return detailed information about an array of nodeid's