Version 0.7.33

Ylian Saint-Hilaire committed Dec 29, 2020 at 15:13 UTC b7591dc5bb8ed9905348f8183c5f6d6548b29ead
3 files changed +30 -7
meshcentral-config-schema.json
+1
@@ -162,6 +162,7 @@
162 "title2": { "type": "string", "default": null, "description": "Secondary title text that is placed on the upper right on the title on many web pages." },
163 "titlePicture": { "type": "string", "default": null, "description": "Web site .png logo file that is 450x66 in size placed in meshcentral-data that is used on the top of many pages." },
164 "loginPicture": { "type": "string", "default": null, "description": "Web site .png logo file placed in meshcentral-data that used on the login page when sitestyle is 2." },
165 + "rootRedirect": { "type": "string", "default": null, "description": "Redirects HTTP root requests to this URL. When in use, direct users to /login to see the normal login page." },
166 "userQuota": { "type": "integer" },
167 "meshQuota": { "type": "integer" },
168 "loginKey": { "type": [ "string", "array" ], "items": { "type": "string" }, "default": null, "description": "Requires that users add the value ?key=xxx in the URL in order to see the web site." },
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.7.32",
3 + "version": "0.7.33",
4 "keywords": [
5 "Remote Device Management",
6 "Remote Device Monitoring",
webserver.js
+28 -6
@@ -204,7 +204,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
204 for (i in parent.config.domains) { domainUserCount[i] = 0; }
205 for (i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; }
206 for (i in parent.config.domains) {
207 - if (domainUserCount[i] == 0) {
207 + if ((parent.config.domains[i].share == null) && (domainUserCount[i] == 0)) {
208 // If newaccounts is set to no new accounts, but no accounts exists, temporarly allow account creation.
209 //if ((parent.config.domains[i].newaccounts === 0) || (parent.config.domains[i].newaccounts === false)) { parent.config.domains[i].newaccounts = 2; }
210 console.log('Server ' + ((i == '') ? '' : (i + ' ')) + 'has no users, next new account will be site administrator.');
@@ -871,6 +871,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
871 func('');
872 }
873
874 + // Redirect a root request to a different page
875 + function handleRootRedirect(req, res, direct) {
876 + const domain = checkUserIpAddress(req, res);
877 + if (domain == null) { return; }
878 + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
879 + res.redirect(domain.rootredirect + getQueryPortion(req));
880 + }
881 +
882 function handleLoginRequest(req, res, direct) {
883 const domain = checkUserIpAddress(req, res);
884 if (domain == null) { return; }
@@ -2842,6 +2850,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2850 // Use the logo on file
2851 try { res.sendFile(obj.path.join(obj.parent.datapath, domain.loginpicture)); return; } catch (ex) { res.sendStatus(404); }
2852 }
2853 + } else {
2854 + res.sendStatus(404);
2855 }
2856 }
2857
@@ -4961,7 +4971,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4971 'Referrer-Policy': 'no-referrer',
4972 'X-XSS-Protection': '1; mode=block',
4973 'X-Content-Type-Options': 'nosniff',
4964 - 'Content-Security-Policy': "default-src 'none'; font-src 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self'" + geourl + selfurl + "; img-src 'self'" + geourl + " data:; style-src 'self' 'unsafe-inline'; frame-src 'self' mcrouter:; media-src 'self'; form-action 'self'"
4974 + 'Content-Security-Policy': "default-src 'none'; font-src 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self'" + geourl + selfurl + "; img-src 'self'" + geourl + " data:; style-src 'self' 'unsafe-inline'; frame-src 'self' https://*.youtube.com mcrouter:; media-src 'self'; form-action 'self'"
4975 };
4976 if ((parent.config.settings.allowframing !== true) && (typeof parent.config.settings.allowframing !== 'string')) { headers['X-Frame-Options'] = 'sameorigin'; }
4977 res.set(headers);
@@ -4982,7 +4992,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
4992 res.sendStatus(404);
4993 } else {
4994 // Check if the file exists, if so, serve it.
4985 - obj.fs.exists(obj.path.join(domain.share, rpath), function (exists) { if (exists == true) { res.sendfile(rpath, { root: domain.share }); } else { res.sendStatus(404); } });
4995 + var fpath = obj.path.join(domain.share, rpath);
4996 + if (rpath == '') {
4997 + res.redirect(req.url + '/' + getQueryPortion(req));
4998 + } else {
4999 + obj.fs.exists(fpath, function (exists) { if (exists == true) { res.sendFile(rpath, { root: domain.share }); } else { next(); } });
5000 + }
5001 }
5002 } else {
5003 //if (parent.config.settings.accesscontrolalloworigin != null) { headers['Access-Control-Allow-Origin'] = parent.config.settings.accesscontrolalloworigin; }
@@ -5029,14 +5044,21 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
5044 if (parent.config.domains[i].dns != null) { continue; } // This is a subdomain with a DNS name, no added HTTP bindings needed.
5045 var domain = parent.config.domains[i];
5046 var url = domain.url;
5032 - obj.app.get(url, handleRootRequest);
5033 - obj.app.post(url, handleRootPostRequest);
5047 + if (domain.rootredirect == null) {
5048 + // Present the login page as the root page
5049 + obj.app.get(url, handleRootRequest);
5050 + obj.app.post(url, handleRootPostRequest);
5051 + } else {
5052 + // Root page redirects the user to a different URL
5053 + obj.app.get(url, handleRootRedirect);
5054 + }
5055 obj.app.get(url + 'refresh.ashx', function (req, res) { res.sendStatus(200); });
5056 if ((domain.myserver !== false) && ((domain.myserver == null) || (domain.myserver.backup === true))) { obj.app.get(url + 'backup.zip', handleBackupRequest); }
5057 if ((domain.myserver !== false) && ((domain.myserver == null) || (domain.myserver.restore === true))) { obj.app.post(url + 'restoreserver.ashx', handleRestoreRequest); }
5058 obj.app.get(url + 'terms', handleTermsRequest);
5059 obj.app.get(url + 'xterm', handleXTermRequest);
5039 - obj.app.post(url + 'login', handleLoginRequest);
5060 + obj.app.get(url + 'login', handleRootRequest);
5061 + obj.app.post(url + 'login', handleRootPostRequest);
5062 obj.app.post(url + 'tokenlogin', handleLoginRequest);
5063 obj.app.get(url + 'logout', handleLogoutRequest);
5064 obj.app.get(url + 'MeshServerRootCert.cer', handleRootCertRequest);