Improvements to show config option in MyServer tab.

Ylian Saint-Hilaire committed Oct 3, 2023 at 20:35 UTC 3a3663bb55ef34102f84e8ed65ef93625a132fd1
6 files changed +29 -18
meshcentral-config-schema.json
+5
@@ -1414,6 +1414,11 @@
1414 "type": "boolean",
1415 "default": true,
1416 "description": "Allows administrators to access the server trace tab from from the My Server tab."
1417 + },
1418 + "Config": {
1419 + "type": "boolean",
1420 + "default": true,
1421 + "description": "Allows administrators remotely view server configuration on the My Server tab."
1422 }
1423 }
1424 },
meshcentral.js
+1 -3
@@ -3787,9 +3787,7 @@ function getConfig(createSampleConfig) {
3787
3788 // Read configuration file if present and change arguments.
3789 var config = {}, configFilePath = path.join(datapath, 'config.json');
3790 - if (args.configfile) {
3791 - configFilePath = common.joinPath(datapath, args.configfile);
3792 - }
3790 + if (args.configfile) { configFilePath = common.joinPath(datapath, args.configfile); }
3791 if (fs.existsSync(configFilePath)) {
3792 // Load and validate the configuration file
3793 try { config = require(configFilePath); } catch (ex) { console.log('ERROR: Unable to parse ' + configFilePath + '.'); return null; }
meshuser.js
+4 -3
@@ -6513,10 +6513,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
6513 }
6514
6515 function serverCommandServerConfig(command) {
6516 - // Load the server config
6517 - var configFilePath = common.joinPath(parent.parent.datapath, (parent.parent.args.configfile ? parent.parent.args.configfile : 'config.json'));
6518 - if (userHasSiteUpdate())
6516 + // Load the server config.json. This is a sensitive file so care must be taken to only send to trusted administrators.
6517 + if (userHasSiteUpdate() && (domain.myserver !== false) && ((domain.myserver == null) || (domain.myserver.config === true))) {
6518 + const configFilePath = common.joinPath(parent.parent.datapath, (parent.parent.args.configfile ? parent.parent.args.configfile : 'config.json'));
6519 fs.readFile(configFilePath, 'utf8', function (err, data) { obj.send({ action: 'serverconfig', data: data }); });
6520 + }
6521 }
6522
6523 function serverCommandServerStats(command) {
sample-config-advanced.json
+2 -1
@@ -289,7 +289,8 @@
289 "Upgrade": false,
290 "ErrorLog": false,
291 "Console": false,
292 - "Trace": false
292 + "Trace": false,
293 + "Config": false
294 },
295 "_passwordRequirements": {
296 "min": 8,
views/default.handlebars
+15 -10
@@ -574,7 +574,7 @@
574 <div id="p2ServerActionsGoogleBackup" style="display:none"><div class="p2AccountActions"><span id="p2ServerActionsGoogleBackupCheck" style="display:none"><strong>&#x2713;</strong></span></div><span><a href=# onclick="return server_setupGoogleDriveBackup()">Google Drive backup</a><br /></span></div>
575 <div id="p2ServerActionsVersion"><div class="p2AccountActions"><span style="display:none"><strong>&#x2713;</strong></span></div><a href=# onclick="return server_showVersionDlg()">Check server version</a></div>
576 <div id="p2ServerActionsErrors"><div class="p2AccountActions"><span style="display:none"><strong>&#x2713;</strong></span></div><a href=# onclick="return server_showErrorsDlg()">Show server error log</a></div>
577 - <div id="p2ServerActionsConfig"><div class="p2AccountActions"><span style="display:none"><strong>&#x2713;</strong></span></div><a href=# onclick="return server_showConfigDlg()">Show server config</a></div>
577 + <div id="p2ServerActionsConfig"><div class="p2AccountActions"><span style="display:none"><strong>&#x2713;</strong></span></div><a href=# onclick="return server_showConfigDlg()">Show server configuration</a></div>
578 </div>
579 <br />
580 </div>
@@ -2151,14 +2151,14 @@
2151 //QV('p2AccountImage', ((features & 4) == 0) && (serverinfo.domainauth == false)); // If account actions are not visible, also remove the image on that panel
2152 QV('accountCreateLoginTokenSpan', features2 & 0x00000080);
2153 QV('p2AccountImageFrame', !accountSettingsLocked)
2154 - QV('p2ServerActions', (siteRights & 21) && ((serverFeatures & 15) != 0));
2154 + QV('p2ServerActions', (siteRights & 21) && ((serverFeatures & 143) != 0));
2155 QV('LeftMenuMyServer', (siteRights & 21) && ((serverFeatures & 64) != 0)); // 16 + 4 + 1
2156 QV('MainMenuMyServer', siteRights & 21);
2157 QV('p2ServerActionsBackup', (siteRights & 1) && ((serverFeatures & 1) != 0));
2158 QV('p2ServerActionsRestore', (siteRights & 4) && ((serverFeatures & 2) != 0));
2159 QV('p2ServerActionsVersion', (siteRights & 16) && ((serverFeatures & 4) != 0));
2160 QV('p2ServerActionsErrors', (siteRights & 16) && ((serverFeatures & 8) != 0));
2161 - QV('p2ServerActionsConfig', (siteRights & 16) && ((serverFeatures & 8) != 0));
2161 + QV('p2ServerActionsConfig', (siteRights & 16) && ((serverFeatures & 128) != 0));
2162 QV('MainMenuMyFiles', siteRights & 8);
2163 QV('LeftMenuMyFiles', siteRights & 8);
2164 if (((siteRights & 8) == 0) && (xxcurrentView == 5)) { setDialogMode(0); go(1); }
@@ -2746,7 +2746,7 @@
2746 case 'servererrors': {
2747 if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerErrors')) {
2748 if (message.data == null) {
2749 - setDialogMode(2, "MeshCentral Server Errors", 1, null, "Server has no error log.");
2749 + setDialogMode(2, "Server Errors", 1, null, "Server has no error log.");
2750 } else {
2751 var x = '<div class="dialogText dialogTextLog"><pre id=d2ServerErrorsLogPre>' + EscapeHtml(message.data) + '</pre></div>';
2752 x += '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="' + "Download error log" + '" style=cursor:pointer onclick=d2CopyServerErrorsToClip()></div>';
@@ -2760,11 +2760,14 @@
2760 case 'serverconfig': {
2761 if ((xxdialogMode == 2) && (xxdialogTag == 'MeshCentralServerConfig')) {
2762 if (message.data == null) {
2763 - setDialogMode(2, "MeshCentral Server Config", 1, null, "Server has no config file.");
2763 + setDialogMode(2, "Server Configuration", 1, null, "Server has no config file.");
2764 } else {
2765 - var x = '<div class="dialogText dialogTextLog"><pre id=d2ServerConfigPre style=overflow:auto>' + EscapeHtml(message.data) + '</pre></div>';
2766 - x += '<br /><div style=float:right><img src=images/link4.png height=10 width=10 title="' + "Download server config" + '" style=cursor:pointer onclick=d2CopyServerConfigToClip()></div>';
2767 - setDialogMode(2, "MeshCentral Server Config", 3, null, x);
2765 + setDialogMode(4, "Server Configuration", 2);
2766 + QV('d4EncodingButton', false);
2767 + QS('dialog').width = 'auto';
2768 + QS('dialog').bottom = '80px';
2769 + QS('dialog').top = QS('dialog').left = QS('dialog').right = '100px';
2770 + Q('d4editorarea').value = message.data;
2771 }
2772 }
2773 break;
@@ -2998,6 +3001,7 @@
3001 meshserver.send({ action: 'fileoperation', fileop: 'set', path: tag.path, file: tag.file, data: btoa(data) });
3002 }
3003 setDialogMode(4, EscapeHtml(message.file), 3, p5editSaveBack, null, message);
3004 + QV('d4EncodingButton', true);
3005 QS('dialog').width = 'auto';
3006 QS('dialog').bottom = '80px';
3007 QS('dialog').top = QS('dialog').left = QS('dialog').right = '100px';
@@ -11073,6 +11077,7 @@
11077 if (gdownloadFile.tag == 'viewer') {
11078 // View the file in the dialog box
11079 setDialogMode(4, EscapeHtml(gdownloadFile.file), 3, p13editSaveBack, null, gdownloadFile.file);
11080 + QV('d4EncodingButton', true);
11081 QS('dialog').width = 'auto';
11082 QS('dialog').bottom = '80px';
11083 QS('dialog').top = QS('dialog').left = QS('dialog').right = '100px';
@@ -12640,7 +12645,7 @@
12645
12646 function server_showErrorsDlg() {
12647 if (xxdialogMode) return false;
12643 - setDialogMode(2, "MeshCentral Errors", 1, null, "Loading...", 'MeshCentralServerErrors');
12648 + setDialogMode(2, "Server Errors", 1, null, "Loading...", 'MeshCentralServerErrors');
12649 meshserver.send({ action: 'servererrors' });
12650 return false;
12651 }
@@ -12650,7 +12655,7 @@
12655
12656 function server_showConfigDlg() {
12657 if (xxdialogMode) return false;
12653 - setDialogMode(2, "MeshCentral Server Config", 1, null, "Loading...", 'MeshCentralServerConfig');
12658 + setDialogMode(2, "Server Configuration", 1, null, "Loading...", 'MeshCentralServerConfig');
12659 meshserver.send({ action: 'serverconfig' });
12660 return false;
12661 }
webserver.js
+2 -1
@@ -3063,7 +3063,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
3063 if (domain.customui != null) { customui = encodeURIComponent(JSON.stringify(domain.customui)); }
3064
3065 // Server features
3066 - var serverFeatures = 127;
3066 + var serverFeatures = 255;
3067 if (domain.myserver === false) { serverFeatures = 0; } // 64 = Show "My Server" tab
3068 else if (typeof domain.myserver == 'object') {
3069 if (domain.myserver.backup !== true) { serverFeatures -= 1; } // Disallow simple server backups
@@ -3072,6 +3072,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
3072 if (domain.myserver.errorlog !== true) { serverFeatures -= 8; } // Disallow show server crash log
3073 if (domain.myserver.console !== true) { serverFeatures -= 16; } // Disallow server console
3074 if (domain.myserver.trace !== true) { serverFeatures -= 32; } // Disallow server tracing
3075 + if (domain.myserver.config !== true) { serverFeatures -= 128; } // Disallow server configuration
3076 }
3077 if (obj.db.databaseType != 1) { // If not using NeDB, we can't backup using the simple system.
3078 if ((serverFeatures & 1) != 0) { serverFeatures -= 1; } // Disallow server backups