diff --git a/meshcentral.js b/meshcentral.js index 7911d4a7..b3d9468e 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -2256,7 +2256,7 @@ function mainStart() { var modules = ['ws', 'cbor', 'nedb', 'https', 'yauzl', 'xmldom', 'ipcheck', 'express', 'archiver', 'multiparty', 'node-forge', 'express-ws', 'compression', 'body-parser', 'connect-redis', 'cookie-session', 'express-handlebars']; if (require('os').platform() == 'win32') { modules.push('node-windows'); if (sspi == true) { modules.push('node-sspi'); } } // Add Windows modules if (ldap == true) { modules.push('ldapauth-fork'); } - if (config.letsencrypt != null) { if ((nodeVersion < 10) || (require('crypto').generateKeyPair == null)) { addServerWarning("Let's Encrypt support requires Node v10.12 or higher.", !args.launch); } else { modules.push('greenlock'); } } // Add Greenlock Module + if (config.letsencrypt != null) { if ((nodeVersion < 10) || (require('crypto').generateKeyPair == null)) { addServerWarning("Let's Encrypt support requires Node v10.12 or higher.", !args.launch); } else { modules.push('greenlock@3.1.5'); } } // Add Greenlock Module if (config.settings.mqtt != null) { modules.push('aedes'); } // Add MQTT Modules if (config.settings.mongodb != null) { modules.push('mongodb'); } // Add MongoDB, official driver. if (config.settings.vault != null) { modules.push('node-vault'); } // Add official HashiCorp's Vault module. diff --git a/meshuser.js b/meshuser.js index 7e4d34c0..76605a35 100644 --- a/meshuser.js +++ b/meshuser.js @@ -1452,8 +1452,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((common.validateInt(command.quota, 0) || command.quota == null) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; } // Site admins can change any server rights, user managers can only change AccountLock, NoMeshCmd and NoNewGroups - var chgusersiteadmin = chguser.siteadmin ? chguser.siteadmin : 0; - if (((user.siteadmin == 0xFFFFFFFF) || ((user.siteadmin & 2) && (((chgusersiteadmin ^ command.siteadmin) & 0xFFFFFF1F) == 0))) && common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; } + if (chguser._id !== user._id) { // We can't change our own siteadmin permissions. + var chgusersiteadmin = chguser.siteadmin ? chguser.siteadmin : 0; + if (((user.siteadmin == 0xFFFFFFFF) || ((user.siteadmin & 2) && (((chgusersiteadmin ^ command.siteadmin) & 0xFFFFFF1F) == 0))) && common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; } + } // Went sending a notification about a group change, we need to send to all the previous and new groups. var allTargetGroups = chguser.groups; diff --git a/package.json b/package.json index 23af4ee7..06bbf027 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.4.7-i", + "version": "0.4.7-j", "keywords": [ "Remote Management", "Intel AMT", diff --git a/translate/translate.json b/translate/translate.json index 1277e4ac..879a6592 100644 --- a/translate/translate.json +++ b/translate/translate.json @@ -3390,7 +3390,7 @@ "de": "Das Ändern der Sprache erfordert eine Aktualisierung der Seite.", "en": "Changing the language will require a refresh of the page.", "ja": "言語を変更するには、ページを更新する必要があります。", - "nl": "Als u de taal wilt wijzigen, moet de pagina worden vernieuwd.", + "nl": "Als u de taal wilt wijzigen, moet de pagina worden ververst.", "pt": "Alterar o idioma exigirá uma atualização da página.", "ru": "Изменение языка потребует обновления страницы.", "xloc": [ @@ -3778,7 +3778,7 @@ "de": "Bestätigen Sie das Kopieren von 1 Eintrag an diesen Ort?", "en": "Confirm copy of 1 entrie to this location?", "ja": "この場所への1つのエントリのコピーを確認しますか?", - "nl": "Bevestig kopie van 1 bestand naar deze locatie?", + "nl": "Bevestig kopiëren van 1 bestand naar deze locatie?", "pt": "Confirmar cópia de 1 entrada para este local?", "ru": "Подтвердить копию 1 записи в это место?", "xloc": [ @@ -3791,7 +3791,7 @@ "de": "Bestätigen Sie das Kopieren von {0} Einträgen an diesen Ort?", "en": "Confirm copy of {0} entries's to this location?", "ja": "{0}エントリのコピーをこの場所に確認しますか?", - "nl": "Bevestig kopieën van {0} bestanden naar deze locatie?", + "nl": "Bevestig kopiëren van {0} bestanden naar deze locatie?", "pt": "Confirmar cópia de {0} entradas para este local?", "ru": "Подтвердить копию {0} записей в этом месте?", "xloc": [ @@ -4130,7 +4130,7 @@ "de": "Kopie", "en": "Copy", "ja": "コピー", - "nl": "Kopie", + "nl": "Kopiëren", "pt": "Copiar", "ru": "Копировать", "xloc": [ @@ -4743,7 +4743,7 @@ { "de": "Benutzergruppe löschen", "en": "Delete User Group", - "nl": "Verdwijder de gebruikersgroep", + "nl": "Verwijder de gebruikersgroep", "xloc": [ "default.handlebars->23->1277", "default.handlebars->23->1285" @@ -5788,7 +5788,7 @@ { "de": "Dupliziere Benutzergruppe", "en": "Duplicate User Group", - "nl": "Duplicer Gebruikers Groep", + "nl": "Dupliceer Gebruikers Groep", "xloc": [ "default.handlebars->23->1253" ] @@ -13127,7 +13127,8 @@ ] }, { - "en": "Relay teller" + "en": "Relay teller", + "nl": "Relay teller" }, { "cs": "Zapamatovat toto zařízení na 30 dní.", @@ -13541,7 +13542,7 @@ "en": "Reset devices", "fr": "Réinitialiser les appareils", "ja": "デバイスをリセットする", - "nl": "Reset apparaten", + "nl": "Herstart apparaten", "pt": "Redefinir dispositivos", "ru": "Сбросить устройства", "xloc": [ @@ -16011,7 +16012,7 @@ "de": "Diese Seite existiert nicht.", "en": "This page does not exist", "ja": "このページは存在しません", - "nl": "", + "nl": "Deze pagina bestaat niet", "pt": "Esta página não existe", "ru": "Страница не существует", "xloc": [ @@ -16191,7 +16192,7 @@ "de": "Um dieses Konto zu löschen, geben Sie das Konto-Passwort in beide untenstehenden Eingabefelder ein und wählen Sie OK.", "en": "To delete this account, type in the account password in both boxes below and hit ok.", "ja": "このアカウントを削除するには、下の両方のボックスにアカウントのパスワードを入力して[OK]をクリックします。", - "nl": "Om dit account te verwijderen, typt u het accountwachtwoord in beide onderstaande vakken en drukt u op OK.", + "nl": "Om dit account te verwijderen, typt u het accountwachtwoord in beide onderstaande vakken en klikt u op OK.", "pt": "Para excluir esta conta, digite a senha da conta nas duas caixas abaixo e pressione ok.", "ru": "Чтобы удалить эту учетную запись, введите пароль учетной записи в оба поля и нажмите ОК.", "xloc": [ @@ -16215,7 +16216,7 @@ "de": "Zum Installieren, kopieren Sie den folgenden Befehl und führen Sie ihn in einem Root-Terminal aus.", "en": "To install, cut and paste the following command in a root terminal.", "ja": "インストールするには、ルートターミナルで次のコマンドをカットアンドペーストします。", - "nl": "Om de volgende opdracht te installeren, knippen en plakken in een root-terminal.", + "nl": "Om te installeren, knip en plak de volgende opdracht in de root-terminal.", "pt": "Para instalar, recorte e cole o seguinte comando em um terminal raiz.", "ru": "Для установки, вырежьте и вставьте следующую команду в root терминал.", "xloc": [ @@ -16239,7 +16240,7 @@ "de": "Um einen Mesh-Agenten zu entfernen, führen Sie den folgenden Befehl aus. Root-Zugriff wird benötigt.", "en": "To remove a mesh agent, run the following command. Root credentials will be needed.", "ja": "メッシュエージェントを削除するには、次のコマンドを実行します。ルート資格情報が必要になります。", - "nl": "Voer de volgende opdracht uit om een mesh-agent te verwijderen. Root gegevens zijn nodig.", + "nl": "Voer de volgende opdracht uit om een mesh-agent te verwijderen. Root rechten zijn nodig.", "pt": "Para remover um agente de malha, execute o seguinte comando. Serão necessárias credenciais raiz.", "ru": "Для удаления mesh агента, выполните следующую команду. Root учетные данные будут необходимы.", "xloc": [ @@ -18333,7 +18334,7 @@ "de": "kopieren", "en": "copy", "ja": "コピー", - "nl": "kopieren", + "nl": "kopiëren", "pt": "Copiar", "ru": "копировать", "xloc": [ diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index a5b95d05..d5311afa 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -822,7 +822,7 @@ var secret = message.secret; if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); } else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '
' + secret.substring(20) } - QH('d2optinfo', format("Install Google Authenticator or a compatible application, use this link or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login.", message.url) + '

' + secret + '

Token: = 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text>
'); + QH('d2optinfo', format("Install Google Authenticator or a compatible application, use this link or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login.", message.url) + '

' + secret + '

Token: = 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text>
'); QV('idx_dlgOkButton', true); QE('idx_dlgOkButton', false); Q('d2otpauthinput').focus(); diff --git a/views/default.handlebars b/views/default.handlebars index 262ccb5e..b2819fd9 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -2032,7 +2032,7 @@ var secret = message.secret; if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); } else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '
' + secret.substring(20) } - QH('d2optinfo', '
' + format("Install Google Authenticator or a compatible application and scan the barcode, use this link or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.", message.url) + '

Secret
' + secret + '


' + "Enter the token here for 2-step login:" + ' = 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text>
'); + QH('d2optinfo', '
' + format("Install Google Authenticator or a compatible application and scan the barcode, use this link or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.", message.url) + '

Secret
' + secret + '


' + "Enter the token here for 2-step login:" + ' = 48 && event.charCode <= 57)\" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text>
'); new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H }); QV('idx_dlgOkButton', true); QE('idx_dlgOkButton', false); @@ -9036,6 +9036,9 @@ if (xxdialogMode) return; haltEvent(e); userid = decodeURIComponent(userid); + var user = users[userid.toLowerCase()]; + if (user == null) return; + var uself = (userinfo._id == user._id); var x = '
'; x += ', k max, blank for default

