mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-11-26 16:06:33 +03:00
Code fixes & clean up.
This commit is contained in:
parent
0a6d955674
commit
7f75ae419c
76
meshuser.js
76
meshuser.js
@ -49,6 +49,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
const MESHRIGHT_CHATNOTIFY = 16384;
|
||||
const MESHRIGHT_UNINSTALL = 32768;
|
||||
const MESHRIGHT_NODESKTOP = 65536;
|
||||
const MESHRIGHT_ADMIN = 0xFFFFFFFF;
|
||||
|
||||
// Site rights
|
||||
const SITERIGHT_SERVERBACKUP = 1; // 0x00000001
|
||||
@ -61,6 +62,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
const SITERIGHT_NOMESHCMD = 128; // 0x00000080
|
||||
const SITERIGHT_USERGROUPS = 256; // 0x00000100
|
||||
const SITERIGHT_RECORDINGS = 512; // 0x00000200
|
||||
const SITERIGHT_ADMIN = 0xFFFFFFFF; // 0xFFFFFFFF
|
||||
|
||||
var obj = {};
|
||||
obj.user = user;
|
||||
@ -299,7 +301,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (id.startsWith('mesh/')) {
|
||||
// Check if we have rights to get this message. If we have limited events on this mesh, don't send the event to the user.
|
||||
var meshrights = parent.GetMeshRights(user, id);
|
||||
if ((meshrights == 0xFFFFFFFF) || ((meshrights & MESHRIGHT_LIMITEVENTS) == 0) || (ids.indexOf(user._id) >= 0)) {
|
||||
if ((meshrights === MESHRIGHT_ADMIN) || ((meshrights & MESHRIGHT_LIMITEVENTS) == 0) || (ids.indexOf(user._id) >= 0)) {
|
||||
// We have the device group rights to see this event or we are directly targetted by the event
|
||||
ws.send(JSON.stringify({ action: 'event', event: event }));
|
||||
} else {
|
||||
@ -401,7 +403,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = args.redirport; }
|
||||
if (typeof domain.userconsentflags == 'number') { serverinfo.consent = domain.userconsentflags; }
|
||||
if ((typeof domain.usersessionidletimeout == 'number') && (domain.usersessionidletimeout > 0)) { serverinfo.timeout = (domain.usersessionidletimeout * 60 * 1000); }
|
||||
if (user.siteadmin == 0xFFFFFFFF) {
|
||||
if (user.siteadmin === SITERIGHT_ADMIN) {
|
||||
if (parent.parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) { serverinfo.manageAllDeviceGroups = true; }
|
||||
if (obj.crossDomain === true) { serverinfo.crossDomain = []; for (var i in parent.parent.config.domains) { serverinfo.crossDomain.push(i); } }
|
||||
}
|
||||
@ -412,7 +414,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Send user information to web socket, this is the first thing we send
|
||||
try { ws.send(JSON.stringify({ action: 'userinfo', userinfo: parent.CloneSafeUser(parent.users[user._id]) })); } catch (ex) { }
|
||||
|
||||
if (user.siteadmin == 0xFFFFFFFF) {
|
||||
if (user.siteadmin === SITERIGHT_ADMIN) {
|
||||
// Send server tracing information
|
||||
try { ws.send(JSON.stringify({ action: 'traceinfo', traceSources: parent.parent.debugRemoteSources })); } catch (ex) { }
|
||||
|
||||
@ -765,7 +767,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
case 'serverconsole':
|
||||
{
|
||||
// This is a server console message, only process this if full administrator
|
||||
if (user.siteadmin != 0xFFFFFFFF) break;
|
||||
if (user.siteadmin != SITERIGHT_ADMIN) break;
|
||||
|
||||
var r = '';
|
||||
var cmdargs = splitArgs(command.value);
|
||||
@ -1235,7 +1237,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
var limit = 10000;
|
||||
if (common.validateInt(command.limit, 1, 60000) == true) { limit = command.limit; }
|
||||
|
||||
if (((rights & MESHRIGHT_LIMITEVENTS) != 0) && (rights != 0xFFFFFFFF)) {
|
||||
if (((rights & MESHRIGHT_LIMITEVENTS) != 0) && (rights != MESHRIGHT_ADMIN)) {
|
||||
// Send the list of most recent events for this nodeid that only apply to us, up to 'limit' count
|
||||
db.GetNodeEventsSelfWithLimit(node._id, domain.id, user._id, limit, function (err, docs) {
|
||||
if (err != null) return;
|
||||
@ -1260,7 +1262,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// TODO (UserGroups)
|
||||
|
||||
// Remove MeshID's that we do not have rights to see events for
|
||||
for (var link in obj.user.links) { if (((obj.user.links[link].rights & MESHRIGHT_LIMITEVENTS) != 0) && ((obj.user.links[link].rights != 0xFFFFFFFF))) { exGroupFilter2.push(link); } }
|
||||
for (var link in obj.user.links) { if (((obj.user.links[link].rights & MESHRIGHT_LIMITEVENTS) != 0) && ((obj.user.links[link].rights != MESHRIGHT_ADMIN))) { exGroupFilter2.push(link); } }
|
||||
for (var i in filter2) { if (exGroupFilter2.indexOf(filter2[i]) == -1) { filter.push(filter2[i]); } }
|
||||
|
||||
if ((command.limit == null) || (typeof command.limit != 'number')) {
|
||||
@ -1467,7 +1469,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
deluser = parent.users[deluserid];
|
||||
if (deluser == null) { err = 'User does not exists'; }
|
||||
else if ((obj.crossDomain !== true) && ((delusersplit.length != 3) || (delusersplit[1] != domain.id))) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
|
||||
else if ((deluser.siteadmin == 0xFFFFFFFF) && (user.siteadmin != 0xFFFFFFFF)) { err = 'Permission denied'; } // Need full admin to remote another administrator
|
||||
else if ((deluser.siteadmin === SITERIGHT_ADMIN) && (user.siteadmin != SITERIGHT_ADMIN)) { err = 'Permission denied'; } // Need full admin to remote another administrator
|
||||
else if ((obj.crossDomain !== true) && (user.groups != null) && (user.groups.length > 0) && ((deluser.groups == null) || (findOne(deluser.groups, user.groups) == false))) { err = 'Invalid user group'; } // Can only perform this operation on other users of our group.
|
||||
}
|
||||
} catch (ex) { err = 'Validation exception: ' + ex; }
|
||||
@ -1702,7 +1704,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
newuserid = 'user/' + newuserdomain.id + '/' + command.username.toLowerCase();
|
||||
if (command.siteadmin != null) {
|
||||
if ((typeof command.siteadmin != 'number') || (Number.isInteger(command.siteadmin) == false)) { err = 'Invalid site permissions'; } // Check permissions
|
||||
else if ((user.siteadmin != 0xFFFFFFFF) && ((command.siteadmin & (0xFFFFFFFF - 224)) != 0)) { err = 'Invalid site permissions'; }
|
||||
else if ((user.siteadmin != SITERIGHT_ADMIN) && ((command.siteadmin & (SITERIGHT_ADMIN - 224)) != 0)) { err = 'Invalid site permissions'; }
|
||||
}
|
||||
if (parent.users[newuserid]) { err = 'User already exists'; } // Account already exists
|
||||
else if ((newuserdomain.auth == 'sspi') || (newuserdomain.auth == 'ldap')) { err = 'Unable to add user in this mode'; }
|
||||
@ -1818,10 +1820,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
change = 0;
|
||||
if (chguser) {
|
||||
// If the target user is admin and we are not admin, no changes can be made.
|
||||
if ((chguser.siteadmin == 0xFFFFFFFF) && (user.siteadmin != 0xFFFFFFFF)) return;
|
||||
if ((chguser.siteadmin === SITERIGHT_ADMIN) && (user.siteadmin != SITERIGHT_ADMIN)) return;
|
||||
|
||||
// Can only perform this operation on other users of our group.
|
||||
if (user.siteadmin != 0xFFFFFFFF) {
|
||||
if (user.siteadmin != SITERIGHT_ADMIN) {
|
||||
if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) return;
|
||||
}
|
||||
|
||||
@ -1845,7 +1847,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Site admins can change any server rights, user managers can only change AccountLock, NoMeshCmd and NoNewGroups
|
||||
if (common.validateInt(command.siteadmin) && (chguser._id !== user._id) && (chguser.siteadmin != command.siteadmin)) { // We can't change our own siteadmin permissions.
|
||||
var chgusersiteadmin = chguser.siteadmin ? chguser.siteadmin : 0;
|
||||
if (user.siteadmin == 0xFFFFFFFF) { chguser.siteadmin = command.siteadmin; change = 1; }
|
||||
if (user.siteadmin === SITERIGHT_ADMIN) { chguser.siteadmin = command.siteadmin; change = 1; }
|
||||
else if (user.siteadmin & 2) {
|
||||
var mask = 0xFFFFFF1D; // Mask: 2 (User Mangement) + 32 (Account locked) + 64 (No New Groups) + 128 (No Tools)
|
||||
if ((user.siteadmin & 256) != 0) { mask -= 256; } // Mask: Manage User Groups
|
||||
@ -1856,7 +1858,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
// When sending a notification about a group change, we need to send to all the previous and new groups.
|
||||
var allTargetGroups = chguser.groups;
|
||||
if ((Array.isArray(command.groups)) && ((user._id != command.id) || (user.siteadmin == 0xFFFFFFFF))) {
|
||||
if ((Array.isArray(command.groups)) && ((user._id != command.id) || (user.siteadmin === SITERIGHT_ADMIN))) {
|
||||
if (command.groups.length == 0) {
|
||||
// Remove the user groups
|
||||
if (chguser.groups != null) { delete chguser.groups; change = 1; }
|
||||
@ -1891,7 +1893,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
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.
|
||||
parent.parent.DispatchEvent(targets, obj, event);
|
||||
}
|
||||
if ((chguser.siteadmin) && (chguser.siteadmin != 0xFFFFFFFF) && (chguser.siteadmin & 32)) {
|
||||
if ((chguser.siteadmin) && (chguser.siteadmin !== SITERIGHT_ADMIN) && (chguser.siteadmin & 32)) {
|
||||
// If the user is locked out of this account, disconnect now
|
||||
parent.parent.DispatchEvent([chguser._id], obj, 'close'); // Disconnect all this user's sessions
|
||||
}
|
||||
@ -1934,9 +1936,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
else if (parent.userGroups[command.clone] == null) { err = "Invalid clone groupid"; }
|
||||
}
|
||||
|
||||
// Get new user group domain
|
||||
ugrpdomain = parent.parent.config.domains[clonesplit[1]];
|
||||
if (ugrpdomain == null) { err = "Invalid domain"; }
|
||||
if (err == null) {
|
||||
// Get new user group domain
|
||||
ugrpdomain = parent.parent.config.domains[clonesplit[1]];
|
||||
if (ugrpdomain == null) { err = "Invalid domain"; }
|
||||
}
|
||||
} else {
|
||||
// Get new user group domain
|
||||
ugrpdomain = domain;
|
||||
@ -1945,7 +1949,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
|
||||
// In some situations, we need a verified email address to create a device group.
|
||||
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.
|
||||
if ((err == null) && (parent.parent.mailserver != null) && (ugrpdomain.auth != 'sspi') && (ugrpdomain.auth != 'ldap') && (user.emailVerified !== true) && (user.siteadmin != SITERIGHT_ADMIN)) { err = "Email verification required"; } // User must verify it's email first.
|
||||
} catch (ex) { err = "Validation exception: " + ex; }
|
||||
|
||||
// Handle any errors
|
||||
@ -2355,7 +2359,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
var chguser = parent.users[command.userid];
|
||||
if (chguser) {
|
||||
// If we are not full administrator, we can't change anything on a different full administrator
|
||||
if ((user.siteadmin != 0xFFFFFFFF) & (chguser.siteadmin == 0xFFFFFFFF)) break;
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) & (chguser.siteadmin === SITERIGHT_ADMIN)) break;
|
||||
|
||||
// Can only perform this operation on other users of our group.
|
||||
if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) break;
|
||||
@ -2499,10 +2503,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
var err = null;
|
||||
try {
|
||||
// Check if we have new group restriction
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 64) != 0)) { err = 'Permission denied'; }
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) && ((user.siteadmin & 64) != 0)) { err = 'Permission denied'; }
|
||||
|
||||
// In some situations, we need a verified email address to create a device group.
|
||||
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.
|
||||
else if ((parent.parent.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap') && (user.emailVerified !== true) && (user.siteadmin != SITERIGHT_ADMIN)) { err = 'Email verification required'; } // User must verify it's email first.
|
||||
|
||||
// Create mesh
|
||||
else if (common.validateString(command.meshname, 1, 64) == false) { err = 'Invalid group name'; } // Meshname is between 1 and 64 characters
|
||||
@ -2582,7 +2586,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
// Check if this user has rights to do this
|
||||
var err = null;
|
||||
if (parent.GetMeshRights(user, mesh) != 0xFFFFFFFF) { err = 'Access denied'; }
|
||||
if (parent.GetMeshRights(user, mesh) != MESHRIGHT_ADMIN) { err = 'Access denied'; }
|
||||
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) { err = 'Invalid group'; } // Invalid domain, operation only valid for current domain
|
||||
|
||||
// Handle any errors
|
||||
@ -2760,14 +2764,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
var targetMeshRights = 0;
|
||||
if ((newuser.links != null) && (newuser.links[command.meshid] != null) && (newuser.links[command.meshid].rights != null)) { targetMeshRights = newuser.links[command.meshid].rights; }
|
||||
if ((targetMeshRights == 0xFFFFFFFF) && (selfMeshRights != 0xFFFFFFFF)) { msgs.push("Can't change rights of device group administrator"); continue; } // A non-admin can't kick out an admin
|
||||
if ((targetMeshRights === MESHRIGHT_ADMIN) && (selfMeshRights != MESHRIGHT_ADMIN)) { msgs.push("Can't change rights of device group administrator"); continue; } // A non-admin can't kick out an admin
|
||||
|
||||
if (command.remove === true) {
|
||||
// Remove mesh from user or user group
|
||||
delete newuser.links[command.meshid];
|
||||
} else {
|
||||
// Adjust rights since we can't add more rights that we have outself for MESHRIGHT_MANAGEUSERS
|
||||
if ((selfMeshRights != 0xFFFFFFFF) && (command.meshadmin == 0xFFFFFFFF)) { msgs.push("Can't set device group administrator, if not administrator"); continue; }
|
||||
if ((selfMeshRights != MESHRIGHT_ADMIN) && (command.meshadmin == MESHRIGHT_ADMIN)) { msgs.push("Can't set device group administrator, if not administrator"); continue; }
|
||||
if (((selfMeshRights & 2) == 0) && ((command.meshadmin & 2) != 0) && ((targetMeshRights & 2) == 0)) { command.meshadmin -= 2; }
|
||||
|
||||
// Add mesh to user or user group
|
||||
@ -3008,7 +3012,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Remove mesh from user
|
||||
if (deluser.links != null && deluser.links[command.meshid] != null) {
|
||||
var delmeshrights = deluser.links[command.meshid].rights;
|
||||
if ((delmeshrights == 0xFFFFFFFF) && (parent.GetMeshRights(user, mesh) != 0xFFFFFFFF)) return; // A non-admin can't kick out an admin
|
||||
if ((delmeshrights == MESHRIGHT_ADMIN) && (parent.GetMeshRights(user, mesh) != MESHRIGHT_ADMIN)) return; // A non-admin can't kick out an admin
|
||||
delete deluser.links[command.meshid];
|
||||
if (deluserid.startsWith('user/')) { db.SetUser(deluser); }
|
||||
else if (deluserid.startsWith('ugrp/')) { db.Set(deluser); }
|
||||
@ -3523,7 +3527,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF))) return;
|
||||
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != SITERIGHT_ADMIN))) return;
|
||||
|
||||
if (command.type == 'default') {
|
||||
// Send the default core to the agent
|
||||
@ -3555,7 +3559,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF))) return;
|
||||
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != SITERIGHT_ADMIN))) return;
|
||||
|
||||
// Force mesh agent disconnection
|
||||
parent.forceMeshAgentDisconnect(user, domain, node._id, command.disconnectMode);
|
||||
@ -4188,7 +4192,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'traceinfo': {
|
||||
if ((user.siteadmin == 0xFFFFFFFF) && (typeof command.traceSources == 'object')) {
|
||||
if ((user.siteadmin === SITERIGHT_ADMIN) && (typeof command.traceSources == 'object')) {
|
||||
parent.parent.debugRemoteSources = command.traceSources;
|
||||
parent.parent.DispatchEvent(['*'], obj, { action: 'traceinfo', userid: user._id, username: user.name, traceSources: command.traceSources, nolog: 1, domain: domain.id });
|
||||
}
|
||||
@ -4228,7 +4232,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
// Check if this user has rights to do this
|
||||
if (rights == 0xFFFFFFFF) {
|
||||
if (rights == MESHRIGHT_ADMIN) {
|
||||
var token = parent.parent.mqttbroker.generateLogin(node.meshid, node._id);
|
||||
var r = { action: 'getmqttlogin', responseid: command.responseid, nodeid: node._id, user: token.user, pass: token.pass };
|
||||
const serverName = parent.getWebServerName(domain);
|
||||
@ -4278,7 +4282,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'distributeCore': {
|
||||
// This is only available when plugins are enabled since it could cause stress on the server
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
for (var i in command.nodes) {
|
||||
parent.sendMeshAgentCore(user, domain, command.nodes[i]._id, 'default');
|
||||
}
|
||||
@ -4286,14 +4290,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'plugins': {
|
||||
// Since plugin actions generally require a server restart, use the Full admin permission
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
parent.db.getPlugins(function(err, docs) {
|
||||
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'pluginLatestCheck': {
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
parent.parent.pluginHandler.getPluginLatest()
|
||||
.then(function(latest) {
|
||||
try { ws.send(JSON.stringify({ action: 'pluginVersionsAvailable', list: latest })); } catch (ex) { }
|
||||
@ -4301,7 +4305,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'addplugin': {
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
try {
|
||||
parent.parent.pluginHandler.getPluginConfig(command.url)
|
||||
.then(parent.parent.pluginHandler.addPlugin)
|
||||
@ -4318,7 +4322,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'installplugin': {
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
parent.parent.pluginHandler.installPlugin(command.id, command.version_only, null, function(){
|
||||
parent.db.getPlugins(function(err, docs) {
|
||||
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
||||
@ -4329,7 +4333,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'disableplugin': {
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
parent.parent.pluginHandler.disablePlugin(command.id, function(){
|
||||
parent.db.getPlugins(function(err, docs) {
|
||||
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
||||
@ -4340,7 +4344,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'removeplugin': {
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
parent.parent.pluginHandler.removePlugin(command.id, function(){
|
||||
parent.db.getPlugins(function(err, docs) {
|
||||
try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
|
||||
@ -4349,7 +4353,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'getpluginversions': {
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
|
||||
parent.parent.pluginHandler.getPluginVersions(command.id)
|
||||
.then(function (versionInfo) {
|
||||
try { ws.send(JSON.stringify({ action: 'downgradePluginVersions', info: versionInfo, error: null })); } catch (ex) { }
|
||||
|
@ -27,6 +27,7 @@ module.exports.pluginHandler = function (parent) {
|
||||
|
||||
obj.fs = require('fs');
|
||||
obj.path = require('path');
|
||||
obj.common = require('./common.js');
|
||||
obj.parent = parent;
|
||||
obj.pluginPath = obj.parent.path.join(obj.parent.datapath, 'plugins');
|
||||
obj.plugins = {};
|
||||
@ -471,7 +472,7 @@ module.exports.pluginHandler = function (parent) {
|
||||
versStr += chunk;
|
||||
});
|
||||
res.on('end', function () {
|
||||
if (versStr[0] == '{' || versStr[0] == '[') { // let's be sure we're JSON
|
||||
if ((versStr[0] == '{') || (versStr[0] == '[')) { // let's be sure we're JSON
|
||||
try {
|
||||
var vers = JSON.parse(versStr);
|
||||
var vList = [];
|
||||
@ -515,9 +516,11 @@ module.exports.pluginHandler = function (parent) {
|
||||
};
|
||||
|
||||
obj.handleAdminReq = function (req, res, user, serv) {
|
||||
if (obj.common.isAlphaNumeric(req.query.pin) !== true) { res.sendStatus(401); return; }
|
||||
var path = obj.path.join(obj.pluginPath, req.query.pin, 'views');
|
||||
if (obj.common.IsFilenameValid(path) !== true) { res.sendStatus(401); return; }
|
||||
serv.app.set('views', path);
|
||||
if (obj.plugins[req.query.pin] != null && typeof obj.plugins[req.query.pin].handleAdminReq == 'function') {
|
||||
if ((obj.plugins[req.query.pin] != null) && (typeof obj.plugins[req.query.pin].handleAdminReq == 'function')) {
|
||||
obj.plugins[req.query.pin].handleAdminReq(req, res, user);
|
||||
} else {
|
||||
res.sendStatus(401);
|
||||
@ -525,9 +528,11 @@ module.exports.pluginHandler = function (parent) {
|
||||
}
|
||||
|
||||
obj.handleAdminPostReq = function (req, res, user, serv) {
|
||||
if (obj.common.isAlphaNumeric(req.query.pin) !== true) { res.sendStatus(401); return; }
|
||||
var path = obj.path.join(obj.pluginPath, req.query.pin, 'views');
|
||||
if (obj.common.IsFilenameValid(path) !== true) { res.sendStatus(401); return; }
|
||||
serv.app.set('views', path);
|
||||
if (obj.plugins[req.query.pin] != null && typeof obj.plugins[req.query.pin].handleAdminPostReq == 'function') {
|
||||
if ((obj.plugins[req.query.pin] != null) && (typeof obj.plugins[req.query.pin].handleAdminPostReq == 'function')) {
|
||||
obj.plugins[req.query.pin].handleAdminPostReq(req, res, user);
|
||||
} else {
|
||||
res.sendStatus(401);
|
||||
|
@ -1751,7 +1751,7 @@
|
||||
var publiclink = '';
|
||||
if (publicfolder) { publiclink = ' (<a style=cursor:pointer onclick=\'p5showPublicLink("' + publicPath + '/' + f.nx + '")\'>' + "Link" + '</a>)'; }
|
||||
if (f.s > 0) { link = '<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=' + encodeURIComponent(filetreelinkpath + '/' + f.nx) + '\">' + shortname + '</a>' + publiclink; }
|
||||
h = '<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value=\'' + f.nx + '\'> <span style=float:right;padding-right:4px>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
||||
h = '<div class=filelist file=3><input file=3 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value=\'' + f.nx + '\'> <span style=float:right;padding-right:4px>' + EscapeHtml(fsize) + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
||||
}
|
||||
|
||||
if (f.t < 3) { html1 += h; } else { html2 += h; }
|
||||
@ -2378,14 +2378,14 @@
|
||||
if (node.intelamt != null) {
|
||||
var str = '';
|
||||
var provisioningStates = { 0: nobreak("Not Activated (Pre)"), 1: nobreak("Not Activated (In)"), 2: nobreak("Activated") };
|
||||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + nobreak("Unknown State") + '</i>, v' + node.intelamt.ver; } else
|
||||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + nobreak("Unknown State") + '</i>, v' + EscapeHtml(node.intelamt.ver); } else
|
||||
|
||||
if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "Activated" + '</i>'; }
|
||||
else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Unknown Version & State" + '</i>'; }
|
||||
else {
|
||||
str += provisioningStates[node.intelamt.state];
|
||||
if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str = ' <span>' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str = ' <span>' + "ACM" + '</span>'; } }
|
||||
str += (', v' + node.intelamt.ver);
|
||||
str += (', v' + EscapeHtml(node.intelamt.ver));
|
||||
}
|
||||
|
||||
if (node.intelamt.tls == 1) { str += ', <span>' + "TLS" + '</span>'; }
|
||||
@ -3669,7 +3669,7 @@
|
||||
if (m[0].gatewaymac) {
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}, Gateway: {1}", EscapeHtml(m[0].mac), EscapeHtml(m[0].gatewaymac)));
|
||||
} else {
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}", m[0].mac));
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}", EscapeHtml(m[0].mac)));
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < m.length; j++) {
|
||||
@ -3698,7 +3698,7 @@
|
||||
// Attribute: Intel AMT
|
||||
if (node.intelamt != null) {
|
||||
var x = '';
|
||||
x += addDetailItem("Version", (node.intelamt.ver) ? ('v' + node.intelamt.ver) : ('<i>' + "Unknown" + '</i>'), s);
|
||||
x += addDetailItem("Version", (node.intelamt.ver) ? ('v' + EscapeHtml(node.intelamt.ver)) : ('<i>' + "Unknown" + '</i>'), s);
|
||||
var provisioningStates = { 0: nobreak("Not Activated (Pre)"), 1: nobreak("Not Activated (In)"), 2: nobreak("Activated") };
|
||||
var provisioningMode = '';
|
||||
if ((node.intelamt.state == 2) && node.intelamt.flags) { if (node.intelamt.flags & 2) { provisioningMode = (', ' + "Client Control Mode (CCM)"); } else if (node.intelamt.flags & 4) { provisioningMode = (', ' + "Admin Control Mode (ACM)"); } }
|
||||
@ -4220,7 +4220,7 @@
|
||||
function addLink(x, f) { return '<a style=cursor:pointer;color:darkblue;text-decoration:none onclick=\'' + f + '\'>♦ ' + x + '</a>'; }
|
||||
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
|
||||
function passwordcheck(p) { var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/; return re.test(p); }
|
||||
function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format('{0} bytes', size); }
|
||||
function getFileSizeStr(size) { if (typeof size != 'number') { size = 0; } if (size == 1) return "1 byte"; return format('{0} bytes', size); }
|
||||
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
|
||||
function focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
|
||||
var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
|
||||
|
@ -5316,14 +5316,14 @@
|
||||
if (node.intelamt != null) {
|
||||
var str = '';
|
||||
var provisioningStates = { 0: nobreak("Not Activated (Pre)"), 1: nobreak("Not Activated (In)"), 2: nobreak("Activated") };
|
||||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + "Unknown State" + '</i>, v' + node.intelamt.ver; } else
|
||||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>' + "Unknown State" + '</i>, v' + EscapeHtml(node.intelamt.ver); } else
|
||||
|
||||
if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>' + "Activated" + '</i>'; }
|
||||
else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>' + "Unknown Version & State" + '</i>'; }
|
||||
else {
|
||||
str += provisioningStates[node.intelamt.state];
|
||||
if ((node.intelamt.state == 2) && node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' <span title="' + "Intel AMT is activated in Client Control Mode" + '">' + "CCM" + '</span>'; } else if (node.intelamt.flags & 4) { str += ' <span title="' + "Intel AMT is activated in Admin Control Mode" + '">' + "ACM" + '</span>'; } }
|
||||
str += (', v' + node.intelamt.ver);
|
||||
str += (', v' + EscapeHtml(node.intelamt.ver));
|
||||
}
|
||||
|
||||
if (node.intelamt.tls == 1) { str += ', <span title="' + "Intel AMT is setup with TLS network security" + '">' + "TLS" + '</span>'; }
|
||||
@ -6959,8 +6959,8 @@
|
||||
for (var i in p) {
|
||||
if (p[i].p != 0) {
|
||||
var c = p[i].c;
|
||||
if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0,30) + '...</span>' }
|
||||
x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + p[i].p + '</div><a href=# style=float:right;padding-right:5px;cursor:pointer title="' + "Stop process" + '" onclick=\'return stopProcess(' + p[i].p + ',"' + p[i].c + '")\'><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? p[i].u : '') + '</div><div>' + c + '</div></div>';
|
||||
if (c.length > 30) { c = '<span title="' + EscapeHtml(c) + '">' + EscapeHTML(c.substring(0,30)) + '...</span>' } else { c = EscapeHtml(c); }
|
||||
x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + EscapeHtml(p[i].p) + '</div><a href=# style=float:right;padding-right:5px;cursor:pointer title="' + "Stop process" + '" onclick=\'return stopProcess(' + EscapeHtml(p[i].p) + ',"' + EscapeHtml(p[i].c) + '")\'><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? EscapeHtml(p[i].u) : '') + '</div><div>' + c + '</div></div>';
|
||||
}
|
||||
}
|
||||
QH('DeskToolsProcesses', x);
|
||||
@ -6989,8 +6989,8 @@
|
||||
for (var i in s) {
|
||||
if (s[i].p != 0) {
|
||||
var c = s[i].d;
|
||||
if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0, 30) + '...</span>' }
|
||||
x += '<div onclick=showServiceDetailsDialog(' + s[i].i + ') class=deskToolsBar><div style=width:70px;float:left;padding-right:5px>' + s[i].p + '</div><div>' + c + '</div></div>';
|
||||
if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0, 30) + '...</span>' } else { c = EscapeHtml(c); }
|
||||
x += '<div onclick=showServiceDetailsDialog(' + s[i].i + ') class=deskToolsBar><div style=width:70px;float:left;padding-right:5px>' + EscapeHtml(s[i].p) + '</div><div>' + c + '</div></div>';
|
||||
}
|
||||
}
|
||||
QH('DeskToolsServices', x);
|
||||
@ -7555,7 +7555,7 @@
|
||||
} else {
|
||||
var link = shortname;
|
||||
if (f.s > 0) { link = '<a href=# style=cursor:pointer onclick="return p13downloadfile(\'' + encodeURIComponentEx(newlinkpath + '/' + name) + '\',\'' + encodeURIComponentEx(name) + '\',' + f.s + ')">' + shortname + '</a>'; }
|
||||
h = '<div id=fileEntry cmenu=filesContextMenu fileIndex=' + i + ' class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <span class=fsize>' + fdatestr + '</span><span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
||||
h = '<div id=fileEntry cmenu=filesContextMenu fileIndex=' + i + ' class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'> <span class=fsize>' + fdatestr + '</span><span style=float:right>' + EscapeHTML(fsize) + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
||||
}
|
||||
|
||||
if (f.t < 3) { html1 += h; } else { html2 += h; }
|
||||
@ -8145,7 +8145,7 @@
|
||||
if (m.gatewaymac) {
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}, Gateway: {1}", EscapeHtml(m.mac), EscapeHtml(m.gatewaymac)));
|
||||
} else {
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}", m.mac));
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}", EscapeHtml(m.mac)));
|
||||
}
|
||||
}
|
||||
for (var j in m.ipv4layer) {
|
||||
@ -8178,7 +8178,7 @@
|
||||
if (m[0].gatewaymac) {
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}, Gateway: {1}", EscapeHtml(m[0].mac), EscapeHtml(m[0].gatewaymac)));
|
||||
} else {
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}", m[0].mac));
|
||||
x += addDetailItem("MAC Layer", format("MAC: {0}", EscapeHtml(m[0].mac)));
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < m.length; j++) {
|
||||
@ -8207,7 +8207,7 @@
|
||||
// Attribute: Intel AMT
|
||||
if (node.intelamt != null) {
|
||||
var x = '';
|
||||
x += addDetailItem("Version", (node.intelamt.ver)?('v' + node.intelamt.ver):('<i>' + "Unknown" + '</i>'), s);
|
||||
x += addDetailItem("Version", (node.intelamt.ver)?('v' + EscapeHtml(node.intelamt.ver)):('<i>' + "Unknown" + '</i>'), s);
|
||||
var provisioningStates = { 0: nobreak("Not Activated (Pre)"), 1: nobreak("Not Activated (In)"), 2: nobreak("Activated") };
|
||||
var provisioningMode = '';
|
||||
if ((node.intelamt.state == 2) && node.intelamt.flags) { if (node.intelamt.flags & 2) { provisioningMode = (', ' + "Client Control Mode (CCM)"); } else if (node.intelamt.flags & 4) { provisioningMode = (', ' + "Admin Control Mode (ACM)"); } }
|
||||
@ -10069,7 +10069,7 @@
|
||||
function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
|
||||
function p5selectallfile() { var nv = (getFileSelCount() == 0), checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p5setActions(); }
|
||||
function setupBackPointers(x) { if (x.f != null) { var fs = 0, fc = 0; for (var i in x.f) { setupBackPointers(x.f[i]); x.f[i].parent = x; if (x.f[i].s) { fs += x.f[i].s; } if (x.f[i].c) { fc += x.f[i].c; } if (x.f[i].t == 3) { fc++; } } x.s = fs; x.c = fc; } return x; }
|
||||
function getFileSizeStr(size) { if (size == 1) return "1 byte"; return format("{0} bytes", size); }
|
||||
function getFileSizeStr(size) { if (typeof size != 'number') { size = 0; } if (size == 1) return "1 byte"; return format("{0} bytes", size); }
|
||||
function p5folderup(x) { if (x == null) { filetreelocation.pop(); } else { while (filetreelocation.length > x) { filetreelocation.pop(); } } updateFiles(); return false; }
|
||||
function p5folderset(x) { filetreelocation.push(decodeURIComponent(x)); updateFiles(); return false; }
|
||||
function p5createfolder() { setDialogMode(2, "New Folder", 3, p5createfolderEx, '<input type=text id=p5renameinput maxlength=64 onkeyup=p5fileNameCheck(event) style=width:100% />'); focusTextBox('p5renameinput'); p5fileNameCheck(); }
|
||||
@ -11938,7 +11938,7 @@
|
||||
} else {
|
||||
var link = shortname;
|
||||
//if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=" + encodeURIComponentEx(filetreelinkpath + '/' + f.nx) + "\">" + shortname + "</a>"; }
|
||||
h = '<div class=filelist file=3><input style=float:left name=fcx class=fcb type=checkbox onchange=d3setActions() value="' + f.nx + '"> <span style=float:right>' + fsize + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
||||
h = '<div class=filelist file=3><input style=float:left name=fcx class=fcb type=checkbox onchange=d3setActions() value="' + f.nx + '"> <span style=float:right>' + EscapeHtml(fsize) + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
|
||||
}
|
||||
|
||||
if (f.t < 3) { html1 += h; } else { html2 += h; }
|
||||
@ -11991,18 +11991,18 @@
|
||||
} else {
|
||||
for (var i in notifications) {
|
||||
var n = notifications[i], t = '', d = new Date(n.time), icon = 0;
|
||||
if (n.title != null) { t = '<b>' + n.title + '</b>: ' }
|
||||
if (n.title != null) { t = '<b>' + EscapeHtml(n.title) + '</b>: ' }
|
||||
if (n.nodeid != null) {
|
||||
var node = getNodeFromId(n.nodeid);
|
||||
if (node != null) {
|
||||
icon = node.icon;
|
||||
if (notifySettings & 16) { t = '<b>' + meshes[node.meshid].name + ' / ' + node.name + '</b>: '; } else { t = '<b>' + node.name + '</b>: '; } // Display with or without group name
|
||||
if (notifySettings & 16) { t = '<b>' + EscapeHtml(meshes[node.meshid].name) + ' / ' + EscapeHtml(node.name) + '</b>: '; } else { t = '<b>' + EscapeHtml(node.name) + '</b>: '; } // Display with or without group name
|
||||
}
|
||||
}
|
||||
|
||||
r += '<div title="' + format("Occured at {0}", printDateTime(d)) + '" id="notifyx' + n.id + '" class=notification style="cursor:pointer;border-top:1px solid ' + ((r == '') ? 'transparent' : 'orange') + '">';
|
||||
if (icon) { r += '<div class=j' + icon + ' onclick="notificationSelected(' + n.id + ')" style=margin:5px;float:left></div>'; }
|
||||
r += '<div onclick="notificationDelete(' + n.id + ')" class=unselectable title="' + "Clear this notification" + '" style=margin:5px;float:right;color:orange><b>X</b></div><div onclick="notificationSelected(' + n.id + ')" style=margin:5px>' + t + n.text + '</div></div>';
|
||||
r += '<div onclick="notificationDelete(' + n.id + ')" class=unselectable title="' + "Clear this notification" + '" style=margin:5px;float:right;color:orange><b>X</b></div><div onclick="notificationSelected(' + n.id + ')" style=margin:5px>' + t + EscapeHtml(n.text) + '</div></div>';
|
||||
}
|
||||
}
|
||||
var deleteall = '';
|
||||
@ -12656,9 +12656,9 @@
|
||||
installedPluginList.forEach(function(p){
|
||||
var cant_action = [];
|
||||
if (p.hasAdminPanel == true && p.status) {
|
||||
p.nameHtml = '<a onclick="return goPlugin(\'' + p.shortName + '\', \'' + p.name.replace(/'/g, "\\'") + '\');">' + p.name + '</a>';
|
||||
p.nameHtml = '<a onclick="return goPlugin(\'' + p.shortName + '\', \'' + p.name.replace(/'/g, "\\'") + '\');">' + EscapeHtml(p.name) + '</a>';
|
||||
} else {
|
||||
p.nameHtml = p.name;
|
||||
p.nameHtml = EscapeHtml(p.name);
|
||||
}
|
||||
p.statusText = statusMap[p.status].text;
|
||||
p.statusColor = statusMap[p.status].color;
|
||||
@ -12691,7 +12691,7 @@
|
||||
}
|
||||
p.actions += '</select>';
|
||||
|
||||
var tpl = '<td><img style=margin-top:3px src=images/plugin24.png></td><td class=gradTable1> </td><td class=gradTable2>' + p.nameHtml + '</td><td class=gradTable2>' + p.description + '</td><td class=gradTable2 style=text-align:center><a href="' + p.homepage + '" target="_blank">Home</a></td><td class=gradTable2 style=text-align:center>' + p.version + '</td><td style=text-align:center class="pluginUpgradeAvailable gradTable2">' + p.upgradeAvail + '</td><td class=gradTable2 style="text-align:center;color:#' + p.statusColor + '">' + p.statusText + '</td><td class="pluginAction gradTable2" style=text-align:center>' + p.actions + '</td><td class=gradTable3> </td>';
|
||||
var tpl = '<td><img style=margin-top:3px src=images/plugin24.png></td><td class=gradTable1> </td><td class=gradTable2>' + p.nameHtml + '</td><td class=gradTable2>' + EscapeHtml(p.description) + '</td><td class=gradTable2 style=text-align:center><a href="' + EscapeHtml(p.homepage) + '" target="_blank">Home</a></td><td class=gradTable2 style=text-align:center>' + EscapeHtml(p.version) + '</td><td style=text-align:center class="pluginUpgradeAvailable gradTable2">' + p.upgradeAvail + '</td><td class=gradTable2 style="text-align:center;color:#' + p.statusColor + '">' + p.statusText + '</td><td class="pluginAction gradTable2" style=text-align:center>' + p.actions + '</td><td class=gradTable3> </td>';
|
||||
var tr = tbl.insertRow(-1);
|
||||
tr.innerHTML = tpl;
|
||||
tr.classList.add('p42tblRow');
|
||||
|
@ -74,7 +74,7 @@
|
||||
if (name != '') { document.title = name + ' - ' + document.title; }
|
||||
|
||||
function load() {
|
||||
if (name != '') { QH('computerName', name); }
|
||||
if (name != '') { QH('computerName', EscapeHtml(name)); }
|
||||
client = MstscClient.create(Q('myCanvas'));
|
||||
Q('inputDomain').focus();
|
||||
canvas = Q('myCanvas');
|
||||
|
44
webserver.js
44
webserver.js
@ -1513,28 +1513,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
var idsplit = cookie.u.split('/');
|
||||
if ((idsplit.length != 2) || (idsplit[0] != domain.id)) {
|
||||
parent.debug('web', 'handleCheckMailRequest: Invalid domain.');
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 1, domainurl: encodeURIComponent(domain.url) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 1, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain));
|
||||
} else {
|
||||
obj.db.Get('user/' + cookie.u.toLowerCase(), function (err, docs) {
|
||||
if (docs.length == 0) {
|
||||
parent.debug('web', 'handleCheckMailRequest: Invalid username.');
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 2, domainurl: encodeURIComponent(domain.url), arg1: encodeURIComponent(idsplit[1]) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 2, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), arg1: encodeURIComponent(idsplit[1]).replace(/'/g, '%27') }, req, domain));
|
||||
} else {
|
||||
var user = docs[0];
|
||||
if (user.email != cookie.e) {
|
||||
parent.debug('web', 'handleCheckMailRequest: Invalid e-mail.');
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 3, domainurl: encodeURIComponent(domain.url), arg1: encodeURIComponent(user.email), arg2: encodeURIComponent(user.name) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 3, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), arg1: encodeURIComponent(user.email).replace(/'/g, '%27'), arg2: encodeURIComponent(user.name).replace(/'/g, '%27') }, req, domain));
|
||||
} else {
|
||||
if (cookie.a == 1) {
|
||||
// Account email verification
|
||||
if (user.emailVerified == true) {
|
||||
parent.debug('web', 'handleCheckMailRequest: email already verified.');
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 4, domainurl: encodeURIComponent(domain.url), arg1: encodeURIComponent(user.email), arg2: encodeURIComponent(user.name) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 4, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), arg1: encodeURIComponent(user.email).replace(/'/g, '%27'), arg2: encodeURIComponent(user.name).replace(/'/g, '%27') }, req, domain));
|
||||
} else {
|
||||
obj.db.GetUserWithVerifiedEmail(domain.id, user.email, function (err, docs) {
|
||||
if (docs.length > 0) {
|
||||
parent.debug('web', 'handleCheckMailRequest: email already in use.');
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 5, domainurl: encodeURIComponent(domain.url), arg1: encodeURIComponent(user.email) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 5, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), arg1: encodeURIComponent(user.email).replace(/'/g, '%27') }, req, domain));
|
||||
} else {
|
||||
parent.debug('web', 'handleCheckMailRequest: email verification success.');
|
||||
|
||||
@ -1549,7 +1549,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, event);
|
||||
|
||||
// Send the confirmation page
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 6, domainurl: encodeURIComponent(domain.url), arg1: encodeURIComponent(user.email), arg2: encodeURIComponent(user.name) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 6, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), arg1: encodeURIComponent(user.email).replace(/'/g, '%27'), arg2: encodeURIComponent(user.name).replace(/'/g, '%27') }, req, domain));
|
||||
|
||||
// Send a notification
|
||||
obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:<br /><b>' + EscapeHtml(user.email) + '</b>.', nolog: 1, id: Math.random() });
|
||||
@ -1563,7 +1563,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
// Account reset
|
||||
if (user.emailVerified != true) {
|
||||
parent.debug('web', 'handleCheckMailRequest: email not verified.');
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 7, domainurl: encodeURIComponent(domain.url), arg1: EscapeHtml(user.email), arg2: EscapeHtml(user.name) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 7, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), arg1: EscapeHtml(user.email), arg2: EscapeHtml(user.name) }, req, domain));
|
||||
} else {
|
||||
// Set a temporary password
|
||||
obj.crypto.randomBytes(16, function (err, buf) {
|
||||
@ -1588,7 +1588,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, event);
|
||||
|
||||
// Send the new password
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 8, domainurl: encodeURIComponent(domain.url), arg1: EscapeHtml(user.name), arg2: EscapeHtml(newpass) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 8, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), arg1: EscapeHtml(user.name), arg2: EscapeHtml(newpass) }, req, domain));
|
||||
parent.debug('web', 'handleCheckMailRequest: send temporary password.');
|
||||
|
||||
// Send to authlog
|
||||
@ -1597,14 +1597,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 9, domainurl: encodeURIComponent(domain.url) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 9, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 10, domainurl: encodeURIComponent(domain.url) }, req, domain));
|
||||
render(req, res, getRenderPage('message', req, domain), getRenderArgs({ titleid: 1, msgid: 10, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1637,7 +1637,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (req.query.ws != null) {
|
||||
// This is a query with a websocket relay cookie, check that the cookie is valid and use it.
|
||||
var rcookie = parent.decodeCookie(req.query.ws, parent.loginCookieEncryptionKey, 240); // Cookie with 4 hour timeout
|
||||
if ((rcookie != null) && (rcookie.domainid == domain.id) && (rcookie.nodeid != null) && (rcookie.tcpport != null)) { render(req, res, getRenderPage('mstsc', req, domain), getRenderArgs({ cookie: req.query.ws, name: encodeURIComponent(req.query.name) }, req, domain)); return; }
|
||||
if ((rcookie != null) && (rcookie.domainid == domain.id) && (rcookie.nodeid != null) && (rcookie.tcpport != null)) {
|
||||
render(req, res, getRenderPage('mstsc', req, domain), getRenderArgs({ cookie: req.query.ws, name: encodeURIComponent(req.query.name).replace(/'/g, '%27') }, req, domain)); return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the logged in user if present
|
||||
@ -1688,7 +1690,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
|
||||
// Generate a cookie and respond
|
||||
var cookie = parent.encodeCookie({ userid: user._id, domainid: user.domain, nodeid: node._id, tcpport: port }, parent.loginCookieEncryptionKey);
|
||||
render(req, res, getRenderPage('mstsc', req, domain), getRenderArgs({ cookie: cookie, name: encodeURIComponent(node.name) }, req, domain));
|
||||
render(req, res, getRenderPage('mstsc', req, domain), getRenderArgs({ cookie: cookie, name: encodeURIComponent(node.name).replace(/'/g, '%27') }, req, domain));
|
||||
});
|
||||
}
|
||||
|
||||
@ -2260,7 +2262,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (domain.customui != null) { customui = encodeURIComponent(JSON.stringify(domain.customui)); }
|
||||
|
||||
// Refresh the session
|
||||
render(req, res, getRenderPage('default', req, domain), getRenderArgs({ authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControls: encodeURIComponent(JSON.stringify(logoutcontrols)).replace(/'/g, '%27'), domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, customui: customui, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), amtscanoptions: amtscanoptions, pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports() }, req, domain));
|
||||
render(req, res, getRenderPage('default', req, domain), getRenderArgs({ authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControls: encodeURIComponent(JSON.stringify(logoutcontrols)).replace(/'/g, '%27'), domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, customui: customui, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate).replace(/'/g, '%27'), amtscanoptions: amtscanoptions, pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports() }, req, domain));
|
||||
});
|
||||
} else {
|
||||
// Send back the login application
|
||||
@ -2354,7 +2356,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (domain.customui != null) { customui = encodeURIComponent(JSON.stringify(domain.customui)); }
|
||||
|
||||
// Render the login page
|
||||
render(req, res, getRenderPage('login', req, domain), getRenderArgs({ loginmode: loginmode, rootCertLink: getRootCertLink(), newAccount: newAccountsAllowed, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, customui: customui, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), messageid: msgid, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext).split('\'').join('\\\'') : null, hwstate: hwstate, otpemail: otpemail, otpsms: otpsms, twoFactorCookieDays: twoFactorCookieDays, authStrategies: authStrategies.join(',') }, req, domain));
|
||||
render(req, res, getRenderPage('login', req, domain), getRenderArgs({ loginmode: loginmode, rootCertLink: getRootCertLink(), newAccount: newAccountsAllowed, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, customui: customui, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge).replace(/'/g, '%27'), messageid: msgid, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext).split('\'').join('\\\'') : null, hwstate: hwstate, otpemail: otpemail, otpsms: otpsms, twoFactorCookieDays: twoFactorCookieDays, authStrategies: authStrategies.join(',') }, req, domain));
|
||||
}
|
||||
|
||||
// Handle a post request on the root
|
||||
@ -2500,7 +2502,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
parent.debug('web', 'handleMessengerRequest()');
|
||||
|
||||
var webRtcConfig = null;
|
||||
if (obj.parent.config.settings && obj.parent.config.settings.webrtconfig && (typeof obj.parent.config.settings.webrtconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtconfig)); }
|
||||
if (obj.parent.config.settings && obj.parent.config.settings.webrtconfig && (typeof obj.parent.config.settings.webrtconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtconfig)).replace(/'/g, '%27'); }
|
||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' });
|
||||
render(req, res, getRenderPage('messenger', req, domain), getRenderArgs({ webrtconfig: webRtcConfig }, req, domain));
|
||||
}
|
||||
@ -3852,8 +3854,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (xdomain != '') xdomain += '/';
|
||||
var meshsettings = 'MeshName=' + mesh.name + '\r\nMeshType=' + mesh.mtype + '\r\nMeshID=0x' + meshidhex + '\r\nServerID=' + serveridhex + '\r\n';
|
||||
if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { meshsettings += 'MeshServer=local\r\n'; }
|
||||
if (req.query.tag != null) { meshsettings += 'Tag=' + req.query.tag + '\r\n'; }
|
||||
if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += 'InstallFlags=' + req.query.installflags + '\r\n'; }
|
||||
if ((req.query.tag != null) && (typeof req.query.tag == 'string') && (obj.common.isAlphaNumeric(req.query.tag) == true)) { meshsettings += 'Tag=' + req.query.tag + '\r\n'; }
|
||||
if ((req.query.installflags != null) && (req.query.installflags != 0) && (parseInt(req.query.installflags) == req.query.installflags)) { meshsettings += 'InstallFlags=' + parseInt(req.query.installflags) + '\r\n'; }
|
||||
if ((domain.agentnoproxy === true) || (obj.args.lanonly == true)) { meshsettings += 'ignoreProxyFile=1\r\n'; }
|
||||
if (obj.args.agentconfig) { for (var i in obj.args.agentconfig) { meshsettings += obj.args.agentconfig[i] + '\r\n'; } }
|
||||
if (domain.agentconfig) { for (var i in domain.agentconfig) { meshsettings += domain.agentconfig[i] + '\r\n'; } }
|
||||
@ -4033,8 +4035,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (obj.args.agentport != null) { httpsPort = obj.args.agentport; } // If an agent only port is enabled, use that.
|
||||
if (obj.args.agentaliasport != null) { httpsPort = obj.args.agentaliasport; } // If an agent alias port is specified, use that.
|
||||
if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { meshsettings += 'MeshServer=local\r\n'; }
|
||||
if (req.query.tag != null) { meshsettings += 'Tag=' + req.query.tag + '\r\n'; }
|
||||
if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += 'InstallFlags=' + req.query.installflags + '\r\n'; }
|
||||
if ((req.query.tag != null) && (typeof req.query.tag == 'string') && (obj.common.isAlphaNumeric(req.query.tag) == true)) { meshsettings += 'Tag=' + req.query.tag + '\r\n'; }
|
||||
if ((req.query.installflags != null) && (req.query.installflags != 0) && (parseInt(req.query.installflags) == req.query.installflags)) { meshsettings += 'InstallFlags=' + parseInt(req.query.installflags) + '\r\n'; }
|
||||
if ((domain.agentnoproxy === true) || (obj.args.lanonly == true)) { meshsettings += 'ignoreProxyFile=1\r\n'; }
|
||||
if (obj.args.agentconfig) { for (var i in obj.args.agentconfig) { meshsettings += obj.args.agentconfig[i] + '\r\n'; } }
|
||||
if (domain.agentconfig) { for (var i in domain.agentconfig) { meshsettings += domain.agentconfig[i] + '\r\n'; } }
|
||||
@ -4130,8 +4132,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (obj.args.agentport != null) { httpsPort = obj.args.agentport; } // If an agent only port is enabled, use that.
|
||||
if (obj.args.agentaliasport != null) { httpsPort = obj.args.agentaliasport; } // If an agent alias port is specified, use that.
|
||||
if (obj.args.lanonly != true) { meshsettings += 'MeshServer=ws' + (obj.args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'agent.ashx\r\n'; } else { meshsettings += 'MeshServer=local\r\n'; }
|
||||
if (req.query.tag != null) { meshsettings += 'Tag=' + req.query.tag + '\r\n'; }
|
||||
if ((req.query.installflags != null) && (req.query.installflags != 0)) { meshsettings += 'InstallFlags=' + req.query.installflags + '\r\n'; }
|
||||
if ((req.query.tag != null) && (typeof req.query.tag == 'string') && (obj.common.isAlphaNumeric(req.query.tag) == true)) { meshsettings += 'Tag=' + req.query.tag + '\r\n'; }
|
||||
if ((req.query.installflags != null) && (req.query.installflags != 0) && (parseInt(req.query.installflags) == req.query.installflags)) { meshsettings += 'InstallFlags=' + parseInt(req.query.installflags) + '\r\n'; }
|
||||
if ((domain.agentnoproxy === true) || (obj.args.lanonly == true)) { meshsettings += 'ignoreProxyFile=1\r\n'; }
|
||||
if (obj.args.agentconfig) { for (var i in obj.args.agentconfig) { meshsettings += obj.args.agentconfig[i] + '\r\n'; } }
|
||||
if (domain.agentconfig) { for (var i in domain.agentconfig) { meshsettings += domain.agentconfig[i] + '\r\n'; } }
|
||||
|
Loading…
Reference in New Issue
Block a user