From 9af599e4df2f90cd7ddf5604207dfaadab5d724b Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 20 Nov 2020 16:43:58 -0800 Subject: [PATCH] Added server maintenance mode. --- meshcentral-config-schema.json | 1 + meshuser.js | 9 ++ public/scripts/amt-wsman-0.2.0-min.js | 2 +- translate/translate.json | 177 ++++++++++++++------------ views/login.handlebars | 2 +- views/login2.handlebars | 2 +- views/message.handlebars | 4 +- views/message2.handlebars | 4 +- webserver.js | 36 ++++++ 9 files changed, 154 insertions(+), 83 deletions(-) diff --git a/meshcentral-config-schema.json b/meshcentral-config-schema.json index 53272afd..33d13a64 100644 --- a/meshcentral-config-schema.json +++ b/meshcentral-config-schema.json @@ -14,6 +14,7 @@ "mongoDumpPath": { "type": "string" }, "WANonly": { "type": "boolean", "default": false, "description": "When enabled, only MeshCentral WAN features are enabled and agents will connect to the server using a well known DNS name." }, "LANonly": { "type": "boolean", "default": false, "description": "When enabled, only MeshCentral LAN features are enabled and agents will find the server using multicast LAN packets." }, + "maintenanceMode": { "type": "boolean", "default": false, "description": "When enabled the server is in maintenance mode, only administrators can login. Use the maintenance command in server console to change." }, "sessionTime": { "type": "integer" }, "sessionKey": { "type": "string" }, "sessionSameSite": { "type": "string" }, diff --git a/meshuser.js b/meshuser.js index 9a41c189..6222b57f 100644 --- a/meshuser.js +++ b/meshuser.js @@ -1109,6 +1109,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use r = "Checking server update..."; break; } + case 'maintenance': { + var arg = null, changed = false; + if ((cmdargs['_'] != null) && (cmdargs['_'][0] != null)) { arg = cmdargs['_'][0].toLowerCase(); } + if (arg == 'enabled') { parent.parent.config.settings.maintenancemode = 1; changed = true; } + else if (arg == 'disabled') { delete parent.parent.config.settings.maintenancemode; changed = true; } + r = 'Maintenance mode: ' + ((parent.parent.config.settings.maintenancemode == null) ? 'Disabled' : 'Enabled'); + if (changed == false) { r += '\r\nTo change type: maintenance [enabled|disabled]'; } + break; + } case 'info': { var info = process.memoryUsage(); info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType]; diff --git a/public/scripts/amt-wsman-0.2.0-min.js b/public/scripts/amt-wsman-0.2.0-min.js index a8eb3bca..86d1ae50 100644 --- a/public/scripts/amt-wsman-0.2.0-min.js +++ b/public/scripts/amt-wsman-0.2.0-min.js @@ -1 +1 @@ -var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return''+e.InstanceID+"";var s="";for(var r in e)if(e.hasOwnProperty(r)){if(s+='',e[r].ReferenceParameters){s+="",s+=""+e[r].Address+""+e[r].ReferenceParameters.ResourceURI+"";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o"+a[o].Value+"";else s+=""+a.Value+"";s+=""}else s+=e[r];s+=""}return s+=""}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('
"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,d,c){var m="",i="";null!=d&&null!=c&&(m="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken"+d+''+c+"",i=''),l=null!=l&&null!=l?""+l+"":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(n)+m+'
'+r+""+i+"PT0.000000S";p.PerformAjax(u+"
",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(o)+"";p.PerformAjax(t+"",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S"+w(t)+""+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+=""+s[o].Address+""+s[o].ReferenceParameters.ResourceURI+"";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n"+t[n].Value+"";else a+=""+t.Value+"";a+=""}else if(Array.isArray(s[o]))for(n=0;n"+s[o][n].toString()+"";else a+=""+s[o].toString()+"";return a+=""}(e,s);p.PerformAjax(n+"",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(t)+"';for(var d in s)l+=""+s[d]+"";p.PerformAjax(l+"",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S'+s+"",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(s)+"";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var d in r)if(null!=r[d])if(Array.isArray(r[d]))for(var c in r[d])l+=""+r[d][c]+"";else l+=""+r[d]+"";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+""+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(n)+"'+r+"",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S'+s+"99999999",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o'+e.InstanceID+"";var s="";for(var r in e)if(e.hasOwnProperty(r)){if(s+='',e[r].ReferenceParameters){s+="",s+=""+e[r].Address+""+e[r].ReferenceParameters.ResourceURI+"";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o"+a[o].Value+"";else s+=""+a.Value+"";s+=""}else s+=e[r];s+=""}return s+=""}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('
"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,c,d){var m="",i="";null!=c&&null!=d&&(m="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken"+c+''+d+"",i=''),l=null!=l&&null!=l?""+l+"":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(n)+m+'
'+r+""+i+"PT0.000000S";p.PerformAjax(u+"
",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(o)+"";p.PerformAjax(t+"",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S"+w(t)+""+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+=""+s[o].Address+""+s[o].ReferenceParameters.ResourceURI+"";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n"+t[n].Value+"";else a+=""+t.Value+"";a+=""}else if(Array.isArray(s[o]))for(n=0;n"+s[o][n].toString()+"";else a+=""+s[o].toString()+"";return a+=""}(e,s);p.PerformAjax(n+"",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(t)+"';for(var c in s)l+=""+s[c]+"";p.PerformAjax(l+"",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S'+s+"",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(s)+"";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S",s,r,a)},p.ExecMethod=function(e,s,r,a,o,t,n){var l="";for(var c in r)if(null!=r[c])if(Array.isArray(r[c]))for(var d in r[c])l+=""+r[c][d]+"";else l+=""+r[c]+"";p.ExecMethodXml(e,s,l,a,o,t,n)},p.ExecMethodXml=function(e,s,r,a,o,t,n){p.PerformAjax(e+"/"+s+""+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(n)+"'+r+"",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S'+s+"99999999",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o3->7", - "message2.handlebars->5->7" + "message.handlebars->3->8", + "message2.handlebars->5->8" ] }, { @@ -13019,8 +13019,8 @@ "zh-chs": "用户“ {1} ”的电邮“ {0} ”已通过验证。", "zh-cht": "用戶“ {1} ”的電郵“ {0} ”已通過驗證。", "xloc": [ - "message.handlebars->3->6", - "message2.handlebars->5->6" + "message.handlebars->3->7", + "message2.handlebars->5->7" ] }, { @@ -13040,8 +13040,8 @@ "zh-chs": "未验证用户“ {1} ”的电邮“ {0} ”。", "zh-cht": "未驗證用戶“ {1} ”的電郵“ {0} ”。", "xloc": [ - "message.handlebars->3->9", - "message2.handlebars->5->9" + "message.handlebars->3->10", + "message2.handlebars->5->10" ] }, { @@ -13098,8 +13098,8 @@ "zh-chs": "错误:无效的帐户检查,验证网址仅在30分钟内有效。", "zh-cht": "錯誤:無效的帳戶檢查,驗證網址僅在30分鐘內有效。", "xloc": [ - "message.handlebars->3->13", - "message2.handlebars->5->13" + "message.handlebars->3->14", + "message2.handlebars->5->14" ] }, { @@ -13119,8 +13119,8 @@ "zh-chs": "错误:无效的帐户检查。", "zh-cht": "錯誤:無效的帳戶檢查。", "xloc": [ - "message.handlebars->3->12", - "message2.handlebars->5->12" + "message.handlebars->3->13", + "message2.handlebars->5->13" ] }, { @@ -13140,8 +13140,8 @@ "zh-chs": "错误:无效的域。", "zh-cht": "錯誤:無效的域。", "xloc": [ - "message.handlebars->3->3", - "message2.handlebars->5->3" + "message.handlebars->3->4", + "message2.handlebars->5->4" ] }, { @@ -13161,8 +13161,8 @@ "zh-chs": "错误:用户“ {1} ”的电邮“ {0} ”无效。", "zh-cht": "錯誤:用戶“ {1} ”的電郵“ {0} ”無效。", "xloc": [ - "message.handlebars->3->5", - "message2.handlebars->5->5" + "message.handlebars->3->6", + "message2.handlebars->5->6" ] }, { @@ -13182,8 +13182,8 @@ "zh-chs": "错误:无效的用户名“ {0} ”。", "zh-cht": "錯誤:無效的用戶名“ {0} ”。", "xloc": [ - "message.handlebars->3->4", - "message2.handlebars->5->4" + "message.handlebars->3->5", + "message2.handlebars->5->5" ] }, { @@ -13680,11 +13680,11 @@ "default.handlebars->29->320", "login-mobile.handlebars->5->42", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3", - "login.handlebars->5->43", + "login.handlebars->5->44", "login.handlebars->container->column_l->centralTable->1->0->logincell->resettokenpanel->1->5->1->2->1->3", "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->3", - "login2.handlebars->7->22", - "login2.handlebars->7->44", + "login2.handlebars->7->23", + "login2.handlebars->7->45", "login2.handlebars->centralTable->1->0->logincell->resetpanel->1->7->1->0->1", "login2.handlebars->centralTable->1->0->logincell->resetpanel->1->7->1->0->1", "login2.handlebars->centralTable->1->0->logincell->resettokenpanel->1->5->1->2farow2->1->3", @@ -13751,8 +13751,8 @@ "zh-cht": "電郵確認", "xloc": [ "login-mobile.handlebars->5->43", - "login.handlebars->5->44", - "login2.handlebars->7->45" + "login.handlebars->5->45", + "login2.handlebars->7->46" ] }, { @@ -13986,7 +13986,7 @@ "login-mobile.handlebars->5->21", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->2->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpanel->1->7->1->0->1", - "login.handlebars->5->21", + "login.handlebars->5->22", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->2->nuEmail", "login.handlebars->container->column_l->centralTable->1->0->logincell->resetpanel->1->7->1->0->1", "login2.handlebars->centralTable->1->0->logincell->createpanel->1->9->1->2->nuEmail" @@ -15639,8 +15639,8 @@ "zh-cht": "忘記了密碼?", "xloc": [ "login-mobile.handlebars->5->22", - "login.handlebars->5->22", - "login2.handlebars->7->23" + "login.handlebars->5->23", + "login2.handlebars->7->24" ] }, { @@ -16506,8 +16506,8 @@ "zh-chs": "进入登录页面", "zh-cht": "進入登入頁面", "xloc": [ - "message.handlebars->3->16", - "message2.handlebars->5->16" + "message.handlebars->3->18", + "message2.handlebars->5->18" ] }, { @@ -16570,10 +16570,10 @@ "xloc": [ "login-mobile.handlebars->5->29", "login-mobile.handlebars->5->33", - "login.handlebars->5->29", - "login.handlebars->5->33", - "login2.handlebars->7->30", - "login2.handlebars->7->34" + "login.handlebars->5->30", + "login.handlebars->5->34", + "login2.handlebars->7->31", + "login2.handlebars->7->35" ] }, { @@ -17777,6 +17777,13 @@ "login2.handlebars->7->2" ] }, + { + "en": "If you are an administrator, [login here].", + "xloc": [ + "message.handlebars->3->17", + "message2.handlebars->5->17" + ] + }, { "cs": "Pokud jste tento požadavek nezačali, ignorujte tento e-mail.", "de": "Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte.", @@ -21591,8 +21598,8 @@ "zh-chs": "登录并转到“我的帐户”选项卡以更新密码。", "zh-cht": "登入並進入“我的帳戶”標籤以更新密碼。", "xloc": [ - "message.handlebars->3->11", - "message2.handlebars->5->11" + "message.handlebars->3->12", + "message2.handlebars->5->12" ] }, { @@ -22590,8 +22597,8 @@ "zh-cht": "最大長度為{0}", "xloc": [ "login-mobile.handlebars->5->37", - "login.handlebars->5->37", - "login2.handlebars->7->38" + "login.handlebars->5->38", + "login2.handlebars->7->39" ] }, { @@ -23379,8 +23386,8 @@ "zh-cht": "最小長度為{0}", "xloc": [ "login-mobile.handlebars->5->36", - "login.handlebars->5->36", - "login2.handlebars->7->37" + "login.handlebars->5->37", + "login2.handlebars->7->38" ] }, { @@ -26617,8 +26624,8 @@ "zh-cht": "密碼提示", "xloc": [ "login-mobile.handlebars->5->27", - "login.handlebars->5->27", - "login2.handlebars->7->28", + "login.handlebars->5->28", + "login2.handlebars->7->29", "login2.handlebars->centralTable->1->0->logincell->loginpanel->1->5->1->4->1" ] }, @@ -26665,12 +26672,12 @@ "xloc": [ "login-mobile.handlebars->5->31", "login-mobile.handlebars->5->35", - "login.handlebars->5->31", - "login.handlebars->5->35", - "login.handlebars->5->42", - "login2.handlebars->7->32", - "login2.handlebars->7->36", - "login2.handlebars->7->43" + "login.handlebars->5->32", + "login.handlebars->5->36", + "login.handlebars->5->43", + "login2.handlebars->7->33", + "login2.handlebars->7->37", + "login2.handlebars->7->44" ] }, { @@ -26712,8 +26719,8 @@ "zh-chs": "帐户{0}的密码已重置为:", "zh-cht": "帳戶{0}的密碼已重置為:", "xloc": [ - "message.handlebars->3->10", - "message2.handlebars->5->10" + "message.handlebars->3->11", + "message2.handlebars->5->11" ] }, { @@ -28842,8 +28849,8 @@ "zh-cht": "記住此裝置{0}天。", "xloc": [ "login-mobile.handlebars->5->20", - "login.handlebars->5->20", - "login2.handlebars->7->21" + "login.handlebars->5->21", + "login2.handlebars->7->22" ] }, { @@ -31249,10 +31256,10 @@ "xloc": [ "login-mobile.handlebars->5->23", "login-mobile.handlebars->5->25", - "login.handlebars->5->23", - "login.handlebars->5->25", - "login2.handlebars->7->24", - "login2.handlebars->7->26" + "login.handlebars->5->24", + "login.handlebars->5->26", + "login2.handlebars->7->25", + "login2.handlebars->7->27" ] }, { @@ -31890,8 +31897,8 @@ "zh-chs": "将保安编码发送到注册的电邮地址?", "zh-cht": "將保安編碼發送到註冊的電郵地址?", "xloc": [ - "login.handlebars->5->24", - "login2.handlebars->7->25" + "login.handlebars->5->25", + "login2.handlebars->7->26" ] }, { @@ -31911,8 +31918,8 @@ "zh-chs": "将保安编码发送到注册电话号码?", "zh-cht": "將保安編碼發送到註冊電話號碼?", "xloc": [ - "login.handlebars->5->26", - "login2.handlebars->7->27" + "login.handlebars->5->27", + "login2.handlebars->7->28" ] }, { @@ -32203,6 +32210,13 @@ "default.handlebars->29->2126" ] }, + { + "en": "Server Under Maintenance", + "xloc": [ + "message.handlebars->3->3", + "message2.handlebars->5->3" + ] + }, { "cs": "Aktualizace serveru", "de": "Server-Aktualisierungen", @@ -32346,6 +32360,13 @@ "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->1" ] }, + { + "en": "Server under maintenance.", + "xloc": [ + "login.handlebars->5->20", + "login2.handlebars->7->21" + ] + }, { "cs": "ServerStats.csv", "de": "ServerStats.csv", @@ -32788,8 +32809,8 @@ "nl": "link voor delen is verlopen.", "fr": "Le lien de partage a expiré.", "xloc": [ - "message.handlebars->3->15", - "message2.handlebars->5->15" + "message.handlebars->3->16", + "message2.handlebars->5->16" ] }, { @@ -32797,8 +32818,8 @@ "nl": "Link voor delen is niet geldig.", "fr": "Le lien de partage n'est pas encore valide.", "xloc": [ - "message.handlebars->3->14", - "message2.handlebars->5->14" + "message.handlebars->3->15", + "message2.handlebars->5->15" ] }, { @@ -34884,10 +34905,10 @@ "xloc": [ "login-mobile.handlebars->5->28", "login-mobile.handlebars->5->32", - "login.handlebars->5->28", - "login.handlebars->5->32", - "login2.handlebars->7->29", - "login2.handlebars->7->33" + "login.handlebars->5->29", + "login.handlebars->5->33", + "login2.handlebars->7->30", + "login2.handlebars->7->34" ] }, { @@ -38852,8 +38873,8 @@ "zh-chs": "用户帐户{1}的已验证电邮{0}。", "zh-cht": "用戶帳戶{1}的已驗證電郵{0}。", "xloc": [ - "message.handlebars->3->8", - "message2.handlebars->5->8" + "message.handlebars->3->9", + "message2.handlebars->5->9" ] }, { @@ -39375,10 +39396,10 @@ "xloc": [ "login-mobile.handlebars->5->30", "login-mobile.handlebars->5->34", - "login.handlebars->5->30", - "login.handlebars->5->34", - "login2.handlebars->7->31", - "login2.handlebars->7->35" + "login.handlebars->5->31", + "login.handlebars->5->35", + "login2.handlebars->7->32", + "login2.handlebars->7->36" ] }, { @@ -42452,8 +42473,8 @@ "zh-cht": "{0}小寫", "xloc": [ "login-mobile.handlebars->5->39", - "login.handlebars->5->39", - "login2.handlebars->7->40" + "login.handlebars->5->40", + "login2.handlebars->7->41" ] }, { @@ -42554,8 +42575,8 @@ "zh-cht": "{0}非字母數字", "xloc": [ "login-mobile.handlebars->5->41", - "login.handlebars->5->41", - "login2.handlebars->7->42" + "login.handlebars->5->42", + "login2.handlebars->7->43" ] }, { @@ -42576,8 +42597,8 @@ "zh-cht": "{0}數字", "xloc": [ "login-mobile.handlebars->5->40", - "login.handlebars->5->40", - "login2.handlebars->7->41" + "login.handlebars->5->41", + "login2.handlebars->7->42" ] }, { @@ -42744,8 +42765,8 @@ "zh-cht": "{0}大寫", "xloc": [ "login-mobile.handlebars->5->38", - "login.handlebars->5->38", - "login2.handlebars->7->39" + "login.handlebars->5->39", + "login2.handlebars->7->40" ] }, { diff --git a/views/login.handlebars b/views/login.handlebars index 0cbcf7b5..710aea80 100644 --- a/views/login.handlebars +++ b/views/login.handlebars @@ -328,7 +328,7 @@ var i; var messageid = parseInt('{{{messageid}}}'); var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent."]; - var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."]; + var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance."]; if (messageid > 0) { var msg = ''; if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; } diff --git a/views/login2.handlebars b/views/login2.handlebars index 2b069926..464f9049 100644 --- a/views/login2.handlebars +++ b/views/login2.handlebars @@ -340,7 +340,7 @@ var i; var messageid = parseInt('{{{messageid}}}'); var okmessages = ['', "If valid, reset mail sent.", "Email sent.", "Email verification required, check your mailbox and click the confirmation link.", "SMS sent."]; - var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later."]; + var failmessages = ["Unable to create account.", "Account limit reached.", "Existing account with this email address.", "Invalid account creation token.", "Username already exists.", "Password rejected, use a different one.", "Invalid email.", "Account not found.", "Invalid token, try again.", "Unable to sent email.", "Account locked.", "Access denied.", "Login failed, check username and password.", "Password change requested.", "IP address blocked, try again later.", "Server under maintenance."]; if (messageid > 0) { var msg = ''; if ((messageid < 100) && (messageid < okmessages.length)) { msg = okmessages[messageid]; } diff --git a/views/message.handlebars b/views/message.handlebars index eda42b45..0053f419 100644 --- a/views/message.handlebars +++ b/views/message.handlebars @@ -53,6 +53,7 @@ var title = ''; if (titleid == 1) { title = "Account Verification"; } if (titleid == 2) { title = "Desktop Sharing"; } + if (titleid == 3) { title = "Server Under Maintenance"; } QH('topTitle', Q('topTitle').innerText + ' - ' + title); QH('mainTitle', title); @@ -74,10 +75,11 @@ case 10: { msg = "ERROR: Invalid account check, verification url is only valid for 30 minutes."; break; } case 11: { msg = "Sharing link not valid yet."; break; } case 12: { msg = "Sharing link is expired."; break; } + case 13: { msg = "If you are an administrator, [login here].".replace('[', '').replace(']', ''); break; } } // Add login page link - if ((msgid != 11) && (msgid != 12)) { msg += ' ' + "Go to login page" + '.' } + if ((msgid != 11) && (msgid != 12) && (msgid != 13)) { msg += ' ' + "Go to login page" + '.' } QH('mainMessage', msg); function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); }; diff --git a/views/message2.handlebars b/views/message2.handlebars index 6b56083a..09ad8964 100644 --- a/views/message2.handlebars +++ b/views/message2.handlebars @@ -54,6 +54,7 @@ var title = ''; if (titleid == 1) { title = "Account Verification"; } if (titleid == 2) { title = "Desktop Sharing"; } + if (titleid == 3) { title = "Server Under Maintenance"; } QH('topTitle', Q('topTitle').innerText + ' - ' + title); QH('mainTitle', title); @@ -75,10 +76,11 @@ case 10: { msg = "ERROR: Invalid account check, verification url is only valid for 30 minutes."; break; } case 11: { msg = "Sharing link not valid yet."; break; } case 12: { msg = "Sharing link is expired."; break; } + case 13: { msg = "If you are an administrator, [login here].".replace('[', '').replace(']', ''); break; } } // Add login page link - if ((msgid != 11) && (msgid != 12)) { msg += ' ' + "Go to login page" + '.' } + if ((msgid != 11) && (msgid != 12) && (msgid != 13)) { msg += ' ' + "Go to login page" + '.' } QH('mainMessage', msg); function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); }; diff --git a/webserver.js b/webserver.js index e3138be6..a1a5d169 100644 --- a/webserver.js +++ b/webserver.js @@ -895,6 +895,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (userid) { var user = obj.users[userid]; + // Check if we are in maintenance mode + if ((parent.config.settings.maintenancemode != null) && (user.siteadmin != 4294967295)) { + req.session.messageid = 115; // Server under maintenance + req.session.loginmode = '1'; + if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); } + return; + } + var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (parent.mailserver != null) && (user.email != null) && (user.emailVerified == true) && (user.otpekey != null)); var sms2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.sms2factor != false)) && (parent.smsserver != null) && (user.phone != null)); @@ -1103,6 +1111,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCreateAccountRequest: failed checks.'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key + // Check if we are in maintenance mode + if (parent.config.settings.maintenancemode != null) { + req.session.messageid = 115; // Server under maintenance + req.session.loginmode = '1'; + if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); } + return; + } + // Always lowercase the email address if (req.body.email) { req.body.email = req.body.email.toLowerCase(); } @@ -1653,6 +1669,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (domain == null) { parent.debug('web', 'handleMSTSCRequest: failed checks.'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key + // Check if we are in maintenance mode + if ((parent.config.settings.maintenancemode != null) && (req.query.admin !== '1')) { + render(req, res, getRenderPage((domain.sitestyle == 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 3, msgid: 13, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); + return; + } + if (req.query.ws != null) { // This is a query with a websocket relay cookie, check that the cookie is valid and use it. var rcookie = parent.decodeCookie(req.query.ws, parent.loginCookieEncryptionKey, 60); // Cookie with 1 hour timeout @@ -2092,6 +2114,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (!obj.args) { parent.debug('web', 'handleRootRequest: no obj.args.'); res.sendStatus(500); return; } + // Check if we are in maintenance mode + if ((parent.config.settings.maintenancemode != null) && (req.query.admin !== '1')) { + parent.debug('web', 'handleLoginRequest: Server under maintenance.'); + render(req, res, getRenderPage((domain.sitestyle == 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 3, msgid: 13, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); + return; + } + if ((domain.sspi != null) && ((req.query.login == null) || (obj.parent.loginCookieEncryptionKey == null))) { // Login using SSPI domain.sspi.authenticate(req, res, function (err) { @@ -2463,6 +2492,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check if we are allowed to create new users using the login screen var newAccountsAllowed = true; if ((domain.newaccounts !== 1) && (domain.newaccounts !== true)) { for (var i in obj.users) { if (obj.users[i].domain == domain.id) { newAccountsAllowed = false; break; } } } + if (parent.config.settings.maintenancemode != null) { newAccountsAllowed = false; } // Encrypt the hardware key challenge state if needed var hwstate = null; @@ -2640,6 +2670,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (domain == null) { parent.debug('web', 'handleMessengerRequest: no domain'); res.sendStatus(404); return; } parent.debug('web', 'handleMessengerRequest()'); + // Check if we are in maintenance mode + if (parent.config.settings.maintenancemode != null) { + render(req, res, getRenderPage((domain.sitestyle == 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 3, msgid: 13, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); + return; + } + var webRtcConfig = null; if (obj.parent.config.settings && obj.parent.config.settings.webrtconfig && (typeof obj.parent.config.settings.webrtconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtconfig)).replace(/'/g, '%27'); } res.set({ 'Cache-Control': 'no-store' });