'; x += '
'; @@ -9048,8 +9051,7 @@ x += '
'; x += '
'; x += '
'; - var user = users[userid.toLowerCase()]; - setDialogMode(2, "Server Permissions", 3, showUserAdminDialogEx, x, user); + setDialogMode(2, "Server Permissions", 2 + (uself?0:1), showUserAdminDialogEx, x, user); if (user.siteadmin && user.siteadmin != 0) { Q('ua_fulladmin').checked = (user.siteadmin == 0xFFFFFFFF); Q('ua_serverbackup').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1) != 0)); // Server Backup @@ -9062,18 +9064,18 @@ Q('ua_nomeshcmd').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 128) != 0)); // No Tools (MeshCMD / Router) Q('ua_manageusergroups').checked = ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 256) != 0)); // Manage User Groups } - QE('ua_fulladmin', userinfo.siteadmin == 0xFFFFFFFF); - QE('ua_serverbackup', userinfo.siteadmin == 0xFFFFFFFF); - QE('ua_manageusers', userinfo.siteadmin == 0xFFFFFFFF); - QE('ua_manageusergroups', userinfo.siteadmin == 0xFFFFFFFF); - QE('ua_serverrestore', userinfo.siteadmin == 0xFFFFFFFF); - QE('ua_fileaccess', userinfo.siteadmin == 0xFFFFFFFF); - QE('ua_fileaccessquota', userinfo.siteadmin == 0xFFFFFFFF); - QE('ua_serverupdate', userinfo.siteadmin == 0xFFFFFFFF); + QE('ua_fulladmin', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); + QE('ua_serverbackup', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); + QE('ua_manageusers', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); + QE('ua_manageusergroups', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); + QE('ua_serverrestore', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); + QE('ua_fileaccess', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); + QE('ua_fileaccessquota', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); + QE('ua_serverupdate', !uself && (userinfo.siteadmin == 0xFFFFFFFF)); QV('d2AdminPermissions', userinfo.siteadmin == 0xFFFFFFFF) - QE('ua_lockedaccount', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id)); - QE('ua_nonewgroups', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id)); - QE('ua_nomeshcmd', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id)); + QE('ua_lockedaccount', !uself && (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id)); + QE('ua_nonewgroups', !uself && (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id)); + QE('ua_nomeshcmd', !uself && (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id)); Q('ua_fileaccessquota').value = (user.quota != null)?(user.quota / 1024):''; showUserAdminDialogValidate(); return false; @@ -9961,12 +9963,12 @@ window.serverStatCpu = new Chart(document.getElementById('serverCpuChart').getContext('2d'), { type: 'doughnut', data: { datasets: [{ data: [0, 0], backgroundColor: ['#AAAAAA', '#00AA00'] }], labels: ["Used", "Free"] }, - options: { responsive: true, legend: { position: 'none', }, animation: { animateScale: true, animateRotate: true }, width: '60px' } + options: { events: [], responsive: true, legend: { position: 'none', }, animation: { animateScale: true, animateRotate: true }, width: '60px' } }); window.serverStatMemory = new Chart(document.getElementById('serverMemoryChart').getContext('2d'), { type: 'doughnut', data: { datasets: [{ data: [0, 0], backgroundColor: ['#AAAAAA', '#00AA00'] }], labels: ["Used", "Free"] }, - options: { responsive: true, legend: { position: 'none', }, animation: { animateScale: true, animateRotate: true }, width: '60px' } + options: { events: [], responsive: true, legend: { position: 'none', }, animation: { animateScale: true, animateRotate: true }, width: '60px' } }); } diff --git a/views/login-mobile.handlebars b/views/login-mobile.handlebars index 4a2f5f59..6054d64d 100644 --- a/views/login-mobile.handlebars +++ b/views/login-mobile.handlebars @@ -53,11 +53,11 @@ - + - + @@ -86,19 +86,19 @@
Username:
Password:
- + - + - + - + @@ -130,7 +130,7 @@
Username:
Email:
Password:
Password:
- + @@ -172,7 +172,6 @@ - -
Email:
@@ -152,7 +152,7 @@
Login token: - +
- + - + @@ -83,19 +83,19 @@
Username:
Password:
- + - + - + - + @@ -126,7 +126,7 @@
Username:
Email:
Password:
Password:
- + diff --git a/webserver.js b/webserver.js index ae303acf..1736c21e 100644 --- a/webserver.js +++ b/webserver.js @@ -1546,7 +1546,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((obj.parent.mailserver != null) && (obj.parent.certificates.CommonName != null) && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.lanonly != true)) { features += 0x00000040; } // Email invites if (obj.args.webrtc == true) { features += 0x00000080; } // Enable WebRTC (Default false for now) if (obj.args.clickonce !== false) { features += 0x00000100; } // Enable ClickOnce (Default true) - if (obj.args.allowhighqualitydesktop == true) { features += 0x00000200; } // Enable AllowHighQualityDesktop (Default false) + if (obj.args.allowhighqualitydesktop !== false) { features += 0x00000200; } // Enable AllowHighQualityDesktop (Default true) if (obj.args.lanonly == true || obj.args.mpsport == 0) { features += 0x00000400; } // No CIRA if ((obj.parent.serverSelfWriteAllowed == true) && (user != null) && (user.siteadmin == 0xFFFFFFFF)) { features += 0x00000800; } // Server can self-write (Allows self-update) if ((parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.nousers !== true)) { features += 0x00001000; } // 2-step login supported @@ -3410,7 +3410,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { 'Referrer-Policy': 'no-referrer', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', - 'Content-Security-Policy': "default-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self'" + geourl + selfurl + "; img-src 'self'" + geourl + " data:; style-src 'self' 'unsafe-inline'; frame-src 'self'; media-src 'self'; base-url: 'none'; form-action 'self'" + 'Content-Security-Policy': "default-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self'" + geourl + selfurl + "; img-src 'self'" + geourl + " data:; style-src 'self' 'unsafe-inline'; frame-src 'self'; media-src 'self'; form-action 'self'" }; if ((parent.config.settings.allowframing !== true) && (typeof parent.config.settings.allowframing !== 'string')) { headers['X-Frame-Options'] = 'sameorigin'; } res.set(headers);
Email:
@@ -148,7 +148,7 @@
Login token: -
+