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);