More work on cross-domain administrator

Ylian Saint-Hilaire committed May 27, 2020 at 15:31 UTC 32a9991afb6a62610a66daaa625c4c0dfba4ab6e
3 files changed +447 -361
meshuser.js
+86 -52
@@ -396,19 +396,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
396 if (args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = args.redirport; }
397 if (typeof domain.userconsentflags == 'number') { serverinfo.consent = domain.userconsentflags; }
398 if ((typeof domain.usersessionidletimeout == 'number') && (domain.usersessionidletimeout > 0)) { serverinfo.timeout = (domain.usersessionidletimeout * 60 * 1000); }
399 + if (user.siteadmin == 0xFFFFFFFF) {
400 + if (parent.parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) { serverinfo.manageAllDeviceGroups = true; }
401 + if (obj.crossDomain === true) { serverinfo.crossDomain = []; for (var i in parent.parent.config.domains) { serverinfo.crossDomain.push(i); } }
402 + }
403
404 // Send server information
405 try { ws.send(JSON.stringify({ action: 'serverinfo', serverinfo: serverinfo })); } catch (ex) { }
406
407 // Send user information to web socket, this is the first thing we send
404 - try {
405 - var xuserinfo = parent.CloneSafeUser(parent.users[user._id]);
406 - if (user.siteadmin == 0xFFFFFFFF) {
407 - if (parent.parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) { xuserinfo.manageAllDeviceGroups = true; }
408 - if (obj.crossDomain === true) { xuserinfo.crossDomain = []; for (var i in parent.parent.config.domains) { xuserinfo.crossDomain.push(i); } }
409 - }
410 - ws.send(JSON.stringify({ action: 'userinfo', userinfo: xuserinfo }));
411 - } catch (ex) { }
408 + try { ws.send(JSON.stringify({ action: 'userinfo', userinfo: parent.CloneSafeUser(parent.users[user._id]) })); } catch (ex) { }
409
410 if (user.siteadmin == 0xFFFFFFFF) {
411 // Send server tracing information
@@ -1832,7 +1829,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1829 }
1830 case 'usergroups':
1831 {
1835 - // TODO: Return only groups in the same administrative domain?
1832 + // Return only groups in the same administrative domain
1833 if ((user.siteadmin & SITERIGHT_USERGROUPS) == 0) {
1834 // We are not user group administrator, return a list with limited data for our domain.
1835 var groups = {}, groupCount = 0;
@@ -1841,35 +1838,44 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1838 } else {
1839 // We are user group administrator, return a full user group list for our domain.
1840 var groups = {}, groupCount = 0;
1844 - for (var i in parent.userGroups) { if (parent.userGroups[i].domain == domain.id) { groupCount++; groups[i] = parent.userGroups[i]; } }
1841 + for (var i in parent.userGroups) { if ((obj.crossDomain == true) || (parent.userGroups[i].domain == domain.id)) { groupCount++; groups[i] = parent.userGroups[i]; } }
1842 try { ws.send(JSON.stringify({ action: 'usergroups', ugroups: groupCount ? groups : null, tag: command.tag })); } catch (ex) { }
1843 }
1844 break;
1845 }
1846 case 'createusergroup':
1847 {
1851 - var err = null;
1848 + var ugrpdomain, err = null;
1849 try {
1850 // Check if we have new group restriction
1854 - if ((user.siteadmin & SITERIGHT_USERGROUPS) == 0) { err = 'Permission denied'; }
1851 + if ((user.siteadmin & SITERIGHT_USERGROUPS) == 0) { err = "Permission denied"; }
1852
1856 - // In some situations, we need a verified email address to create a device group.
1857 - else if ((parent.parent.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap') && (user.emailVerified !== true) && (user.siteadmin != 0xFFFFFFFF)) { err = 'Email verification required'; } // User must verify it's email first.
1858 -
1859 - // Create user group
1860 - else if (common.validateString(command.name, 1, 64) == false) { err = 'Invalid group name'; } // User group name is between 1 and 64 characters
1861 - else if ((command.desc != null) && (common.validateString(command.desc, 0, 1024) == false)) { err = 'Invalid group description'; } // User group description is between 0 and 1024 characters
1853 + // Create user group validation
1854 + else if (common.validateString(command.name, 1, 64) == false) { err = "Invalid group name"; } // User group name is between 1 and 64 characters
1855 + else if ((command.desc != null) && (common.validateString(command.desc, 0, 1024) == false)) { err = "Invalid group description"; } // User group description is between 0 and 1024 characters
1856
1857 // If we are cloning from an existing user group, check that.
1858 if (command.clone) {
1865 - if (common.validateString(command.clone, 1, 256) == false) { err = 'Invalid clone groupid'; }
1859 + if (common.validateString(command.clone, 1, 256) == false) { err = "Invalid clone groupid"; }
1860 else {
1861 var clonesplit = command.clone.split('/');
1868 - if ((clonesplit.length != 3) || (clonesplit[0] != 'ugrp') || (clonesplit[1] != domain.id)) { err = 'Invalid clone groupid'; }
1869 - else if (parent.userGroups[command.clone] == null) { err = 'Invalid clone groupid'; }
1862 + if ((clonesplit.length != 3) || (clonesplit[0] != 'ugrp') || ((command.domain == null) && (clonesplit[1] != domain.id))) { err = "Invalid clone groupid"; }
1863 + else if (parent.userGroups[command.clone] == null) { err = "Invalid clone groupid"; }
1864 }
1865 +
1866 + // Get new user group domain
1867 + ugrpdomain = parent.parent.config.domains[clonesplit[1]];
1868 + if (ugrpdomain == null) { err = "Invalid domain"; }
1869 + } else {
1870 + // Get new user group domain
1871 + ugrpdomain = domain;
1872 + if ((obj.crossDomain === true) && (command.domain != null)) { ugrpdomain = parent.parent.config.domains[command.domain]; }
1873 + if (ugrpdomain == null) { err = "Invalid domain"; }
1874 }
1872 - } catch (ex) { err = 'Validation exception: ' + ex; }
1875 +
1876 + // In some situations, we need a verified email address to create a device group.
1877 + if ((err == null) && (parent.parent.mailserver != null) && (ugrpdomain.auth != 'sspi') && (ugrpdomain.auth != 'ldap') && (user.emailVerified !== true) && (user.siteadmin != 0xFFFFFFFF)) { err = "Email verification required"; } // User must verify it's email first.
1878 + } catch (ex) { err = "Validation exception: " + ex; }
1879
1880 // Handle any errors
1881 if (err != null) {
@@ -1880,10 +1886,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1886 // We only create Agent-less Intel AMT mesh (Type1), or Agent mesh (Type2)
1887 parent.crypto.randomBytes(48, function (err, buf) {
1888 // Create new device group identifier
1883 - var ugrpid = 'ugrp/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
1889 + var ugrpid = 'ugrp/' + ugrpdomain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
1890
1891 // Create the new device group
1886 - var ugrp = { type: 'ugrp', _id: ugrpid, name: command.name, desc: command.desc, domain: domain.id, links: {} };
1892 + var ugrp = { type: 'ugrp', _id: ugrpid, name: command.name, desc: command.desc, domain: ugrpdomain.id, links: {} };
1893
1894 // Clone the existing group if required
1895 var pendingDispatchEvents = [];
@@ -1901,7 +1907,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1907
1908 // Notify user change
1909 var targets = ['*', 'server-users', user._id, xuser._id];
1904 - var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(xuser), action: 'accountchange', msg: 'User group membership changed: ' + xuser.name, domain: domain.id };
1910 + var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(xuser), action: 'accountchange', msg: 'User group membership changed: ' + xuser.name, domain: ugrpdomain.id };
1911 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
1912 //parent.parent.DispatchEvent(targets, obj, event);
1913 pendingDispatchEvents.push([targets, obj, event]);
@@ -1914,7 +1920,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1920 db.Set(xmesh);
1921
1922 // Notify mesh change
1917 - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Added group ' + ugrp.name + ' to mesh ' + xmesh.name, domain: domain.id, invite: mesh.invite };
1923 + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Added group ' + ugrp.name + ' to mesh ' + xmesh.name, domain: ugrpdomain.id, invite: mesh.invite };
1924 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
1925 //parent.parent.DispatchEvent(['*', xmesh._id, user._id], obj, event);
1926 pendingDispatchEvents.push([parent.CreateMeshDispatchTargets(xmesh, [user._id]), obj, event]);
@@ -1929,7 +1935,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1935 if (db.changeStream == false) { parent.userGroups[ugrpid] = ugrp; }
1936
1937 // Event the device group creation
1932 - var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: ugrpid, name: ugrp.name, desc: ugrp.desc, action: 'createusergroup', links: ugrp.links, msg: 'User group created: ' + ugrp.name, domain: domain.id };
1938 + var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: ugrpid, name: ugrp.name, desc: ugrp.desc, action: 'createusergroup', links: ugrp.links, msg: 'User group created: ' + ugrp.name, ugrpdomain: domain.id };
1939 parent.parent.DispatchEvent(['*', ugrpid, user._id], obj, event); // Even if DB change stream is active, this event must be acted upon.
1940
1941 // Event any pending events, these must be sent out after the group creation event is displatched.
@@ -1949,7 +1955,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1955 // Change the name or description of a user group
1956 if (common.validateString(command.ugrpid, 1, 1024) == false) break; // Check the user group id
1957 var ugroupidsplit = command.ugrpid.split('/');
1952 - if ((ugroupidsplit.length != 3) || (ugroupidsplit[0] != 'ugrp') || (ugroupidsplit[1] != domain.id)) break;
1958 + if ((ugroupidsplit.length != 3) || (ugroupidsplit[0] != 'ugrp') || ((obj.crossDomain !== true) && (ugroupidsplit[1] != domain.id))) break;
1959 +
1960 + // Get the domain
1961 + var delGroupDomain = parent.parent.config.domains[ugroupidsplit[1]];
1962 + if (delGroupDomain == null) break;
1963
1964 db.Get(command.ugrpid, function (err, groups) {
1965 if ((err != null) || (groups.length != 1)) return;
@@ -1967,7 +1977,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1977
1978 // Notify user change
1979 var targets = ['*', 'server-users', user._id, xuser._id];
1970 - var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(xuser), action: 'accountchange', msg: 'User group membership changed: ' + xuser.name, domain: domain.id };
1980 + var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(xuser), action: 'accountchange', msg: 'User group membership changed: ' + xuser.name, delGroupDomain: domain.id };
1981 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
1982 parent.parent.DispatchEvent(targets, obj, event);
1983 }
@@ -1978,7 +1988,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1988 db.Set(xmesh);
1989
1990 // Notify mesh change
1981 - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Removed group ' + group.name + ' from mesh ' + xmesh.name, domain: domain.id, invite: mesh.invite };
1991 + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Removed group ' + group.name + ' from mesh ' + xmesh.name, domain: delGroupDomain.id, invite: mesh.invite };
1992 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
1993 parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(xmesh, [user._id]), obj, event);
1994 }
@@ -1991,7 +2001,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2001 if (db.changeStream == false) { delete parent.userGroups[group._id]; }
2002
2003 // Event the user group being removed
1994 - var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, action: 'deleteusergroup', msg: change, domain: domain.id };
2004 + var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, action: 'deleteusergroup', msg: change, domain: delGroupDomain.id };
2005 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
2006 parent.parent.DispatchEvent(['*', group._id, user._id], obj, event);
2007
@@ -2032,10 +2042,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2042 else if (common.validateStrArray(command.usernames, 1, 64) == false) { err = 'Invalid usernames'; } // Username is between 1 and 64 characters
2043 else {
2044 var ugroupidsplit = command.ugrpid.split('/');
2035 - if ((ugroupidsplit.length != 3) || (ugroupidsplit[0] != 'ugrp') || (ugroupidsplit[1] != domain.id)) { err = 'Invalid groupid'; }
2045 + if ((ugroupidsplit.length != 3) || (ugroupidsplit[0] != 'ugrp') || ((obj.crossDomain !== true) && (ugroupidsplit[1] != domain.id))) { err = 'Invalid groupid'; }
2046 }
2047 } catch (ex) { err = 'Validation exception: ' + ex; }
2048
2049 + // Fetch the domain
2050 + var addUserDomain = domain;
2051 + if (obj.crossDomain === true) { addUserDomain = parent.parent.config.domains[ugroupidsplit[1]]; }
2052 + if (addUserDomain == null) { err = 'Invalid domain'; }
2053 +
2054 // Handle any errors
2055 if (err != null) {
2056 if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addusertousergroup', responseid: command.responseid, result: err })); } catch (ex) { } }
@@ -2050,7 +2065,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2065 var unknownUsers = [], addedCount = 0, failCount = 0;
2066 for (var i in command.usernames) {
2067 // Check if the user exists
2053 - var chguserid = 'user/' + domain.id + '/' + command.usernames[i].toLowerCase(), chguser = parent.users[chguserid];
2068 + var chguserid = 'user/' + addUserDomain.id + '/' + command.usernames[i].toLowerCase(), chguser = parent.users[chguserid];
2069 if (chguser != null) {
2070 // Add mesh to user
2071 if (chguser.links == null) { chguser.links = {}; }
@@ -2060,7 +2075,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2075
2076 // Notify user change
2077 var targets = ['*', 'server-users', user._id, chguser._id];
2063 - var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'User group membership changed: ' + chguser.name, domain: domain.id };
2078 + var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'User group membership changed: ' + chguser.name, domain: addUserDomain.id };
2079 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
2080 parent.parent.DispatchEvent(targets, obj, event);
2081
@@ -2078,7 +2093,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2093 db.Set(group);
2094
2095 // Notify user group change
2081 - var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, name: group.name, desc: group.desc, action: 'usergroupchange', links: group.links, msg: 'Added user ' + chguser.name + ' to user group ' + group.name, domain: domain.id };
2096 + var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, name: group.name, desc: group.desc, action: 'usergroupchange', links: group.links, msg: 'Added user ' + chguser.name + ' to user group ' + group.name, addUserDomain: domain.id };
2097 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
2098 parent.parent.DispatchEvent(['*', group._id, user._id, chguserid], obj, event);
2099 }
@@ -2102,10 +2117,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2117 else if (common.validateString(command.userid, 1, 256) == false) { err = 'Invalid userid'; }
2118 else {
2119 var ugroupidsplit = command.ugrpid.split('/');
2105 - if ((ugroupidsplit.length != 3) || (ugroupidsplit[0] != 'ugrp') || (ugroupidsplit[1] != domain.id)) { err = 'Invalid groupid'; }
2120 + if ((ugroupidsplit.length != 3) || (ugroupidsplit[0] != 'ugrp') || ((obj.crossDomain !== true) && (ugroupidsplit[1] != domain.id))) { err = 'Invalid groupid'; }
2121 }
2122 } catch (ex) { err = 'Validation exception: ' + ex; }
2123
2124 + // Fetch the domain
2125 + var removeUserDomain = domain;
2126 + if (obj.crossDomain !== true) { removeUserDomain = parent.parent.config.domains[ugroupidsplit[1]]; }
2127 + if (removeUserDomain == null) { err = 'Invalid domain'; }
2128 +
2129 // Handle any errors
2130 if (err != null) {
2131 if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'removeuserfromusergroup', responseid: command.responseid, result: err })); } catch (ex) { } }
@@ -2122,7 +2142,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2142
2143 // Notify user change
2144 var targets = ['*', 'server-users', user._id, chguser._id];
2125 - var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'User group membership changed: ' + chguser.name, domain: domain.id };
2145 + var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'User group membership changed: ' + chguser.name, domain: removeUserDomain.id };
2146 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
2147 parent.parent.DispatchEvent(targets, obj, event);
2148
@@ -2141,7 +2161,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2161
2162 // Notify user group change
2163 if (change) {
2144 - var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, name: group.name, desc: group.desc, action: 'usergroupchange', links: group.links, msg: 'Removed user ' + chguser.name + ' from user group ' + group.name, domain: domain.id };
2164 + var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, name: group.name, desc: group.desc, action: 'usergroupchange', links: group.links, msg: 'Removed user ' + chguser.name + ' from user group ' + group.name, domain: removeUserDomain.id };
2165 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user group. Another event will come.
2166 parent.parent.DispatchEvent(['*', group._id, user._id, chguser._id], obj, event);
2167 }
@@ -2593,7 +2613,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2613 }
2614 case 'addmeshuser':
2615 {
2596 - var err = null;
2616 + var err = null, mesh, meshIdSplit;
2617 if (typeof command.userid == 'string') { command.userids = [command.userid]; }
2618
2619 // Resolve the device group name if needed
@@ -2614,9 +2634,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2634 else {
2635 if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
2636 mesh = parent.meshes[command.meshid];
2637 + meshIdSplit = command.meshid.split('/');
2638 if (mesh == null) { err = 'Unknown group'; }
2639 else if (((selfMeshRights = parent.GetMeshRights(user, mesh)) & MESHRIGHT_MANAGEUSERS) == 0) { err = 'Permission denied'; }
2619 - else if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
2640 + else if ((meshIdSplit.length != 3) || (meshIdSplit[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
2641 }
2642 } catch (ex) { err = 'Validation exception: ' + ex; }
2643
@@ -2644,6 +2665,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2665 for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { newuser = parent.users[i]; command.userids[i] = newuserid = parent.users[i]._id; break; } }
2666 }
2667
2668 + // Make sure this user is in the same domain as the device group
2669 + if (meshIdSplit[1] != newuserid.split('/')[1]) { msgs.push("Mismatch domains"); continue; }
2670 +
2671 if (newuser != null) {
2672 // Can't add or modify self
2673 if (newuserid == obj.user._id) { msgs.push("Can't change self"); continue; }
@@ -2719,7 +2743,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2743 }
2744 case 'adddeviceuser': {
2745 if (typeof command.userid == 'string') { command.userids = [command.userid]; }
2722 - var err = null;
2746 + var err = null, nodeIdSplit;
2747 try {
2748 if (common.validateString(command.nodeid, 1, 1024) == false) { err = 'Invalid nodeid'; } // Check the nodeid
2749 else if (common.validateInt(command.rights) == false) { err = 'Invalid rights'; } // Device rights must be an integer
@@ -2772,6 +2796,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2796 }
2797 }
2798
2799 + // Check the the user and device are in the same domain
2800 + if (command.nodeid.split('/')[1] != newuserid.split('/')[1]) return; // Domain mismatch
2801 +
2802 if (newuser != null) {
2803 // Add this user to the dispatch target list
2804 dispatchTargets.push(newuser._id);
@@ -2840,7 +2867,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2867 }
2868 case 'removemeshuser':
2869 {
2843 - var err = null;
2870 + var xdomain, err = null;
2871
2872 // Resolve the device group name if needed
2873 if ((typeof command.meshname == 'string') && (command.meshid == null)) {
@@ -2857,19 +2884,26 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2884 if (common.validateString(command.meshid, 1, 1024) == false) { err = "Invalid groupid"; } // Check meshid
2885 if (command.userid.indexOf('/') == -1) { command.userid = 'user/' + domain.id + '/' + command.userid; }
2886 if (command.userid == obj.user._id) { err = "Can't remove self"; } // Can't add of modify self
2860 - if ((command.userid.split('/').length != 3) || (command.userid.split('/')[1] != domain.id)) { err = "Invalid userid"; } // Invalid domain, operation only valid for current domain
2887 + if ((command.userid.split('/').length != 3) || ((obj.crossDomain !== true) && (command.userid.split('/')[1] != domain.id))) { err = "Invalid userid"; } // Invalid domain, operation only valid for current domain
2888 else {
2889 if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
2890 mesh = parent.meshes[command.meshid];
2891 + var meshIdSplit = command.meshid.split('/');
2892 if (mesh == null) { err = "Unknown device group"; }
2893 else if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGEUSERS) == 0) { err = "Permission denied"; }
2866 - else if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) { err = "Invalid domain"; } // Invalid domain, operation only valid for current domain
2894 + else if (meshIdSplit.length != 3) { err = "Invalid domain"; } // Invalid domain, operation only valid for current domain
2895 + else {
2896 + xdomain = domain;
2897 + if (obj.crossDomain !== true) { xdomain = parent.parent.config.domains[meshIdSplit[1]]; }
2898 + if (xdomain == null) { err = "Invalid domain"; }
2899 + }
2900 }
2901 } catch (ex) { err = "Validation exception: " + ex; }
2902
2903 // Handle any errors
2904 if (err != null) {
2872 - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: err })); } catch (ex) { } }
2905 + console.log(err);
2906 + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'removemeshuser', responseid: command.responseid, result: err })); } catch (ex) { } }
2907 break;
2908 }
2909
@@ -2879,9 +2913,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2913 else if (deluserid.startsWith('ugrp/')) { deluser = parent.userGroups[deluserid]; }
2914
2915 // Search for a user name in that windows domain is the username starts with *\
2882 - if ((deluser == null) && (deluserid.startsWith('user/' + domain.id + '/*\\')) == true) {
2916 + if ((deluser == null) && (deluserid.startsWith('user/' + xdomain.id + '/*\\')) == true) {
2917 var search = deluserid.split('/')[2].substring(1);
2884 - for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { deluser = parent.users[i]; command.userid = deluserid = deluser._id; break; } }
2918 + for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == xdomain.id)) { deluser = parent.users[i]; command.userid = deluserid = deluser._id; break; } }
2919 }
2920
2921 if (deluser != null) {
@@ -2897,13 +2931,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2931 if (deluserid.startsWith('user/')) {
2932 // Notify user change
2933 var targets = ['*', 'server-users', user._id, deluser._id];
2900 - var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(deluser), action: 'accountchange', msg: 'Device group membership changed: ' + deluser.name, domain: domain.id };
2934 + var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(deluser), action: 'accountchange', msg: 'Device group membership changed: ' + deluser.name, domain: xdomain.id };
2935 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
2936 parent.parent.DispatchEvent(targets, obj, event);
2937 } else if (deluserid.startsWith('ugrp/')) {
2938 // Notify user group change
2939 var targets = ['*', 'server-ugroups', user._id, deluser._id];
2906 - var event = { etype: 'ugrp', username: user.name, ugrpid: deluser._id, name: deluser.name, desc: deluser.desc, action: 'usergroupchange', links: deluser.links, msg: 'User group changed: ' + deluser.name, domain: domain.id };
2940 + var event = { etype: 'ugrp', username: user.name, ugrpid: deluser._id, name: deluser.name, desc: deluser.desc, action: 'usergroupchange', links: deluser.links, msg: 'User group changed: ' + deluser.name, domain: xdomain.id };
2941 if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
2942 parent.parent.DispatchEvent(targets, obj, event);
2943 }
@@ -2918,9 +2952,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2952 // Notify mesh change
2953 var event;
2954 if (deluser != null) {
2921 - event = { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + deluser.name + ' from group ' + mesh.name, domain: domain.id, invite: mesh.invite };
2955 + event = { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + deluser.name + ' from group ' + mesh.name, domain: xdomain.id, invite: mesh.invite };
2956 } else {
2923 - event = { etype: 'mesh', username: user.name, userid: (deluserid.split('/')[2]), meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + (deluserid.split('/')[2]) + ' from group ' + mesh.name, domain: domain.id, invite: mesh.invite };
2957 + event = { etype: 'mesh', username: user.name, userid: (deluserid.split('/')[2]), meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + (deluserid.split('/')[2]) + ' from group ' + mesh.name, domain: xdomain.id, invite: mesh.invite };
2958 }
2959 parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id, command.userid]), obj, event);
2960 if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'removemeshuser', responseid: command.responseid, result: 'ok' })); } catch (ex) { } }
@@ -3054,7 +3088,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3088
3089 // Handle any errors
3090 if (err != null) {
3057 - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: err })); } catch (ex) { } }
3091 + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'changeDeviceMesh', responseid: command.responseid, result: err })); } catch (ex) { } }
3092 break;
3093 }
3094
translate/translate.json
+285 -277
@@ -192,7 +192,7 @@
192 "zh-chs": " 用戶需要先登錄到該服務器一次,然後才能將其添加到設備組。",
193 "xloc": [
194 "default.handlebars->25->1258",
195 - "default.handlebars->25->1566"
195 + "default.handlebars->25->1569"
196 ]
197 },
198 {
@@ -619,7 +619,7 @@
619 "default-mobile.handlebars->9->108",
620 "default-mobile.handlebars->9->284",
621 "default.handlebars->25->1365",
622 - "default.handlebars->25->1712",
622 + "default.handlebars->25->1715",
623 "default.handlebars->25->750"
624 ]
625 },
@@ -669,7 +669,7 @@
669 "ru": "1 активная сессия",
670 "zh-chs": "1個活動會話",
671 "xloc": [
672 - "default.handlebars->25->1630"
672 + "default.handlebars->25->1633"
673 ]
674 },
675 {
@@ -731,7 +731,7 @@
731 "ru": "1 группа",
732 "zh-chs": "1組",
733 "xloc": [
734 - "default.handlebars->25->1595"
734 + "default.handlebars->25->1598"
735 ]
736 },
737 {
@@ -1131,7 +1131,7 @@
1131 "zh-chs": "啟用第二因素身份驗證",
1132 "xloc": [
1133 "default.handlebars->25->1436",
1134 - "default.handlebars->25->1617"
1134 + "default.handlebars->25->1620"
1135 ]
1136 },
1137 {
@@ -1878,7 +1878,7 @@
1878 "ru": "Доступ к файлам сервера",
1879 "zh-chs": "訪問服務器文件",
1880 "xloc": [
1881 - "default.handlebars->25->1572"
1881 + "default.handlebars->25->1575"
1882 ]
1883 },
1884 {
@@ -2003,7 +2003,7 @@
2003 "zh-chs": "帐户已被锁定",
2004 "xloc": [
2005 "default.handlebars->25->1438",
2006 - "default.handlebars->25->1569"
2006 + "default.handlebars->25->1572"
2007 ]
2008 },
2009 {
@@ -2278,8 +2278,8 @@
2278 "ru": "Добавить устройство",
2279 "zh-chs": "添加設備",
2280 "xloc": [
2281 - "default.handlebars->25->1546",
2282 - "default.handlebars->25->1663"
2281 + "default.handlebars->25->1549",
2282 + "default.handlebars->25->1666"
2283 ]
2284 },
2285 {
@@ -2314,8 +2314,8 @@
2314 "zh-chs": "添加設備組",
2315 "xloc": [
2316 "default.handlebars->25->1290",
2317 - "default.handlebars->25->1540",
2318 - "default.handlebars->25->1651",
2317 + "default.handlebars->25->1543",
2318 + "default.handlebars->25->1654",
2319 "default.handlebars->25->198"
2320 ]
2321 },
@@ -2432,7 +2432,7 @@
2432 "ru": "Добавить участие",
2433 "zh-chs": "添加會員",
2434 "xloc": [
2435 - "default.handlebars->25->1681"
2435 + "default.handlebars->25->1684"
2436 ]
2437 },
2438 {
@@ -2524,7 +2524,7 @@
2524 "xloc": [
2525 "default.handlebars->25->1190",
2526 "default.handlebars->25->1289",
2527 - "default.handlebars->25->1657",
2527 + "default.handlebars->25->1660",
2528 "default.handlebars->25->572"
2529 ]
2530 },
@@ -2585,7 +2585,7 @@
2585 "zh-chs": "添加用戶",
2586 "xloc": [
2587 "default.handlebars->25->1189",
2588 - "default.handlebars->25->1535"
2588 + "default.handlebars->25->1538"
2589 ]
2590 },
2591 {
@@ -2619,7 +2619,7 @@
2619 "ru": "Добавить пользователей в группу",
2620 "zh-chs": "將用戶添加到用戶組",
2621 "xloc": [
2622 - "default.handlebars->25->1568"
2622 + "default.handlebars->25->1571"
2623 ]
2624 },
2625 {
@@ -2826,7 +2826,7 @@
2826 "ru": "Области администратора",
2827 "zh-chs": "管理領域",
2828 "xloc": [
2829 - "default.handlebars->25->1599"
2829 + "default.handlebars->25->1602"
2830 ]
2831 },
2832 {
@@ -2989,7 +2989,7 @@
2989 "ru": "Счетчик ошибок агента",
2990 "zh-chs": "座席錯誤計數器",
2991 "xloc": [
2992 - "default.handlebars->25->1722"
2992 + "default.handlebars->25->1725"
2993 ]
2994 },
2995 {
@@ -3058,7 +3058,7 @@
3058 "ru": "Сессии агентов",
3059 "zh-chs": "座席會議",
3060 "xloc": [
3061 - "default.handlebars->25->1738"
3061 + "default.handlebars->25->1741"
3062 ]
3063 },
3064 {
@@ -3181,7 +3181,7 @@
3181 "ru": "Агенты",
3182 "zh-chs": "代理商",
3183 "xloc": [
3184 - "default.handlebars->25->1751"
3184 + "default.handlebars->25->1754"
3185 ]
3186 },
3187 {
@@ -3268,7 +3268,7 @@
3268 "zh-chs": "允許用戶管理此設備組和該組中的設備。",
3269 "xloc": [
3270 "default.handlebars->25->1256",
3271 - "default.handlebars->25->1565"
3271 + "default.handlebars->25->1568"
3272 ]
3273 },
3274 {
@@ -3372,7 +3372,7 @@
3372 "zh-chs": "始終通知",
3373 "xloc": [
3374 "default.handlebars->25->1170",
3375 - "default.handlebars->25->1608",
3375 + "default.handlebars->25->1611",
3376 "default.handlebars->25->518"
3377 ]
3378 },
@@ -3391,7 +3391,7 @@
3391 "zh-chs": "總是提示",
3392 "xloc": [
3393 "default.handlebars->25->1171",
3394 - "default.handlebars->25->1609",
3394 + "default.handlebars->25->1612",
3395 "default.handlebars->25->519"
3396 ]
3397 },
@@ -4001,7 +4001,7 @@
4001 "ru": "Вы уверенны, что {0} плагин: {1}",
4002 "zh-chs": "您確定要{0}插件嗎:{1}",
4003 "xloc": [
4004 - "default.handlebars->25->1791"
4004 + "default.handlebars->25->1794"
4005 ]
4006 },
4007 {
@@ -4097,7 +4097,7 @@
4097 "ru": "Приложение аутентификации",
4098 "zh-chs": "身份驗證應用",
4099 "xloc": [
4100 - "default.handlebars->25->1612"
4100 + "default.handlebars->25->1615"
4101 ]
4102 },
4103 {
@@ -4414,7 +4414,7 @@
4414 "ru": "Резервные коды",
4415 "zh-chs": "備用碼",
4416 "xloc": [
4417 - "default.handlebars->25->1614"
4417 + "default.handlebars->25->1617"
4418 ]
4419 },
4420 {
@@ -4431,7 +4431,7 @@
4431 "ru": "Плохой ключ",
4432 "zh-chs": "錯誤的簽名",
4433 "xloc": [
4434 - "default.handlebars->25->1729"
4434 + "default.handlebars->25->1732"
4435 ]
4436 },
4437 {
@@ -4448,7 +4448,7 @@
4448 "ru": "Плохой веб-сертификат",
4449 "zh-chs": "錯誤的網絡證書",
4450 "xloc": [
4451 - "default.handlebars->25->1728"
4451 + "default.handlebars->25->1731"
4452 ]
4453 },
4454 {
@@ -4586,7 +4586,7 @@
4586 "ru": "Отправить сообщение",
4587 "zh-chs": "廣播",
4588 "xloc": [
4589 - "default.handlebars->25->1533",
4589 + "default.handlebars->25->1536",
4590 "default.handlebars->container->column_l->p4->3->1->0->3->1"
4591 ]
4592 },
@@ -4711,7 +4711,7 @@
4711 "ru": "CIRA Сервер",
4712 "zh-chs": "CIRA服務器",
4713 "xloc": [
4714 - "default.handlebars->25->1779"
4714 + "default.handlebars->25->1782"
4715 ]
4716 },
4717 {
@@ -4728,7 +4728,7 @@
4728 "ru": "CIRA Сервер команды",
4729 "zh-chs": "CIRA服務器命令",
4730 "xloc": [
4731 - "default.handlebars->25->1780"
4731 + "default.handlebars->25->1783"
4732 ]
4733 },
4734 {
@@ -4762,7 +4762,7 @@
4762 "ru": "Загрузка CPU",
4763 "zh-chs": "CPU負載",
4764 "xloc": [
4765 - "default.handlebars->25->1743"
4765 + "default.handlebars->25->1746"
4766 ]
4767 },
4768 {
@@ -4779,7 +4779,7 @@
4779 "ru": "Загрузка CPU за последние 15 минут",
4780 "zh-chs": "最近15分鐘的CPU負載",
4781 "xloc": [
4782 - "default.handlebars->25->1746"
4782 + "default.handlebars->25->1749"
4783 ]
4784 },
4785 {
@@ -4796,7 +4796,7 @@
4796 "ru": "Загрузка CPU за последние 5 минут",
4797 "zh-chs": "最近5分鐘的CPU負載",
4798 "xloc": [
4799 - "default.handlebars->25->1745"
4799 + "default.handlebars->25->1748"
4800 ]
4801 },
4802 {
@@ -4813,7 +4813,7 @@
4813 "ru": "Загрузка CPU за последнюю минуту",
4814 "zh-chs": "最後一分鐘的CPU負載",
4815 "xloc": [
4816 - "default.handlebars->25->1744"
4816 + "default.handlebars->25->1747"
4817 ]
4818 },
4819 {
@@ -4868,7 +4868,7 @@
4868 "ru": "Ошибка вызова",
4869 "zh-chs": "通話錯誤",
4870 "xloc": [
4871 - "default.handlebars->25->1792"
4871 + "default.handlebars->25->1795"
4872 ]
4873 },
4874 {
@@ -5008,7 +5008,7 @@
5008 "ru": "Смена email для {0}",
5009 "zh-chs": "更改{0}的電子郵件",
5010 "xloc": [
5011 - "default.handlebars->25->1640"
5011 + "default.handlebars->25->1643"
5012 ]
5013 },
5014 {
@@ -5046,7 +5046,7 @@
5046 "xloc": [
5047 "default-mobile.handlebars->9->90",
5048 "default.handlebars->25->1115",
5049 - "default.handlebars->25->1629"
5049 + "default.handlebars->25->1632"
5050 ]
5051 },
5052 {
@@ -5063,7 +5063,7 @@
5063 "ru": "Смена пароля для {0}",
5064 "zh-chs": "更改{0}的密碼",
5065 "xloc": [
5066 - "default.handlebars->25->1647"
5066 + "default.handlebars->25->1650"
5067 ]
5068 },
5069 {
@@ -5133,7 +5133,7 @@
5133 "ru": "Изменить пароль для этого пользователя",
5134 "zh-chs": "更改該用戶的密碼",
5135 "xloc": [
5136 - "default.handlebars->25->1628"
5136 + "default.handlebars->25->1631"
5137 ]
5138 },
5139 {
@@ -5338,7 +5338,7 @@
5338 "ru": "Проверка...",
5339 "zh-chs": "檢查...",
5340 "xloc": [
5341 - "default.handlebars->25->1786",
5341 + "default.handlebars->25->1789",
5342 "default.handlebars->25->888"
5343 ]
5344 },
@@ -5554,7 +5554,7 @@
5554 "nl": "Wis alle meldingen",
5555 "zh-chs": "全部清除",
5556 "xloc": [
5557 - "default.handlebars->25->1716"
5557 + "default.handlebars->25->1719"
5558 ]
5559 },
5560 {
@@ -5604,7 +5604,7 @@
5604 "ru": "Очистить это уведомление",
5605 "zh-chs": "清除此通知",
5606 "xloc": [
5607 - "default.handlebars->25->1715"
5607 + "default.handlebars->25->1718"
5608 ]
5609 },
5610 {
@@ -5680,7 +5680,7 @@
5680 "nl": "Klik hier om de gebruikersgroepsnaam te bewerken",
5681 "zh-chs": "单击此处编辑用户组名称",
5682 "xloc": [
5683 - "default.handlebars->25->1525"
5683 + "default.handlebars->25->1527"
5684 ]
5685 },
5686 {
@@ -5855,8 +5855,8 @@
5855 "ru": "Общие группы устройств",
5856 "zh-chs": "通用設備組",
5857 "xloc": [
5858 - "default.handlebars->25->1541",
5859 - "default.handlebars->25->1652"
5858 + "default.handlebars->25->1544",
5859 + "default.handlebars->25->1655"
5860 ]
5861 },
5862 {
@@ -5873,8 +5873,8 @@
5873 "ru": "Общие устройства",
5874 "zh-chs": "通用設備",
5875 "xloc": [
5876 - "default.handlebars->25->1547",
5877 - "default.handlebars->25->1664"
5876 + "default.handlebars->25->1550",
5877 + "default.handlebars->25->1667"
5878 ]
5879 },
5880 {
@@ -5914,8 +5914,8 @@
5914 "default.handlebars->25->1235",
5915 "default.handlebars->25->1448",
5916 "default.handlebars->25->1517",
5917 - "default.handlebars->25->1561",
5918 - "default.handlebars->25->1650",
5917 + "default.handlebars->25->1564",
5918 + "default.handlebars->25->1653",
5919 "default.handlebars->25->408",
5920 "default.handlebars->25->647",
5921 "default.handlebars->25->656"
@@ -6016,7 +6016,7 @@
6016 "ru": "Подтвердить удаление пользователя {0}?",
6017 "zh-chs": "確認刪除用戶{0}?",
6018 "xloc": [
6019 - "default.handlebars->25->1649"
6019 + "default.handlebars->25->1652"
6020 ]
6021 },
6022 {
@@ -6030,7 +6030,7 @@
6030 "nl": "Bevestig lidmaatschap verwijderen van gebruiker \\\"{0}\\\"?",
6031 "zh-chs": "确认删除用户\\“ {0} \\”的成员身份?",
6032 "xloc": [
6033 - "default.handlebars->25->1564"
6033 + "default.handlebars->25->1567"
6034 ]
6035 },
6036 {
@@ -6044,7 +6044,7 @@
6044 "nl": "Bevestig lidmaatschap verwijdering van gebruikergroep \\\"{0}\\\"?",
6045 "zh-chs": "确认删除用户组 “{0}” 的成员身份?",
6046 "xloc": [
6047 - "default.handlebars->25->1679"
6047 + "default.handlebars->25->1682"
6048 ]
6049 },
6050 {
@@ -6111,8 +6111,8 @@
6111 "nl": "Bevestig verwijdering van toegangsrechten voor apparaat \\\"{0}\\\"?",
6112 "zh-chs": "确认删除设备“ {0} ”的访问权限?",
6113 "xloc": [
6114 - "default.handlebars->25->1554",
6115 - "default.handlebars->25->1670"
6114 + "default.handlebars->25->1557",
6115 + "default.handlebars->25->1673"
6116 ]
6117 },
6118 {
@@ -6126,8 +6126,8 @@
6126 "nl": "Bevestig verwijdering van toegangsrechten voor apparaatgroep \\\"{0}\\\"?",
6127 "zh-chs": "是否确认删除设备组“ {0}”的访问权限?",
6128 "xloc": [
6129 - "default.handlebars->25->1556",
6130 - "default.handlebars->25->1683"
6129 + "default.handlebars->25->1559",
6130 + "default.handlebars->25->1686"
6131 ]
6132 },
6133 {
@@ -6141,7 +6141,7 @@
6141 "nl": "Bevestig verwijdering van toegangsrechten voor gebruiker \\\"{0}\\\"?",
6142 "zh-chs": "确认删除用户\\“ {0} \\”的访问权限?",
6143 "xloc": [
6144 - "default.handlebars->25->1672"
6144 + "default.handlebars->25->1675"
6145 ]
6146 },
6147 {
@@ -6155,7 +6155,7 @@
6155 "nl": "Bevestig verwijdering van toegangsrechten voor gebruikergroep \\\"{0}\\\"?",
6156 "zh-chs": "确认删除用户组“ {0}”的访问权限?",
6157 "xloc": [
6158 - "default.handlebars->25->1675"
6158 + "default.handlebars->25->1678"
6159 ]
6160 },
6161 {
@@ -6169,8 +6169,8 @@
6169 "nl": "Verwijdering van toegangsrechten bevestigen?",
6170 "zh-chs": "确认删除访问权限?",
6171 "xloc": [
6172 - "default.handlebars->25->1673",
6173 - "default.handlebars->25->1676"
6172 + "default.handlebars->25->1676",
6173 + "default.handlebars->25->1679"
6174 ]
6175 },
6176 {
@@ -6417,7 +6417,7 @@
6417 "ru": "Подключено Intel® AMT",
6418 "zh-chs": "連接的英特爾®AMT",
6419 "xloc": [
6420 - "default.handlebars->25->1734"
6420 + "default.handlebars->25->1737"
6421 ]
6422 },
6423 {
@@ -6434,7 +6434,7 @@
6434 "ru": "Подключенные пользователи",
6435 "zh-chs": "關聯用戶",
6436 "xloc": [
6437 - "default.handlebars->25->1739"
6437 + "default.handlebars->25->1742"
6438 ]
6439 },
6440 {
@@ -6511,7 +6511,7 @@
6511 "ru": "Подключений ",
6512 "zh-chs": "連接數",
6513 "xloc": [
6514 - "default.handlebars->25->1750"
6514 + "default.handlebars->25->1753"
6515 ]
6516 },
6517 {
@@ -6528,7 +6528,7 @@
6528 "ru": "Ретранслятор подключения",
6529 "zh-chs": "連接繼電器",
6530 "xloc": [
6531 - "default.handlebars->25->1778"
6531 + "default.handlebars->25->1781"
6532 ]
6533 },
6534 {
@@ -6655,7 +6655,7 @@
6655 "ru": "Cookie-кодировщик",
6656 "zh-chs": "Cookie編碼器",
6657 "xloc": [
6658 - "default.handlebars->25->1764"
6658 + "default.handlebars->25->1767"
6659 ]
6660 },
6661 {
@@ -6960,7 +6960,7 @@
6960 "ru": "Основной сервер",
6961 "zh-chs": "核心服務器",
6962 "xloc": [
6963 - "default.handlebars->25->1763"
6963 + "default.handlebars->25->1766"
6964 ]
6965 },
6966 {
@@ -7030,7 +7030,7 @@
7030 "ru": "Создать группу пользователей",
7031 "zh-chs": "創建用戶組",
7032 "xloc": [
7033 - "default.handlebars->25->1522"
7033 + "default.handlebars->25->1524"
7034 ]
7035 },
7036 {
@@ -7116,7 +7116,7 @@
7116 "ru": "Создано",
7117 "zh-chs": "創建",
7118 "xloc": [
7119 - "default.handlebars->25->1588"
7119 + "default.handlebars->25->1591"
7120 ]
7121 },
7122 {
@@ -7437,7 +7437,8 @@
7437 "en": "Default",
7438 "nl": "Standaard",
7439 "xloc": [
7440 - "default.handlebars->25->1474"
7440 + "default.handlebars->25->1474",
7441 + "default.handlebars->25->1520"
7442 ]
7443 },
7444 {
@@ -7588,7 +7589,7 @@
7589 "ru": "Удалить пользователя",
7590 "zh-chs": "刪除用戶",
7591 "xloc": [
7591 - "default.handlebars->25->1627"
7592 + "default.handlebars->25->1630"
7593 ]
7594 },
7595 {
@@ -7605,8 +7606,8 @@
7606 "ru": "Удалить группу пользователей",
7607 "zh-chs": "刪除用戶組",
7608 "xloc": [
7608 - "default.handlebars->25->1552",
7609 - "default.handlebars->25->1562"
7609 + "default.handlebars->25->1555",
7610 + "default.handlebars->25->1565"
7611 ]
7612 },
7613 {
@@ -7637,7 +7638,7 @@
7638 "ru": "Удалить пользователя {0}",
7639 "zh-chs": "刪除用戶{0}",
7640 "xloc": [
7640 - "default.handlebars->25->1648"
7641 + "default.handlebars->25->1651"
7642 ]
7643 },
7644 {
@@ -7741,7 +7742,7 @@
7742 "ru": "Удалить группу пользователей {0}?",
7743 "zh-chs": "刪除用戶組{0}?",
7744 "xloc": [
7744 - "default.handlebars->25->1560"
7745 + "default.handlebars->25->1563"
7746 ]
7747 },
7748 {
@@ -7878,10 +7879,10 @@
7879 "default.handlebars->25->1127",
7880 "default.handlebars->25->1155",
7881 "default.handlebars->25->1238",
7881 - "default.handlebars->25->1521",
7882 - "default.handlebars->25->1528",
7883 - "default.handlebars->25->1529",
7884 - "default.handlebars->25->1558",
7882 + "default.handlebars->25->1523",
7883 + "default.handlebars->25->1530",
7884 + "default.handlebars->25->1531",
7885 + "default.handlebars->25->1561",
7886 "default.handlebars->25->477",
7887 "default.handlebars->25->478",
7888 "default.handlebars->25->688",
@@ -7920,7 +7921,7 @@
7921 "xloc": [
7922 "default-mobile.handlebars->9->245",
7923 "default.handlebars->25->1243",
7923 - "default.handlebars->25->1693",
7924 + "default.handlebars->25->1696",
7925 "default.handlebars->25->444",
7926 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevDesktop",
7927 "default.handlebars->contextMenu->cxdesktop"
@@ -7958,7 +7959,7 @@
7959 "zh-chs": "桌面通知",
7960 "xloc": [
7961 "default.handlebars->25->1165",
7961 - "default.handlebars->25->1603",
7962 + "default.handlebars->25->1606",
7963 "default.handlebars->25->513"
7964 ]
7965 },
@@ -7977,7 +7978,7 @@
7978 "zh-chs": "桌面提示",
7979 "xloc": [
7980 "default.handlebars->25->1164",
7980 - "default.handlebars->25->1602",
7981 + "default.handlebars->25->1605",
7982 "default.handlebars->25->512"
7983 ]
7984 },
@@ -7996,7 +7997,7 @@
7997 "zh-chs": "桌面提示+工具欄",
7998 "xloc": [
7999 "default.handlebars->25->1162",
7999 - "default.handlebars->25->1600",
8000 + "default.handlebars->25->1603",
8001 "default.handlebars->25->510"
8002 ]
8003 },
@@ -8029,7 +8030,7 @@
8030 "zh-chs": "桌面工具欄",
8031 "xloc": [
8032 "default.handlebars->25->1163",
8032 - "default.handlebars->25->1601",
8033 + "default.handlebars->25->1604",
8034 "default.handlebars->25->511"
8035 ]
8036 },
@@ -8102,7 +8103,7 @@
8103 "zh-chs": "設備",
8104 "xloc": [
8105 "default.handlebars->25->1265",
8105 - "default.handlebars->25->1667",
8106 + "default.handlebars->25->1670",
8107 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->5"
8108 ]
8109 },
@@ -8141,10 +8142,10 @@
8142 "default.handlebars->25->1260",
8143 "default.handlebars->25->1263",
8144 "default.handlebars->25->1264",
8144 - "default.handlebars->25->1544",
8145 - "default.handlebars->25->1550",
8146 - "default.handlebars->25->1655",
8147 - "default.handlebars->25->1702"
8145 + "default.handlebars->25->1547",
8146 + "default.handlebars->25->1553",
8147 + "default.handlebars->25->1658",
8148 + "default.handlebars->25->1705"
8149 ]
8150 },
8151 {
@@ -8182,9 +8183,9 @@
8183 "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->3",
8184 "default.handlebars->25->1414",
8185 "default.handlebars->25->1508",
8185 - "default.handlebars->25->1531",
8186 - "default.handlebars->25->1597",
8187 - "default.handlebars->25->1737",
8186 + "default.handlebars->25->1534",
8187 + "default.handlebars->25->1600",
8188 + "default.handlebars->25->1740",
8189 "default.handlebars->container->column_l->p2->p2info->7"
8190 ]
8191 },
@@ -8244,7 +8245,7 @@
8245 "zh-chs": "設備名稱",
8246 "xloc": [
8247 "default-mobile.handlebars->9->267",
8247 - "default.handlebars->25->1701",
8248 + "default.handlebars->25->1704",
8249 "default.handlebars->25->244",
8250 "default.handlebars->25->686",
8251 "player.handlebars->3->9"
@@ -8625,7 +8626,7 @@
8626 "zh-chs": "设备",
8627 "xloc": [
8628 "default.handlebars->25->1509",
8628 - "default.handlebars->25->1532"
8629 + "default.handlebars->25->1535"
8630 ]
8631 },
8632 {
@@ -8815,7 +8816,8 @@
8816 "en": "Domain",
8817 "nl": "Domein",
8818 "xloc": [
8818 - "default.handlebars->25->1475"
8819 + "default.handlebars->25->1475",
8820 + "default.handlebars->25->1521"
8821 ]
8822 },
8823 {
@@ -9263,7 +9265,7 @@
9265 "nl": "Dubbele agent",
9266 "zh-chs": "代理重复",
9267 "xloc": [
9266 - "default.handlebars->25->1733"
9268 + "default.handlebars->25->1736"
9269 ]
9270 },
9271 {
@@ -9297,7 +9299,7 @@
9299 "ru": "Скопировать группу пользователей",
9300 "zh-chs": "重複的用戶組",
9301 "xloc": [
9300 - "default.handlebars->25->1523"
9302 + "default.handlebars->25->1525"
9303 ]
9304 },
9305 {
@@ -9328,8 +9330,8 @@
9330 "ru": "Длительность",
9331 "zh-chs": "持續時間",
9332 "xloc": [
9331 - "default.handlebars->25->1687",
9332 - "default.handlebars->25->1707",
9333 + "default.handlebars->25->1690",
9334 + "default.handlebars->25->1710",
9335 "player.handlebars->3->2"
9336 ]
9337 },
@@ -9814,7 +9816,7 @@
9816 "ru": "Редактировать группу пользователей",
9817 "zh-chs": "編輯用戶組",
9818 "xloc": [
9817 - "default.handlebars->25->1559"
9819 + "default.handlebars->25->1562"
9820 ]
9821 },
9822 {
@@ -9864,10 +9866,10 @@
9866 "xloc": [
9867 "default-mobile.handlebars->9->78",
9868 "default.handlebars->25->1477",
9867 - "default.handlebars->25->1582",
9868 - "default.handlebars->25->1583",
9869 - "default.handlebars->25->1622",
9870 - "default.handlebars->25->1636",
9869 + "default.handlebars->25->1585",
9870 + "default.handlebars->25->1586",
9871 + "default.handlebars->25->1625",
9872 + "default.handlebars->25->1639",
9873 "default.handlebars->25->292",
9874 "login-mobile.handlebars->5->42",
9875 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3",
@@ -10001,7 +10003,7 @@
10003 "zh-chs": "電子郵件已驗證",
10004 "xloc": [
10005 "default.handlebars->25->1434",
10004 - "default.handlebars->25->1578"
10006 + "default.handlebars->25->1581"
10007 ]
10008 },
10009 {
@@ -10035,7 +10037,7 @@
10037 "ru": "Email не подтвержден",
10038 "zh-chs": "電子郵件未驗證",
10039 "xloc": [
10038 - "default.handlebars->25->1579"
10040 + "default.handlebars->25->1582"
10041 ]
10042 },
10043 {
@@ -10087,7 +10089,7 @@
10089 "nl": "Email/SMS verkeer",
10090 "zh-chs": "电子邮件/短信流量",
10091 "xloc": [
10090 - "default.handlebars->25->1772"
10092 + "default.handlebars->25->1775"
10093 ]
10094 },
10095 {
@@ -10185,7 +10187,7 @@
10187 "en": "Enabled",
10188 "nl": "Ingeschakeld",
10189 "xloc": [
10188 - "default.handlebars->25->1709"
10190 + "default.handlebars->25->1712"
10191 ]
10192 },
10193 {
@@ -10209,7 +10211,7 @@
10211 "en": "End Time",
10212 "nl": "Eindtijd",
10213 "xloc": [
10212 - "default.handlebars->25->1706"
10214 + "default.handlebars->25->1709"
10215 ]
10216 },
10217 {
@@ -10772,7 +10774,7 @@
10774 "ru": "Внешний",
10775 "zh-chs": "外部",
10776 "xloc": [
10775 - "default.handlebars->25->1757"
10777 + "default.handlebars->25->1760"
10778 ]
10779 },
10780 {
@@ -10978,7 +10980,7 @@
10980 "default-mobile.handlebars->9->165",
10981 "default-mobile.handlebars->9->246",
10982 "default.handlebars->25->1250",
10981 - "default.handlebars->25->1694",
10983 + "default.handlebars->25->1697",
10984 "default.handlebars->25->218",
10985 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevFiles",
10986 "default.handlebars->contextMenu->cxfiles"
@@ -11016,7 +11018,7 @@
11018 "zh-chs": "文件通知",
11019 "xloc": [
11020 "default.handlebars->25->1169",
11019 - "default.handlebars->25->1607",
11021 + "default.handlebars->25->1610",
11022 "default.handlebars->25->517"
11023 ]
11024 },
@@ -11035,7 +11037,7 @@
11037 "zh-chs": "文件提示",
11038 "xloc": [
11039 "default.handlebars->25->1168",
11038 - "default.handlebars->25->1606",
11040 + "default.handlebars->25->1609",
11041 "default.handlebars->25->516"
11042 ]
11043 },
@@ -11197,7 +11199,7 @@
11199 "zh-chs": "下次登錄時強制重置密碼。",
11200 "xloc": [
11201 "default.handlebars->25->1482",
11200 - "default.handlebars->25->1645"
11202 + "default.handlebars->25->1648"
11203 ]
11204 },
11205 {
@@ -11283,8 +11285,8 @@
11285 "ru": "Свободно",
11286 "zh-chs": "自由",
11287 "xloc": [
11286 - "default.handlebars->25->1718",
11287 - "default.handlebars->25->1720"
11288 + "default.handlebars->25->1721",
11289 + "default.handlebars->25->1723"
11290 ]
11291 },
11292 {
@@ -11578,7 +11580,7 @@
11580 "ru": "Администратор с полным доступом",
11581 "zh-chs": "正式管理員",
11582 "xloc": [
11581 - "default.handlebars->25->1573"
11583 + "default.handlebars->25->1576"
11584 ]
11585 },
11586 {
@@ -12017,6 +12019,12 @@
12019 "default.handlebars->container->column_l->p50->3->1->0->3->3"
12020 ]
12021 },
12022 + {
12023 + "en": "Group Identifier",
12024 + "xloc": [
12025 + "default.handlebars->25->1532"
12026 + ]
12027 + },
12028 {
12029 "cs": "Členové skupiny",
12030 "de": "Gruppenmitglieder",
@@ -12031,7 +12039,7 @@
12039 "ru": "Члены группы",
12040 "zh-chs": "小組成員",
12041 "xloc": [
12034 - "default.handlebars->25->1536"
12042 + "default.handlebars->25->1539"
12043 ]
12044 },
12045 {
@@ -12203,7 +12211,7 @@
12211 "ru": "Всего кучи",
12212 "zh-chs": "堆總數",
12213 "xloc": [
12206 - "default.handlebars->25->1759"
12214 + "default.handlebars->25->1762"
12215 ]
12216 },
12217 {
@@ -12220,7 +12228,7 @@
12228 "ru": "Куча используется",
12229 "zh-chs": "堆使用",
12230 "xloc": [
12223 - "default.handlebars->25->1758"
12231 + "default.handlebars->25->1761"
12232 ]
12233 },
12234 {
@@ -13011,8 +13019,8 @@
13019 "xloc": [
13020 "default.handlebars->25->1352",
13021 "default.handlebars->25->1360",
13014 - "default.handlebars->25->1755",
13015 - "default.handlebars->25->1777"
13022 + "default.handlebars->25->1758",
13023 + "default.handlebars->25->1780"
13024 ]
13025 },
13026 {
@@ -13053,14 +13061,14 @@
13061 "en": "Intel AMT Redirection",
13062 "nl": "Intel AMT omleiding",
13063 "xloc": [
13056 - "default.handlebars->25->1696"
13064 + "default.handlebars->25->1699"
13065 ]
13066 },
13067 {
13068 "en": "Intel AMT WSMAN",
13069 "nl": "Intel AMT WSMAN",
13070 "xloc": [
13063 - "default.handlebars->25->1695"
13071 + "default.handlebars->25->1698"
13072 ]
13073 },
13074 {
@@ -13745,7 +13753,7 @@
13753 "ru": "Некорректный тип группы устройств",
13754 "zh-chs": "無效的設備組類型",
13755 "xloc": [
13748 - "default.handlebars->25->1732"
13756 + "default.handlebars->25->1735"
13757 ]
13758 },
13759 {
@@ -13762,7 +13770,7 @@
13770 "ru": "Некорректный JSON",
13771 "zh-chs": "無效的JSON",
13772 "xloc": [
13765 - "default.handlebars->25->1726"
13773 + "default.handlebars->25->1729"
13774 ]
13775 },
13776 {
@@ -13814,7 +13822,7 @@
13822 "ru": "Некорректная сигнатура PKCS",
13823 "zh-chs": "無效的PKCS簽名",
13824 "xloc": [
13817 - "default.handlebars->25->1724"
13825 + "default.handlebars->25->1727"
13826 ]
13827 },
13828 {
@@ -13831,7 +13839,7 @@
13839 "ru": "Некорректная сигнатура RSA",
13840 "zh-chs": "無效的RSA密碼",
13841 "xloc": [
13834 - "default.handlebars->25->1725"
13842 + "default.handlebars->25->1728"
13843 ]
13844 },
13845 {
@@ -14658,7 +14666,7 @@
14666 "ru": "Последний вход в систему",
14667 "zh-chs": "上次登錄",
14668 "xloc": [
14661 - "default.handlebars->25->1589"
14669 + "default.handlebars->25->1592"
14670 ]
14671 },
14672 {
@@ -14721,7 +14729,7 @@
14729 "ru": "Последнее изменение: {0}",
14730 "zh-chs": "上次更改:{0}",
14731 "xloc": [
14724 - "default.handlebars->25->1593"
14732 + "default.handlebars->25->1596"
14733 ]
14734 },
14735 {
@@ -14888,7 +14896,7 @@
14896 "nl": "Leeg laten voor geen.",
14897 "zh-chs": "一无所有。",
14898 "xloc": [
14891 - "default.handlebars->25->1633"
14899 + "default.handlebars->25->1636"
14900 ]
14901 },
14902 {
@@ -14927,7 +14935,7 @@
14935 "ru": "Меньше",
14936 "zh-chs": "減",
14937 "xloc": [
14930 - "default.handlebars->25->1794"
14938 + "default.handlebars->25->1797"
14939 ]
14940 },
14941 {
@@ -15523,7 +15531,7 @@
15531 "ru": "Заблокированная учетная запись",
15532 "zh-chs": "賬戶鎖定",
15533 "xloc": [
15526 - "default.handlebars->25->1570"
15534 + "default.handlebars->25->1573"
15535 ]
15536 },
15537 {
@@ -16036,7 +16044,7 @@
16044 "ru": "Сообщения главного сервера",
16045 "zh-chs": "主服務器消息",
16046 "xloc": [
16039 - "default.handlebars->25->1766"
16047 + "default.handlebars->25->1769"
16048 ]
16049 },
16050 {
@@ -16462,7 +16470,7 @@
16470 "ru": "Достигнуто максимальное число сессий",
16471 "zh-chs": "達到的會話數上限",
16472 "xloc": [
16465 - "default.handlebars->25->1730"
16473 + "default.handlebars->25->1733"
16474 ]
16475 },
16476 {
@@ -16516,7 +16524,7 @@
16524 "ru": "Мегабайт",
16525 "zh-chs": "兆字節",
16526 "xloc": [
16519 - "default.handlebars->25->1756"
16527 + "default.handlebars->25->1759"
16528 ]
16529 },
16530 {
@@ -16534,7 +16542,7 @@
16542 "zh-chs": "記憶",
16543 "xloc": [
16544 "default-mobile.handlebars->9->366",
16537 - "default.handlebars->25->1747",
16545 + "default.handlebars->25->1750",
16546 "default.handlebars->25->842",
16547 "default.handlebars->container->column_l->p40->3->1->p40type->3"
16548 ]
@@ -16672,7 +16680,7 @@
16680 "ru": "Трафик MeshAgent",
16681 "zh-chs": "MeshAgent流量",
16682 "xloc": [
16675 - "default.handlebars->25->1768"
16683 + "default.handlebars->25->1771"
16684 ]
16685 },
16686 {
@@ -16689,7 +16697,7 @@
16697 "ru": "Обновление MeshAgent",
16698 "zh-chs": "MeshAgent更新",
16699 "xloc": [
16692 - "default.handlebars->25->1769"
16700 + "default.handlebars->25->1772"
16701 ]
16702 },
16703 {
@@ -16792,7 +16800,7 @@
16800 "ru": "Соединения сервера MeshCentral",
16801 "zh-chs": "MeshCentral服務器對等",
16802 "xloc": [
16795 - "default.handlebars->25->1767"
16803 + "default.handlebars->25->1770"
16804 ]
16805 },
16806 {
@@ -17056,7 +17064,7 @@
17064 "ru": "Диспетчер сообщения",
17065 "zh-chs": "郵件調度程序",
17066 "xloc": [
17059 - "default.handlebars->25->1765"
17067 + "default.handlebars->25->1768"
17068 ]
17069 },
17070 {
@@ -17205,7 +17213,7 @@
17213 "ru": "Еще",
17214 "zh-chs": "更多",
17215 "xloc": [
17208 - "default.handlebars->25->1793"
17216 + "default.handlebars->25->1796"
17217 ]
17218 },
17219 {
@@ -17281,7 +17289,7 @@
17289 "en": "Multiplexor",
17290 "nl": "Multiplexor",
17291 "xloc": [
17284 - "default.handlebars->25->1708"
17292 + "default.handlebars->25->1711"
17293 ]
17294 },
17295 {
@@ -17554,10 +17562,10 @@
17562 "default.handlebars->25->1237",
17563 "default.handlebars->25->1413",
17564 "default.handlebars->25->1506",
17557 - "default.handlebars->25->1520",
17558 - "default.handlebars->25->1527",
17559 - "default.handlebars->25->1557",
17560 - "default.handlebars->25->1576",
17565 + "default.handlebars->25->1522",
17566 + "default.handlebars->25->1529",
17567 + "default.handlebars->25->1560",
17568 + "default.handlebars->25->1579",
17569 "default.handlebars->25->467",
17570 "default.handlebars->25->717",
17571 "default.handlebars->25->77",
@@ -17953,7 +17961,7 @@
17961 "zh-chs": "找不到活動",
17962 "xloc": [
17963 "default.handlebars->25->1403",
17956 - "default.handlebars->25->1684",
17964 + "default.handlebars->25->1687",
17965 "default.handlebars->25->788"
17966 ]
17967 },
@@ -18097,7 +18105,7 @@
18105 "ru": "Нет членов",
18106 "zh-chs": "沒有會員",
18107 "xloc": [
18100 - "default.handlebars->25->1539"
18108 + "default.handlebars->25->1542"
18109 ]
18110 },
18111 {
@@ -18247,8 +18255,8 @@
18255 "ru": "Нет общих групп устройств",
18256 "zh-chs": "沒有共同的設備組",
18257 "xloc": [
18250 - "default.handlebars->25->1545",
18251 - "default.handlebars->25->1656"
18258 + "default.handlebars->25->1548",
18259 + "default.handlebars->25->1659"
18260 ]
18261 },
18262 {
@@ -18344,8 +18352,8 @@
18352 "ru": "Нет общих устройств",
18353 "zh-chs": "沒有共同的設備",
18354 "xloc": [
18347 - "default.handlebars->25->1551",
18348 - "default.handlebars->25->1668"
18355 + "default.handlebars->25->1554",
18356 + "default.handlebars->25->1671"
18357 ]
18358 },
18359 {
@@ -18535,7 +18543,7 @@
18543 "ru": "Нет серверных прав",
18544 "zh-chs": "沒有服務器權限",
18545 "xloc": [
18538 - "default.handlebars->25->1571"
18546 + "default.handlebars->25->1574"
18547 ]
18548 },
18549 {
@@ -18552,7 +18560,7 @@
18560 "ru": "Нет членства в группах пользователей",
18561 "zh-chs": "沒有用戶組成員身份",
18562 "xloc": [
18555 - "default.handlebars->25->1662"
18563 + "default.handlebars->25->1665"
18564 ]
18565 },
18566 {
@@ -18654,13 +18662,13 @@
18662 "default.handlebars->25->1179",
18663 "default.handlebars->25->1354",
18664 "default.handlebars->25->1373",
18657 - "default.handlebars->25->1524",
18665 "default.handlebars->25->1526",
18666 + "default.handlebars->25->1528",
18667 "default.handlebars->25->158",
18660 - "default.handlebars->25->1585",
18661 - "default.handlebars->25->1594",
18662 - "default.handlebars->25->1598",
18663 - "default.handlebars->25->1610",
18668 + "default.handlebars->25->1588",
18669 + "default.handlebars->25->1597",
18670 + "default.handlebars->25->1601",
18671 + "default.handlebars->25->1613",
18672 "default.handlebars->25->174",
18673 "default.handlebars->25->175",
18674 "default.handlebars->25->464",
@@ -18820,7 +18828,7 @@
18828 "en": "Not on server",
18829 "nl": "Niet op de server",
18830 "xloc": [
18823 - "default.handlebars->25->1700"
18831 + "default.handlebars->25->1703"
18832 ]
18833 },
18834 {
@@ -18837,7 +18845,7 @@
18845 "ru": "Не задано",
18846 "zh-chs": "沒有設置",
18847 "xloc": [
18840 - "default.handlebars->25->1577"
18848 + "default.handlebars->25->1580"
18849 ]
18850 },
18851 {
@@ -18854,7 +18862,7 @@
18862 "ru": "не подтверждено",
18863 "zh-chs": "未經審核的",
18864 "xloc": [
18857 - "default.handlebars->25->1638"
18865 + "default.handlebars->25->1641"
18866 ]
18867 },
18868 {
@@ -18872,7 +18880,7 @@
18880 "zh-chs": "筆記",
18881 "xloc": [
18882 "default.handlebars->25->1187",
18875 - "default.handlebars->25->1618",
18883 + "default.handlebars->25->1621",
18884 "default.handlebars->25->536",
18885 "default.handlebars->25->590",
18886 "default.handlebars->25->609",
@@ -18980,7 +18988,7 @@
18988 "ru": "Уведомить",
18989 "zh-chs": "通知",
18990 "xloc": [
18983 - "default.handlebars->25->1624"
18991 + "default.handlebars->25->1627"
18992 ]
18993 },
18994 {
@@ -19094,7 +19102,7 @@
19102 "ru": "Произошло в {0}",
19103 "zh-chs": "發生在{0}",
19104 "xloc": [
19097 - "default.handlebars->25->1714"
19105 + "default.handlebars->25->1717"
19106 ]
19107 },
19108 {
@@ -19578,7 +19586,7 @@
19586 "ru": "Частичные права",
19587 "zh-chs": "部分權利",
19588 "xloc": [
19581 - "default.handlebars->25->1574"
19589 + "default.handlebars->25->1577"
19590 ]
19591 },
19592 {
@@ -19615,10 +19623,10 @@
19623 "default-mobile.handlebars->9->258",
19624 "default.handlebars->25->1478",
19625 "default.handlebars->25->1479",
19618 - "default.handlebars->25->1590",
19619 - "default.handlebars->25->1592",
19620 - "default.handlebars->25->1641",
19621 - "default.handlebars->25->1642",
19626 + "default.handlebars->25->1593",
19627 + "default.handlebars->25->1595",
19628 + "default.handlebars->25->1644",
19629 + "default.handlebars->25->1645",
19630 "default.handlebars->25->249",
19631 "default.handlebars->25->278",
19632 "default.handlebars->25->635"
@@ -19727,7 +19735,7 @@
19735 "ru": "Подсказка пароля",
19736 "zh-chs": "密碼提示",
19737 "xloc": [
19730 - "default.handlebars->25->1643"
19738 + "default.handlebars->25->1646"
19739 ]
19740 },
19741 {
@@ -20049,7 +20057,7 @@
20057 "default-mobile.handlebars->9->65",
20058 "default-mobile.handlebars->9->67",
20059 "default.handlebars->25->143",
20052 - "default.handlebars->25->1635",
20060 + "default.handlebars->25->1638",
20061 "default.handlebars->25->868",
20062 "default.handlebars->25->871"
20063 ]
@@ -20064,7 +20072,7 @@
20072 "nl": "Telefoonnummer",
20073 "zh-chs": "电话号码",
20074 "xloc": [
20067 - "default.handlebars->25->1584"
20075 + "default.handlebars->25->1587"
20076 ]
20077 },
20078 {
@@ -20078,7 +20086,7 @@
20086 "zh-chs": "电话号码:",
20087 "xloc": [
20088 "default-mobile.handlebars->9->66",
20081 - "default.handlebars->25->1634",
20089 + "default.handlebars->25->1637",
20090 "default.handlebars->25->870"
20091 ]
20092 },
@@ -20215,7 +20223,7 @@
20223 "zh-chs": "插件動作",
20224 "xloc": [
20225 "default.handlebars->25->169",
20218 - "default.handlebars->25->1790"
20226 + "default.handlebars->25->1793"
20227 ]
20228 },
20229 {
@@ -20533,7 +20541,7 @@
20541 "en": "Present on server",
20542 "nl": "Aanwezig op de server",
20543 "xloc": [
20536 - "default.handlebars->25->1699"
20544 + "default.handlebars->25->1702"
20545 ]
20546 },
20547 {
@@ -20647,7 +20655,7 @@
20655 "ru": "Протокол",
20656 "zh-chs": "協議",
20657 "xloc": [
20650 - "default.handlebars->25->1697",
20658 + "default.handlebars->25->1700",
20659 "player.handlebars->3->15"
20660 ]
20661 },
@@ -20955,7 +20963,7 @@
20963 "ru": "RSS",
20964 "zh-chs": "的RSS",
20965 "xloc": [
20958 - "default.handlebars->25->1760"
20966 + "default.handlebars->25->1763"
20967 ]
20968 },
20969 {
@@ -21050,7 +21058,7 @@
21058 "en": "Recording Details",
21059 "nl": "Opname details",
21060 "xloc": [
21053 - "default.handlebars->25->1711"
21061 + "default.handlebars->25->1714"
21062 ]
21063 },
21064 {
@@ -21174,7 +21182,7 @@
21182 "ru": "Число ретрансляций",
21183 "zh-chs": "中繼計數",
21184 "xloc": [
21177 - "default.handlebars->25->1742"
21185 + "default.handlebars->25->1745"
21186 ]
21187 },
21188 {
@@ -21191,7 +21199,7 @@
21199 "ru": "Ошибки ретранслятора",
21200 "zh-chs": "中繼錯誤",
21201 "xloc": [
21194 - "default.handlebars->25->1735"
21202 + "default.handlebars->25->1738"
21203 ]
21204 },
21205 {
@@ -21208,8 +21216,8 @@
21216 "ru": "Сессии ретранслятора",
21217 "zh-chs": "接力會議",
21218 "xloc": [
21211 - "default.handlebars->25->1741",
21212 - "default.handlebars->25->1754"
21219 + "default.handlebars->25->1744",
21220 + "default.handlebars->25->1757"
21221 ]
21222 },
21223 {
@@ -21529,8 +21537,8 @@
21537 "nl": "Apparaatgroepmachtigingen verwijderen",
21538 "zh-chs": "删除设备组权限",
21539 "xloc": [
21532 - "default.handlebars->25->1555",
21533 - "default.handlebars->25->1682"
21540 + "default.handlebars->25->1558",
21541 + "default.handlebars->25->1685"
21542 ]
21543 },
21544 {
@@ -21544,8 +21552,8 @@
21552 "nl": "Apparaatmachtigingen verwijderen",
21553 "zh-chs": "删除设备权限",
21554 "xloc": [
21547 - "default.handlebars->25->1553",
21548 - "default.handlebars->25->1669"
21555 + "default.handlebars->25->1556",
21556 + "default.handlebars->25->1672"
21557 ]
21558 },
21559 {
@@ -21573,7 +21581,7 @@
21581 "nl": "Lidmaatschap van gebruikersgroep verwijderen",
21582 "zh-chs": "删除用户组成员身份",
21583 "xloc": [
21576 - "default.handlebars->25->1678"
21584 + "default.handlebars->25->1681"
21585 ]
21586 },
21587 {
@@ -21588,7 +21596,7 @@
21596 "zh-chs": "删除用户组权限",
21597 "xloc": [
21598 "default.handlebars->25->1328",
21591 - "default.handlebars->25->1674"
21599 + "default.handlebars->25->1677"
21600 ]
21601 },
21602 {
@@ -21602,7 +21610,7 @@
21610 "nl": "Gebruikerslidmaatschap verwijderen",
21611 "zh-chs": "删除用户成员资格",
21612 "xloc": [
21605 - "default.handlebars->25->1563"
21613 + "default.handlebars->25->1566"
21614 ]
21615 },
21616 {
@@ -21617,7 +21625,7 @@
21625 "zh-chs": "删除用户权限",
21626 "xloc": [
21627 "default.handlebars->25->1326",
21620 - "default.handlebars->25->1671"
21628 + "default.handlebars->25->1674"
21629 ]
21630 },
21631 {
@@ -21634,7 +21642,7 @@
21642 "ru": "Удалить все двухфакторные аутентификации.",
21643 "zh-chs": "刪除所有第二因素驗證。",
21644 "xloc": [
21637 - "default.handlebars->25->1646"
21645 + "default.handlebars->25->1649"
21646 ]
21647 },
21648 {
@@ -21732,7 +21740,7 @@
21740 "ru": "Удалить этого пользователя",
21741 "zh-chs": "删除该用户",
21742 "xloc": [
21735 - "default.handlebars->25->1626"
21743 + "default.handlebars->25->1629"
21744 ]
21745 },
21746 {
@@ -21749,7 +21757,7 @@
21757 "ru": "Удалить членство пользователя в группе",
21758 "zh-chs": "刪除用戶組成員身份",
21759 "xloc": [
21752 - "default.handlebars->25->1660"
21760 + "default.handlebars->25->1663"
21761 ]
21762 },
21763 {
@@ -21763,7 +21771,7 @@
21771 "nl": "Gebruikersrechten voor dit apparaat verwijderen",
21772 "zh-chs": "删除此设备的用户组权限",
21773 "xloc": [
21766 - "default.handlebars->25->1549"
21774 + "default.handlebars->25->1552"
21775 ]
21776 },
21777 {
@@ -21780,7 +21788,7 @@
21788 "ru": "Удалить права группы пользователей для этой группы устройств",
21789 "zh-chs": "刪除該設備組的用戶組權限",
21790 "xloc": [
21783 - "default.handlebars->25->1543",
21791 + "default.handlebars->25->1546",
21792 "default.handlebars->25->574"
21793 ]
21794 },
@@ -21799,9 +21807,9 @@
21807 "zh-chs": "刪除此設備組的用戶權限",
21808 "xloc": [
21809 "default.handlebars->25->1204",
21802 - "default.handlebars->25->1537",
21803 - "default.handlebars->25->1654",
21804 - "default.handlebars->25->1666",
21810 + "default.handlebars->25->1540",
21811 + "default.handlebars->25->1657",
21812 + "default.handlebars->25->1669",
21813 "default.handlebars->25->575"
21814 ]
21815 },
@@ -21864,7 +21872,7 @@
21872 "xloc": [
21873 "default-mobile.handlebars->9->89",
21874 "default.handlebars->25->1486",
21867 - "default.handlebars->25->1644"
21875 + "default.handlebars->25->1647"
21876 ]
21877 },
21878 {
@@ -22106,7 +22114,7 @@
22114 "ru": "Ограничения",
22115 "zh-chs": "限制條件",
22116 "xloc": [
22109 - "default.handlebars->25->1575"
22117 + "default.handlebars->25->1578"
22118 ]
22119 },
22120 {
@@ -22329,8 +22337,8 @@
22337 "nl": "SMS",
22338 "zh-chs": "短信",
22339 "xloc": [
22332 - "default.handlebars->25->1615",
22333 - "default.handlebars->25->1620",
22340 + "default.handlebars->25->1618",
22341 + "default.handlebars->25->1623",
22342 "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3",
22343 "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->3"
22344 ]
@@ -22345,7 +22353,7 @@
22353 "nl": "SMS geschikt telefoonnummer voor deze gebruiker.",
22354 "zh-chs": "此用户的短信功能电话号码。",
22355 "xloc": [
22348 - "default.handlebars->25->1632"
22356 + "default.handlebars->25->1635"
22357 ]
22358 },
22359 {
@@ -22749,7 +22757,7 @@
22757 "xloc": [
22758 "default-mobile.handlebars->9->259",
22759 "default-mobile.handlebars->9->345",
22752 - "default.handlebars->25->1616",
22760 + "default.handlebars->25->1619",
22761 "default.handlebars->25->250",
22762 "default.handlebars->25->636",
22763 "default.handlebars->25->821"
@@ -22769,7 +22777,7 @@
22777 "ru": "Ключ безопасности",
22778 "zh-chs": "安全密鑰",
22779 "xloc": [
22772 - "default.handlebars->25->1613"
22780 + "default.handlebars->25->1616"
22781 ]
22782 },
22783 {
@@ -23060,14 +23068,14 @@
23068 "nl": "Stuur een SMS bericht naar deze gebruiker",
23069 "zh-chs": "发送短信给该用户",
23070 "xloc": [
23063 - "default.handlebars->25->1621"
23071 + "default.handlebars->25->1624"
23072 ]
23073 },
23074 {
23075 "en": "Send a email message to this user",
23076 "nl": "Stuur een e-mailbericht naar deze gebruiker",
23077 "xloc": [
23070 - "default.handlebars->25->1623"
23078 + "default.handlebars->25->1626"
23079 ]
23080 },
23081 {
@@ -23084,7 +23092,7 @@
23092 "ru": "Отправить уведомление всем пользователям этой группы.",
23093 "zh-chs": "向該組中的所有用戶發送通知。",
23094 "xloc": [
23087 - "default.handlebars->25->1534"
23095 + "default.handlebars->25->1537"
23096 ]
23097 },
23098 {
@@ -23217,7 +23225,7 @@
23225 "ru": "Отправить уведомление пользователю",
23226 "zh-chs": "發送用戶通知",
23227 "xloc": [
23220 - "default.handlebars->25->1625"
23228 + "default.handlebars->25->1628"
23229 ]
23230 },
23231 {
@@ -23286,7 +23294,7 @@
23294 "ru": "Сертификат сервера",
23295 "zh-chs": "服務器證書",
23296 "xloc": [
23289 - "default.handlebars->25->1770"
23297 + "default.handlebars->25->1773"
23298 ]
23299 },
23300 {
@@ -23303,7 +23311,7 @@
23311 "ru": "База данных сервера",
23312 "zh-chs": "服務器數據庫",
23313 "xloc": [
23306 - "default.handlebars->25->1771"
23314 + "default.handlebars->25->1774"
23315 ]
23316 },
23317 {
@@ -23361,7 +23369,7 @@
23369 "ru": "Квота сервера",
23370 "zh-chs": "服務器配額",
23371 "xloc": [
23364 - "default.handlebars->25->1587"
23372 + "default.handlebars->25->1590"
23373 ]
23374 },
23375 {
@@ -23395,7 +23403,7 @@
23403 "ru": "Права",
23404 "zh-chs": "服務器權限",
23405 "xloc": [
23398 - "default.handlebars->25->1586"
23406 + "default.handlebars->25->1589"
23407 ]
23408 },
23409 {
@@ -23412,7 +23420,7 @@
23420 "ru": "Состояние сервера",
23421 "zh-chs": "服務器狀態",
23422 "xloc": [
23415 - "default.handlebars->25->1721"
23423 + "default.handlebars->25->1724"
23424 ]
23425 },
23426 {
@@ -23446,7 +23454,7 @@
23454 "ru": "Трассировка сервера",
23455 "zh-chs": "服務器跟踪",
23456 "xloc": [
23449 - "default.handlebars->25->1781"
23457 + "default.handlebars->25->1784"
23458 ]
23459 },
23460 {
@@ -23585,7 +23593,7 @@
23593 "ru": "ServerStats.csv",
23594 "zh-chs": "ServerStats.csv",
23595 "xloc": [
23588 - "default.handlebars->25->1762"
23596 + "default.handlebars->25->1765"
23597 ]
23598 },
23599 {
@@ -23626,7 +23634,7 @@
23634 "en": "Session",
23635 "nl": "Sessie",
23636 "xloc": [
23629 - "default.handlebars->25->1685"
23637 + "default.handlebars->25->1688"
23638 ]
23639 },
23640 {
@@ -24165,8 +24173,8 @@
24173 "ru": "Размер",
24174 "zh-chs": "尺寸",
24175 "xloc": [
24168 - "default.handlebars->25->1688",
24169 - "default.handlebars->25->1703",
24176 + "default.handlebars->25->1691",
24177 + "default.handlebars->25->1706",
24178 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize"
24179 ]
24180 },
@@ -24977,8 +24985,8 @@
24985 "en": "Start Time",
24986 "nl": "Start tijd",
24987 "xloc": [
24980 - "default.handlebars->25->1686",
24981 - "default.handlebars->25->1705",
24988 + "default.handlebars->25->1689",
24989 + "default.handlebars->25->1708",
24990 "default.handlebars->25->700"
24991 ]
24992 },
@@ -25031,8 +25039,8 @@
25039 "ru": "Статус",
25040 "zh-chs": "狀態",
25041 "xloc": [
25034 - "default.handlebars->25->1637",
25035 - "default.handlebars->25->1698",
25042 + "default.handlebars->25->1640",
25043 + "default.handlebars->25->1701",
25044 "default.handlebars->container->column_l->p42->p42tbl->1->0->7"
25045 ]
25046 },
@@ -25584,7 +25592,7 @@
25592 "xloc": [
25593 "default-mobile.handlebars->9->162",
25594 "default.handlebars->25->1247",
25587 - "default.handlebars->25->1692",
25595 + "default.handlebars->25->1695",
25596 "default.handlebars->25->215",
25597 "default.handlebars->25->445",
25598 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevTerminal",
@@ -25623,7 +25631,7 @@
25631 "zh-chs": "終端通知",
25632 "xloc": [
25633 "default.handlebars->25->1167",
25626 - "default.handlebars->25->1605",
25634 + "default.handlebars->25->1608",
25635 "default.handlebars->25->515"
25636 ]
25637 },
@@ -25642,7 +25650,7 @@
25650 "zh-chs": "終端提示",
25651 "xloc": [
25652 "default.handlebars->25->1166",
25645 - "default.handlebars->25->1604",
25653 + "default.handlebars->25->1607",
25654 "default.handlebars->25->514"
25655 ]
25656 },
@@ -25786,7 +25794,7 @@
25794 "ru": "На данный момент уведомлений нет",
25795 "zh-chs": "目前沒有任何通知",
25796 "xloc": [
25789 - "default.handlebars->25->1713"
25797 + "default.handlebars->25->1716"
25798 ]
25799 },
25800 {
@@ -27019,9 +27027,9 @@
27027 "default.handlebars->25->1144",
27028 "default.handlebars->25->1145",
27029 "default.handlebars->25->13",
27022 - "default.handlebars->25->1677",
27023 - "default.handlebars->25->1690",
27024 - "default.handlebars->25->1691",
27030 + "default.handlebars->25->1680",
27031 + "default.handlebars->25->1693",
27032 + "default.handlebars->25->1694",
27033 "default.handlebars->25->392",
27034 "default.handlebars->25->41",
27035 "default.handlebars->25->42",
@@ -27066,7 +27074,7 @@
27074 "ru": "Неизвестное действие",
27075 "zh-chs": "未知動作",
27076 "xloc": [
27069 - "default.handlebars->25->1727"
27077 + "default.handlebars->25->1730"
27078 ]
27079 },
27080 {
@@ -27083,8 +27091,8 @@
27091 "ru": "Неизвестное устройство",
27092 "zh-chs": "未知設備",
27093 "xloc": [
27086 - "default.handlebars->25->1548",
27087 - "default.handlebars->25->1665"
27094 + "default.handlebars->25->1551",
27095 + "default.handlebars->25->1668"
27096 ]
27097 },
27098 {
@@ -27101,9 +27109,9 @@
27109 "ru": "Неизвестная группа устройств",
27110 "zh-chs": "未知設備組",
27111 "xloc": [
27104 - "default.handlebars->25->1542",
27105 - "default.handlebars->25->1653",
27106 - "default.handlebars->25->1731"
27112 + "default.handlebars->25->1545",
27113 + "default.handlebars->25->1656",
27114 + "default.handlebars->25->1734"
27115 ]
27116 },
27117 {
@@ -27120,7 +27128,7 @@
27128 "ru": "Неизвестная группа",
27129 "zh-chs": "未知群組",
27130 "xloc": [
27123 - "default.handlebars->25->1723"
27131 + "default.handlebars->25->1726"
27132 ]
27133 },
27134 {
@@ -27155,7 +27163,7 @@
27163 "ru": "Неизвестная группа пользователей",
27164 "zh-chs": "未知用戶組",
27165 "xloc": [
27158 - "default.handlebars->25->1659"
27166 + "default.handlebars->25->1662"
27167 ]
27168 },
27169 {
@@ -27244,7 +27252,7 @@
27252 "ru": "Актуально",
27253 "zh-chs": "最新",
27254 "xloc": [
27247 - "default.handlebars->25->1788"
27255 + "default.handlebars->25->1791"
27256 ]
27257 },
27258 {
@@ -27493,8 +27501,8 @@
27501 "ru": "Использовано",
27502 "zh-chs": "用過的",
27503 "xloc": [
27496 - "default.handlebars->25->1717",
27497 - "default.handlebars->25->1719"
27504 + "default.handlebars->25->1720",
27505 + "default.handlebars->25->1722"
27506 ]
27507 },
27508 {
@@ -27513,8 +27521,8 @@
27521 "xloc": [
27522 "default.handlebars->25->1205",
27523 "default.handlebars->25->1428",
27516 - "default.handlebars->25->1538",
27517 - "default.handlebars->25->1710",
27524 + "default.handlebars->25->1541",
27525 + "default.handlebars->25->1713",
27526 "default.handlebars->25->193",
27527 "default.handlebars->25->577"
27528 ]
@@ -27570,7 +27578,7 @@
27578 "ru": "Учетные записи пользователей",
27579 "zh-chs": "用戶帳號",
27580 "xloc": [
27573 - "default.handlebars->25->1736"
27581 + "default.handlebars->25->1739"
27582 ]
27583 },
27584 {
@@ -27607,7 +27615,7 @@
27615 "zh-chs": "用戶同意",
27616 "xloc": [
27617 "default.handlebars->25->1173",
27610 - "default.handlebars->25->1611",
27618 + "default.handlebars->25->1614",
27619 "default.handlebars->25->521"
27620 ]
27621 },
@@ -27628,8 +27636,8 @@
27636 "default.handlebars->25->1261",
27637 "default.handlebars->25->1262",
27638 "default.handlebars->25->1519",
27631 - "default.handlebars->25->1661",
27632 - "default.handlebars->25->1680",
27639 + "default.handlebars->25->1664",
27640 + "default.handlebars->25->1683",
27641 "default.handlebars->25->576"
27642 ]
27643 },
@@ -27664,7 +27672,7 @@
27672 "ru": "Членство в группах пользователей",
27673 "zh-chs": "用戶組成員資格",
27674 "xloc": [
27667 - "default.handlebars->25->1658"
27675 + "default.handlebars->25->1661"
27676 ]
27677 },
27678 {
@@ -27689,8 +27697,8 @@
27697 "zh-chs": "用戶標識",
27698 "xloc": [
27699 "default.handlebars->25->1322",
27692 - "default.handlebars->25->1580",
27693 - "default.handlebars->25->1581"
27700 + "default.handlebars->25->1583",
27701 + "default.handlebars->25->1584"
27702 ]
27703 },
27704 {
@@ -27698,7 +27706,7 @@
27706 "nl": "Gebruikers-ID's",
27707 "xloc": [
27708 "default.handlebars->25->1259",
27701 - "default.handlebars->25->1567"
27709 + "default.handlebars->25->1570"
27710 ]
27711 },
27712 {
@@ -27795,7 +27803,7 @@
27803 "ru": "Сессии пользователя",
27804 "zh-chs": "用戶會話",
27805 "xloc": [
27798 - "default.handlebars->25->1753"
27806 + "default.handlebars->25->1756"
27807 ]
27808 },
27809 {
@@ -27990,8 +27998,8 @@
27998 "zh-chs": "用戶數",
27999 "xloc": [
28000 "default.handlebars->25->1507",
27993 - "default.handlebars->25->1530",
27994 - "default.handlebars->25->1752",
28001 + "default.handlebars->25->1533",
28002 + "default.handlebars->25->1755",
28003 "default.handlebars->container->topbar->1->1->UsersSubMenuSpan->UsersSubMenu->1->0->UsersGeneral"
28004 ]
28005 },
@@ -28009,7 +28017,7 @@
28017 "ru": "Сессии пользователей",
28018 "zh-chs": "用戶會話",
28019 "xloc": [
28012 - "default.handlebars->25->1740"
28020 + "default.handlebars->25->1743"
28021 ]
28022 },
28023 {
@@ -28094,7 +28102,7 @@
28102 "ru": "Проверенный",
28103 "zh-chs": "已驗證",
28104 "xloc": [
28097 - "default.handlebars->25->1639"
28105 + "default.handlebars->25->1642"
28106 ]
28107 },
28108 {
@@ -28198,7 +28206,7 @@
28206 "ru": "Версия несовместима, пожалуйста, сначала обновите установку MeshCentral",
28207 "zh-chs": "版本不兼容,请先升级您的MeshCentral安装",
28208 "xloc": [
28201 - "default.handlebars->25->1784"
28209 + "default.handlebars->25->1787"
28210 ]
28211 },
28212 {
@@ -28266,8 +28274,8 @@
28274 "ru": "Просмотр журнала изменений",
28275 "zh-chs": "查看变更日志",
28276 "xloc": [
28269 - "default.handlebars->25->1787",
28270 - "default.handlebars->25->1789"
28277 + "default.handlebars->25->1790",
28278 + "default.handlebars->25->1792"
28279 ]
28280 },
28281 {
@@ -28318,7 +28326,7 @@
28326 "ru": "Посмотреть примечания об этом пользователе",
28327 "zh-chs": "查看有關此用戶的註釋",
28328 "xloc": [
28321 - "default.handlebars->25->1619"
28329 + "default.handlebars->25->1622"
28330 ]
28331 },
28332 {
@@ -28525,8 +28533,8 @@
28533 "ru": "Веб-сервер",
28534 "zh-chs": "網絡服務器",
28535 "xloc": [
28528 - "default.handlebars->25->1773",
28529 - "default.handlebars->25->1774"
28536 + "default.handlebars->25->1776",
28537 + "default.handlebars->25->1777"
28538 ]
28539 },
28540 {
@@ -28543,7 +28551,7 @@
28551 "ru": "Запросы веб-сервера",
28552 "zh-chs": "Web服務器請求",
28553 "xloc": [
28546 - "default.handlebars->25->1775"
28554 + "default.handlebars->25->1778"
28555 ]
28556 },
28557 {
@@ -28560,7 +28568,7 @@
28568 "ru": "Ретранслятор Web Socket",
28569 "zh-chs": "Web套接字中繼",
28570 "xloc": [
28563 - "default.handlebars->25->1776"
28571 + "default.handlebars->25->1779"
28572 ]
28573 },
28574 {
@@ -28665,7 +28673,7 @@
28673 "ru": "Будет изменено при следующем входе в систему.",
28674 "zh-chs": "下次登錄時將更改。",
28675 "xloc": [
28668 - "default.handlebars->25->1591"
28676 + "default.handlebars->25->1594"
28677 ]
28678 },
28679 {
@@ -29618,7 +29626,7 @@
29626 "ru": "\\\\'",
29627 "zh-chs": "\\\\'",
29628 "xloc": [
29621 - "default.handlebars->25->1785"
29629 + "default.handlebars->25->1788"
29630 ]
29631 },
29632 {
@@ -29893,7 +29901,7 @@
29901 "ru": "свободно",
29902 "zh-chs": "自由",
29903 "xloc": [
29896 - "default.handlebars->25->1748"
29904 + "default.handlebars->25->1751"
29905 ]
29906 },
29907 {
@@ -30263,7 +30271,7 @@
30271 "ru": "servertrace.csv",
30272 "zh-chs": "servertrace.csv",
30273 "xloc": [
30266 - "default.handlebars->25->1783"
30274 + "default.handlebars->25->1786"
30275 ]
30276 },
30277 {
@@ -30320,7 +30328,7 @@
30328 "ru": "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss",
30329 "zh-chs": "時間,conn.agent,conn.users,conn.usersessions,conn.relaysession,conn.intelamt,mem.external,mem.heapused,mem.heaptotal,mem.rss",
30330 "xloc": [
30323 - "default.handlebars->25->1761"
30331 + "default.handlebars->25->1764"
30332 ]
30333 },
30334 {
@@ -30337,7 +30345,7 @@
30345 "ru": "time, source, message",
30346 "zh-chs": "時間,來源,訊息",
30347 "xloc": [
30340 - "default.handlebars->25->1782"
30348 + "default.handlebars->25->1785"
30349 ]
30350 },
30351 {
@@ -30368,7 +30376,7 @@
30376 "ru": "всего",
30377 "zh-chs": "總",
30378 "xloc": [
30371 - "default.handlebars->25->1749"
30379 + "default.handlebars->25->1752"
30380 ]
30381 },
30382 {
@@ -30527,7 +30535,7 @@
30535 "zh-chs": "{0} Kb",
30536 "xloc": [
30537 "default.handlebars->25->1375",
30530 - "default.handlebars->25->1689"
30538 + "default.handlebars->25->1692"
30539 ]
30540 },
30541 {
@@ -30581,7 +30589,7 @@
30589 "ru": "{0} активных сессий",
30590 "zh-chs": "{0}個活動會話",
30591 "xloc": [
30584 - "default.handlebars->25->1631"
30592 + "default.handlebars->25->1634"
30593 ]
30594 },
30595 {
@@ -30617,7 +30625,7 @@
30625 "xloc": [
30626 "default-mobile.handlebars->9->119",
30627 "default.handlebars->25->1385",
30620 - "default.handlebars->25->1704"
30628 + "default.handlebars->25->1707"
30629 ]
30630 },
30631 {
@@ -30675,7 +30683,7 @@
30683 "ru": "{0} групп",
30684 "zh-chs": "{0}個群組",
30685 "xloc": [
30678 - "default.handlebars->25->1596"
30686 + "default.handlebars->25->1599"
30687 ]
30688 },
30689 {
@@ -31255,4 +31263,4 @@
31263 ]
31264 }
31265 ]
31258 -}
31266 +}
\ No newline at end of file
views/default.handlebars
+76 -32
@@ -2407,7 +2407,7 @@
2407 }
2408 case 'createmesh': {
2409 // A new mesh was created
2410 - if ((meshes[message.event.meshid] == null) && ((userinfo.manageAllDeviceGroups) || (message.event.links[userinfo._id] != null))) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some.
2410 + if ((meshes[message.event.meshid] == null) && ((serverinfo.manageAllDeviceGroups) || (message.event.links[userinfo._id] != null))) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some.
2411 meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links };
2412 masterUpdate(4 + 128 + 8192 + 16384);
2413 meshserver.send({ action: 'files' });
@@ -2873,8 +2873,10 @@
2873 go(xviewmode);
2874 goBackStack.push(4);
2875 } else if (args.gotougrp != null) {
2876 - if ((usergroups == null) || usergroups['ugrp/' + domain + '/' + args.gotougrp] == null) return; // This user group is not loaded yet
2877 - gotoUserGroup('ugrp/' + domain + '/' + args.gotougrp);
2876 + var xusergrpid = args.gotougrp;
2877 + if (args.gotougrp.indexOf('/') < 0) { xusergrpid = 'ugrp/' + domain + '/' + args.gotougrp; }
2878 + if ((usergroups == null) || usergroups[xusergrpid] == null) return; // This user group is not loaded yet
2879 + gotoUserGroup(xusergrpid);
2880 go(xviewmode);
2881 goBackStack.push(50);
2882 } else if (!isNaN(xviewmode)) {
@@ -5300,7 +5302,10 @@
5302 x += '<a href=# onclick="return p20showAddMeshUserDialog(5)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add User" + '</a>';
5303 if (usergroups != null) {
5304 var userGroupCount = 0, newUserGroup = false;
5303 - for (var i in usergroups) { userGroupCount++; if ((currentNode.links == null) || (currentNode.links[i] == null)) { newUserGroup = true; } }
5305 + for (var i in usergroups) {
5306 + if (usergroups[i]._id.split('/')[1] != nodeid.split('/')[1]) continue;
5307 + userGroupCount++; if ((currentNode.links == null) || (currentNode.links[i] == null)) { newUserGroup = true; }
5308 + }
5309 if ((userGroupCount > 0) && (newUserGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(6)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add User Group" + '</a>'; }
5310 }
5311 }
@@ -8671,7 +8676,11 @@
8676 x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Users" + '</a>';
8677 if (usergroups != null) {
8678 var userGroupCount = 0, newUserGroup = false;
8674 - for (var i in usergroups) { userGroupCount++; if ((currentMesh.links == null) || (currentMesh.links[i] == null)) { newUserGroup = true; } }
8679 + for (var i in usergroups) {
8680 + if (usergroups[i]._id.split('/')[1] != currentMesh._id.split('/')[1]) continue;
8681 + userGroupCount++;
8682 + if ((currentMesh.links == null) || (currentMesh.links[i] == null)) { newUserGroup = true; }
8683 + }
8684 if ((userGroupCount > 0) && (newUserGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(2)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add User Group" + '</a>'; }
8685 }
8686 }
@@ -8914,6 +8923,7 @@
8923 }
8924
8925 function p20showAddMeshUserDialog(userid, selected) {
8926 + console.log('p20showAddMeshUserDialog', userid, selected);
8927 if (xxdialogMode) return false;
8928 var x = '';
8929 if ((userid == null) || (userid == 5)) {
@@ -8939,14 +8949,20 @@
8949 if (usergroups == null) return;
8950 var y = '';
8951 var ousergroups = getOrderedList(usergroups, 'name');
8942 - for (var i in ousergroups) { if ((currentMesh.links == null) || (currentMesh.links[ousergroups[i]._id] == null)) { y += '<option value=' + encodeURIComponentEx(ousergroups[i]._id) + '>' + EscapeHtml(ousergroups[i].name) + '</option>'; } }
8952 + for (var i in ousergroups) {
8953 + if (currentMesh._id.split('/')[1] != ousergroups[i]._id.split('/')[1]) continue;
8954 + if ((currentMesh.links == null) || (currentMesh.links[ousergroups[i]._id] == null)) { y += '<option value=' + encodeURIComponentEx(ousergroups[i]._id) + '>' + EscapeHtml(ousergroups[i].name) + '</option>'; }
8955 + }
8956 x += addHtmlValue("User Group", '<div style=width:230px;margin:0;padding:0><select onchange=p20validateAddMeshUserDialog() id=dp2groupid style=width:100%>' + y + '</select></div>');
8957 } else if (userid == 6) {
8958 if (usergroups == null) return;
8959 var y = '';
8960 if (selected == null) {
8961 var ousergroups = getOrderedList(usergroups, 'name');
8949 - for (var i in ousergroups) { if ((currentNode.links == null) || (currentNode.links[ousergroups[i]._id] == null)) { y += '<option value=' + encodeURIComponentEx(ousergroups[i]._id) + '>' + EscapeHtml(ousergroups[i].name) + '</option>'; } }
8962 + for (var i in ousergroups) {
8963 + if (currentNode._id.split('/')[1] != ousergroups[i]._id.split('/')[1]) continue;
8964 + if ((currentNode.links == null) || (currentNode.links[ousergroups[i]._id] == null)) { y += '<option value=' + encodeURIComponentEx(ousergroups[i]._id) + '>' + EscapeHtml(ousergroups[i].name) + '</option>'; }
8965 + }
8966 } else {
8967 y += '<option value=' + selected + '>' + EscapeHtml(usergroups[decodeURIComponent(selected)].name) + '</option>';
8968 }
@@ -9149,7 +9165,10 @@
9165 var lastuser = xusers[xusers.length - 1].trim(), lastuserl = lastuser.toLowerCase(), matchingUsers = [];
9166 if (lastuser.length > 0) {
9167 for (var i in users) {
9152 - if (users[i].name === lastuser) { exactMatch = true; break; }
9168 + var userSplit = users[i]._id.split('/');
9169 + if ((currentMesh != null) && (currentMesh.domain != userSplit[1])) continue;
9170 + if ((currentNode != null) && (currentNode.domain != userSplit[1])) continue;
9171 + if (userSplit[2] === lastuserl) { exactMatch = true; break; }
9172 if (users[i].name.toLowerCase().indexOf(lastuserl) >= 0) { matchingUsers.push([users[i]._id, users[i].name]); if (matchingUsers.length >= 8) break; }
9173 }
9174 if ((exactMatch == false) && (matchingUsers.length > 0)) {
@@ -10075,7 +10094,7 @@
10094 }
10095
10096 // If we are a cross-domain administrator, add the domain.
10078 - if ((userinfo.crossDomain != null)) {
10097 + if ((serverinfo.crossDomain != null)) {
10098 var userdomain = user._id.split('/')[1];
10099 if (userdomain != '') { username += ', <span style=color:#26F>' + userdomain + '</span>'; }
10100 }
@@ -10297,9 +10316,9 @@
10316 if (xxdialogMode) return;
10317 var x = '';
10318
10300 - if (userinfo.crossDomain) {
10319 + if (serverinfo.crossDomain) {
10320 var y = '<select style=width:240px id=p4domain>';
10302 - for (var i in userinfo.crossDomain) { y += '<option value=' + i + '>' + ((userinfo.crossDomain[i] == '')?"Default":EscapeHtml(userinfo.crossDomain[i])) + '</option>'; }
10321 + for (var i in serverinfo.crossDomain) { y += '<option value=' + i + '>' + ((serverinfo.crossDomain[i] == '')?"Default":EscapeHtml(serverinfo.crossDomain[i])) + '</option>'; }
10322 y += '</select>';
10323 x += addHtmlValue("Domain", y);
10324 }
@@ -10361,7 +10380,7 @@
10380 x.emailVerified = Q('p4verifiedEmail').checked;
10381 x.emailInvitation = Q('p4invitationEmail').checked;
10382 }
10364 - if (userinfo.crossDomain) { x.domain = userinfo.crossDomain[parseInt(Q('p4domain').value)]; }
10383 + if (serverinfo.crossDomain) { x.domain = serverinfo.crossDomain[parseInt(Q('p4domain').value)]; }
10384 meshserver.send(x);
10385 }
10386
@@ -10522,12 +10541,20 @@
10541 function addUserGroupHtml(group) {
10542 var usercount = 0, meshcount = 0, devicecount = 0;
10543 if (group.links) { for (var i in group.links) { if (i.startsWith('user/')) { usercount++; } if (i.startsWith('mesh/')) { meshcount++; } if (i.startsWith('node/')) { devicecount++; } } }
10544 +
10545 + // Group name, if we are a cross-domain administrator, add the domain.
10546 + var name = EscapeHtml(group.name);
10547 + if ((serverinfo.crossDomain != null)) {
10548 + var grpdomain = group._id.split('/')[1];
10549 + if (grpdomain != '') { name += ', <span style=color:#26F>' + EscapeHtml(grpdomain) + '</span>'; }
10550 + }
10551 +
10552 var x = '<tr tabindex=0 onmouseover=userMouseHover2(this,1) onmouseout=userMouseHover2(this,0) onkeypress="if (event.key==\'Enter\') gotoUserGroup(\'' + encodeURIComponentEx(group._id) + '\')"><td style=cursor:pointer>';
10553 x += '<div class=bar style=width:100%>';
10554 x += '<div class=baricon><input class=UserGroupCheckbox value=' + encodeURIComponentEx(group._id) + ' onclick=p50updateInfo() type=checkbox></div>';
10555 x += '<div class=baricon onclick=gotoUserGroup("' + encodeURIComponentEx(group._id) + '")><div class=m4></div></div>';
10556 x += '<div class=g1 onclick=gotoUserGroup("' + encodeURIComponentEx(group._id) + '")></div><div class=g2 onclick=gotoUserGroup("' + encodeURIComponentEx(group._id) + '")></div>';
10530 - x += '<div onclick=gotoUserGroup("' + encodeURIComponentEx(group._id) + '")><span style=font-size:16px>' + group.name + '</span></div></div><td style=text-align:center>' + usercount + '<td style=text-align:center>' + meshcount + '<td style=text-align:center>' + devicecount;
10557 + x += '<div onclick=gotoUserGroup("' + encodeURIComponentEx(group._id) + '")><span style=font-size:16px>' + name + '</span></div></div><td style=text-align:center>' + usercount + '<td style=text-align:center>' + meshcount + '<td style=text-align:center>' + devicecount;
10558 return x;
10559 }
10560
@@ -10586,6 +10613,12 @@
10613 if (usergroups) { for (var i in usergroups) { y += '<option value=' + encodeURIComponentEx(i) + '>' + EscapeHtml(usergroups[i].name) + '</option>'; } }
10614 x += addHtmlValue("User Group", '<div style=width:230px;margin:0;padding:0><select id=dp4groupid style=width:100%>' + y + '</select></div>');
10615 }
10616 + if ((mode == 1) && (serverinfo.crossDomain)) {
10617 + var y = '<select style=width:240px id=p4domain>';
10618 + for (var i in serverinfo.crossDomain) { y += '<option value=' + i + '>' + ((serverinfo.crossDomain[i] == '')?"Default":EscapeHtml(serverinfo.crossDomain[i])) + '</option>'; }
10619 + y += '</select>';
10620 + x += addHtmlValue("Domain", y);
10621 + }
10622 x += addHtmlValue("Name", '<input id=p4name maxlength=64 onchange=showCreateUserGroupDialogValidate() onkeyup=showCreateUserGroupDialogValidate() />');
10623 x += addHtmlValue("Description", '<textarea id=p4desc value="" style=width:230px;height:60px;resize:none maxlength=1024 /></textarea>');
10624 setDialogMode(2, (mode == 1)?"Create User Group":"Duplicate User Group", 3, showCreateUserGroupDialogEx, x, mode);
@@ -10598,6 +10631,7 @@
10631 function showCreateUserGroupDialogEx(b, mode) {
10632 var x = { action: 'createusergroup', name: Q('p4name').value, desc: Q('p4desc').value };
10633 if (mode == 2) { x.clone = decodeURIComponent(Q('dp4groupid').value); }
10634 + if ((mode == 1) && (serverinfo.crossDomain)) { x.domain = serverinfo.crossDomain[parseInt(Q('p4domain').value)]; }
10635 meshserver.send(x);
10636 }
10637
@@ -10635,6 +10669,8 @@
10669 } else {
10670 x += addDeviceAttribute("Description", desc);
10671 }
10672 +
10673 + if (serverinfo.crossDomain != null) { x += addDeviceAttribute("Group Identifier", group._id); }
10674 x += addDeviceAttribute("Users", usercount);
10675 x += addDeviceAttribute("Device Groups", meshcount);
10676 x += addDeviceAttribute("Devices", devicecount);
@@ -10681,7 +10717,7 @@
10717 // Display all device groups for this user group
10718 count = 1;
10719 var deviceGroupCount = 0, newDeviceGroup = false;
10684 - for (var i in meshes) { deviceGroupCount++; if ((currentUserGroup.links == null) || (currentUserGroup.links[i] == null)) { newDeviceGroup = true; } }
10720 + for (var i in meshes) { if (currentUserGroup._id.split('/')[1] != meshes[i]._id.split('/')[1]) continue; deviceGroupCount++; if ((currentUserGroup.links == null) || (currentUserGroup.links[i] == null)) { newDeviceGroup = true; } }
10721 if ((deviceGroupCount > 0) && (newDeviceGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(3)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device Group" + '</a>'; }
10722 x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Device Groups" + '</th><th scope=col style=text-align:left></th></tr>';
10723 if (currentUserGroup.links) {
@@ -10705,7 +10741,8 @@
10741
10742 // Display all devices for this user group
10743 count = 1;
10708 - x += '<br /><a href=# onclick="return p20showAddMeshUserDialog(7)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device" + '</a>';
10744 + x += '<br />';
10745 + if (currentUserGroup._id.split('/')[1] == userinfo._id.split('/')[1]) { x += '<a href=# onclick="return p20showAddMeshUserDialog(7)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device" + '</a>'; }
10746 x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Devices" + '</th><th scope=col style=text-align:left></th></tr>';
10747 if (currentUserGroup.links) {
10748 var onodes = [];
@@ -10735,7 +10772,7 @@
10772 // Change the URL
10773 var urlviewmode = '';
10774 if (((features & 0x10000000) == 0) && (xxcurrentView >= 51) && (xxcurrentView <= 59) && (currentUserGroup != null)) {
10738 - urlviewmode = '?viewmode=' + xxcurrentView + '&gotougrp=' + currentUserGroup._id.split('/')[2];
10775 + urlviewmode = '?viewmode=' + xxcurrentView + '&gotougrp=' + ((serverinfo.crossDomain)?currentUserGroup._id:currentUserGroup._id.split('/')[2]);
10776 for (var i in urlargs) { urlviewmode += ('&' + i + '=' + urlargs[i]); }
10777 try { window.history.replaceState({}, document.title, window.location.pathname + urlviewmode); } catch (ex) { }
10778 }
@@ -10839,9 +10876,7 @@
10876 }
10877
10878 function p51validateAddUserDialog() {
10842 - var meshrights = GetMeshRights(currentMesh);
10879 var ok = true;
10844 -
10880 if (Q('dp51username')) {
10881 var xusers = Q('dp51username').value.split(',');
10882 for (var i in xusers) {
@@ -10855,8 +10890,9 @@
10890 var lastuser = xusers[xusers.length - 1].trim(), lastuserl = lastuser.toLowerCase(), matchingUsers = [];
10891 if (lastuser.length > 0) {
10892 for (var i in users) {
10858 - if (users[i].name === lastuser) { exactMatch = true; break; }
10859 - if (users[i].name.toLowerCase().indexOf(lastuserl) >= 0) { matchingUsers.push([users[i]._id, users[i].name]); if (matchingUsers.length >= 8) break; }
10893 + var userSplit = users[i]._id.split('/');
10894 + if ((currentUserGroup.domain == userSplit[1]) && (userSplit[2] === lastuserl)) { exactMatch = true; break; }
10895 + if ((users[i].name.toLowerCase().indexOf(lastuserl) >= 0) && (currentUserGroup.domain == userSplit[1])) { matchingUsers.push([users[i]._id, users[i].name]); if (matchingUsers.length >= 8) break; }
10896 }
10897 if ((exactMatch == false) && (matchingUsers.length > 0)) {
10898 var x = '';
@@ -10934,7 +10970,7 @@
10970 var email = user.email?EscapeHtml(user.email):'<i>' + "Not set" + '</i>', everify = '';
10971 if (serverinfo.emailcheck) { everify = ((user.emailVerified == true) ? '<b style=color:green;cursor:pointer title="' + "Email is verified" + '">&#x2713</b> ' : '<b style=color:red;cursor:pointer title="' + "Email not verified" + '">&#x2717;</b> '); }
10972
10937 - if (userinfo.crossDomain) {
10973 + if (serverinfo.crossDomain) {
10974 x += addDeviceAttribute("User Identifier", EscapeHtml(user._id));
10975 } else {
10976 if (user.name.toLowerCase() != user._id.split('/')[2]) { x += addDeviceAttribute("User Identifier", EscapeHtml(user._id.split('/')[2])); }
@@ -11039,7 +11075,7 @@
11075 // Change the URL
11076 var urlviewmode = '';
11077 if (((features & 0x10000000) == 0) && (xxcurrentView >= 30) && (xxcurrentView <= 39) && (currentUser != null)) {
11042 - urlviewmode = '?viewmode=' + xxcurrentView + '&gotouser=' + ((userinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]);
11078 + urlviewmode = '?viewmode=' + xxcurrentView + '&gotouser=' + ((serverinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]);
11079 for (var i in urlargs) { urlviewmode += ('&' + i + '=' + urlargs[i]); }
11080 try { window.history.replaceState({}, document.title, window.location.pathname + urlviewmode); } catch (ex) { }
11081 }
@@ -11150,7 +11186,7 @@
11186
11187 // Display common device groups
11188 var deviceGroupCount = 0, newDeviceGroup = false;
11153 - for (var i in meshes) { deviceGroupCount++; if ((currentUser.links == null) || (currentUser.links[i] == null)) { newDeviceGroup = true; } }
11189 + for (var i in meshes) { if (meshes[i]._id.split('/')[1] != currentUser._id.split('/')[1]) continue; deviceGroupCount++; if ((currentUser.links == null) || (currentUser.links[i] == null)) { newDeviceGroup = true; } }
11190 if ((deviceGroupCount > 0) && (newDeviceGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(1)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device Group" + '</a>'; }
11191 x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Device Groups" + '</th><th scope=col style=text-align:left></th></tr>';
11192 if (currentUser.links) {
@@ -11179,7 +11215,11 @@
11215 x += '<br />';
11216 if ((userinfo.siteadmin & 256) != 0) {
11217 var userGroupCount = 0, newUserGroup = false;
11182 - for (var i in usergroups) { userGroupCount++; if ((currentUser.links == null) || (currentUser.links[i] == null)) { newUserGroup = true; } }
11218 + for (var i in usergroups) {
11219 + if (usergroups[i]._id.split('/')[1] != currentUser._id.split('/')[1]) continue;
11220 + userGroupCount++;
11221 + if ((currentUser.links == null) || (currentUser.links[i] == null)) { newUserGroup = true; }
11222 + }
11223 if ((userGroupCount > 0) && (newUserGroup)) { x += '<a href=# onclick="return p30showAddUserGroupDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add User Group" + '</a>'; }
11224 }
11225 x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "User Group Memberships" + '</th><th scope=col style=text-align:left></th></tr>';
@@ -11204,7 +11244,8 @@
11244
11245 // Display common devices
11246 count = 1;
11207 - x += '<br /><a href=# onclick="return p20showAddMeshUserDialog(4)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device" + '</a>';
11247 + x += '<br />';
11248 + if (currentUser._id.split('/')[1] == userinfo._id.split('/')[1]) { x += '<a href=# onclick="return p20showAddMeshUserDialog(4)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device" + '</a>'; }
11249 x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Devices" + '</th><th scope=col style=text-align:left></th></tr>';
11250 if (currentUser.links) {
11251 // Sort the list of devices to display
@@ -11262,7 +11303,10 @@
11303 function p30showAddUserGroupDialog() {
11304 if (xxdialogMode || (usergroups == null)) return;
11305 var y = '';
11265 - for (var i in usergroups) { if ((currentUser.links == null) || (currentUser.links[i] == null)) { y += '<option value=' + encodeURIComponentEx(i) + '>' + EscapeHtml(usergroups[i].name) + '</option>'; } }
11306 + for (var i in usergroups) {
11307 + if (usergroups[i]._id.split('/')[1] != currentUser._id.split('/')[1]) continue;
11308 + if ((currentUser.links == null) || (currentUser.links[i] == null)) { y += '<option value=' + encodeURIComponentEx(i) + '>' + EscapeHtml(usergroups[i].name) + '</option>'; }
11309 + }
11310 var x = addHtmlValue("User Group", '<div style=width:230px;margin:0;padding:0><select id=dp2groupid style=width:100%>' + y + '</select></div>');
11311 setDialogMode(2, "Add Membership", 3, p30showAddUserGroupDialogEx, x);
11312 Q('dp2groupid').focus();
@@ -12027,9 +12071,9 @@
12071 } else if ((x >= 20) && (x <= 29)) {
12072 if (currentMesh) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotomesh=' + currentMesh._id.split('/')[2] + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentMesh._id); }
12073 } else if ((x >= 30) && (x <= 39)) {
12030 - if (currentUser) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotouser=' + ((userinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]) + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUser._id); }
12074 + if (currentUser) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotouser=' + ((serverinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]) + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUser._id); }
12075 } else if ((x >= 50) && (x <= 59)) {
12032 - if (currentUserGroup) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotougrp=' + currentUserGroup._id.split('/')[2] + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUserGroup._id); }
12076 + if (currentUserGroup) { window.open(window.location.origin + '{{{domainurl}}}' + '?gotougrp=' + ((serverinfo.crossDomain)?currentUserGroup._id:currentUserGroup._id.split('/')[2]) + '&viewmode=' + x + '&hide=16', 'meshcentral:' + currentUserGroup._id); }
12077 } else { // if (x < 10))
12078 window.open(window.location.origin + '{{{domainurl}}}' + '?viewmode=' + x + '&hide=0', 'meshcentral:' + x);
12079 }
@@ -12066,9 +12110,9 @@
12110 } else if ((xxcurrentView >= 20) && (xxcurrentView <= 29)) { // Device Group Link
12111 if (currentMesh != null) { urlviewmode = '?viewmode=' + xxcurrentView + '&gotomesh=' + currentMesh._id.split('/')[2]; }
12112 } else if ((xxcurrentView >= 30) && (xxcurrentView <= 39)) { // User Link
12069 - if (currentUser != null) { urlviewmode = '?viewmode=' + xxcurrentView + '&gotouser=' + ((userinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]); }
12113 + if (currentUser != null) { urlviewmode = '?viewmode=' + xxcurrentView + '&gotouser=' + ((serverinfo.crossDomain)?currentUser._id:currentUser._id.split('/')[2]); }
12114 } else if ((xxcurrentView >= 51) && (xxcurrentView <= 51)) { // User Group Link
12071 - if ((currentUserGroup != null) && (currentUserGroup._id != null)) { urlviewmode = '?viewmode=' + xxcurrentView + '&gotougrp=' + currentUserGroup._id.split('/')[2]; }
12115 + if ((currentUserGroup != null) && (currentUserGroup._id != null)) { urlviewmode = '?viewmode=' + xxcurrentView + '&gotougrp=' + ((serverinfo.crossDomain)?currentUserGroup._id:currentUserGroup._id.split('/')[2]); }
12116 } else if (xxcurrentView > 1) { urlviewmode = '?viewmode=' + xxcurrentView; }
12117 for (var i in urlargs) { urlviewmode += (((urlviewmode == '')?'?':'&') + i + '=' + urlargs[i]); }
12118 try { window.history.replaceState({}, document.title, window.location.pathname + urlviewmode); } catch (ex) { }
@@ -12344,7 +12388,7 @@
12388 if ((mesh == null) || (mesh.links == null)) { return 0; }
12389
12390 // Check if super user
12347 - if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF;
12391 + if (serverinfo.manageAllDeviceGroups) return 0xFFFFFFFF;
12392
12393 // Check device group link permission
12394 var rights = 0, r = mesh.links[userid];
@@ -12380,7 +12424,7 @@
12424 if (mesh.links[userid] != null) { return true; } // User has visilibity thru a direct link
12425
12426 // Check if user user
12383 - if (userinfo.manageAllDeviceGroups) return true;
12427 + if (serverinfo.manageAllDeviceGroups) return true;
12428
12429 // Check permissions thru user groups
12430 var user = null;