Added function handlers for agentdisconnect and addmeshuser

Noah Zalev committed Jan 8, 2022 at 11:55 UTC fe4d426bdb9b062834c882d40d238505a7405d9a
1 file changed +146 -146
meshuser.js
+146 -146
@@ -2171,139 +2171,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2171 if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'editmesh', responseid: command.responseid, result: 'ok' })); } catch (ex) { } }
2172 break;
2173 }
2174 - case 'addmeshuser':
2175 - {
2176 - var err = null, mesh, meshIdSplit;
2177 - if (typeof command.userid == 'string') { command.userids = [command.userid]; }
2178 -
2179 - // Resolve the device group name if needed
2180 - if ((typeof command.meshname == 'string') && (command.meshid == null)) {
2181 - for (var i in parent.meshes) {
2182 - var m = parent.meshes[i];
2183 - if ((m.mtype == 2) && (m.name == command.meshname) && parent.IsMeshViewable(user, m)) {
2184 - if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; }
2185 - }
2186 - }
2187 - }
2188 -
2189 - var selfMeshRights = 0;
2190 - try {
2191 - if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid groupid'; } // Check the meshid
2192 - else if (common.validateInt(command.meshadmin) == false) { err = 'Invalid group rights'; } // Mesh rights must be an integer
2193 - else if ((common.validateStrArray(command.usernames, 1, 64) == false) && (common.validateStrArray(command.userids, 1, 128) == false)) { err = 'Invalid usernames'; } // Username is between 1 and 64 characters
2194 - else {
2195 - if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
2196 - mesh = parent.meshes[command.meshid];
2197 - meshIdSplit = command.meshid.split('/');
2198 - if (mesh == null) { err = 'Unknown group'; }
2199 - else if (((selfMeshRights = parent.GetMeshRights(user, mesh)) & MESHRIGHT_MANAGEUSERS) == 0) { err = 'Permission denied'; }
2200 - else if ((meshIdSplit.length != 3) || (meshIdSplit[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
2201 - }
2202 - } catch (ex) { err = 'Validation exception: ' + ex; }
2203 -
2204 - // Handle any errors
2205 - if (err != null) {
2206 - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: err })); } catch (ex) { } }
2207 - break;
2208 - }
2209 -
2210 - // Convert user names to userid's
2211 - if (command.userids == null) {
2212 - command.userids = [];
2213 - for (var i in command.usernames) {
2214 - if (parent.users['user/' + domain.id + '/' + command.usernames[i].toLowerCase()] != null) { command.userids.push('user/' + domain.id + '/' + command.usernames[i].toLowerCase()); }
2215 - else if (parent.users['user/' + domain.id + '/' + command.usernames[i]] != null) { command.userids.push('user/' + domain.id + '/' + command.usernames[i]); }
2216 - }
2217 - }
2218 - var unknownUsers = [], successCount = 0, failCount = 0, msgs = [];
2219 - for (var i in command.userids) {
2220 - // Check if the user exists
2221 - var newuserid = command.userids[i], newuser = null;
2222 - if (newuserid.startsWith('user/')) { newuser = parent.users[newuserid]; }
2223 - else if (newuserid.startsWith('ugrp/')) { newuser = parent.userGroups[newuserid]; }
2224 -
2225 - // Search for a user name in that windows domain is the username starts with *\
2226 - if ((newuser == null) && (newuserid.startsWith('user/' + domain.id + '/*\\')) == true) {
2227 - var search = newuserid.split('/')[2].substring(1);
2228 - 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; } }
2229 - }
2230 -
2231 - // Make sure this user is in the same domain as the device group
2232 - if (meshIdSplit[1] != newuserid.split('/')[1]) { msgs.push("Mismatch domains"); continue; }
2233 -
2234 - if (newuser != null) {
2235 - // Can't add or modify self
2236 - if (newuserid == obj.user._id) { msgs.push("Can't change self"); continue; }
2237 -
2238 - var targetMeshRights = 0;
2239 - if ((newuser.links != null) && (newuser.links[command.meshid] != null) && (newuser.links[command.meshid].rights != null)) { targetMeshRights = newuser.links[command.meshid].rights; }
2240 - 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
2241 -
2242 - if (command.remove === true) {
2243 - // Remove mesh from user or user group
2244 - delete newuser.links[command.meshid];
2245 - } else {
2246 - // Adjust rights since we can't add more rights that we have outself for MESHRIGHT_MANAGEUSERS
2247 - if ((selfMeshRights != MESHRIGHT_ADMIN) && (command.meshadmin == MESHRIGHT_ADMIN)) { msgs.push("Can't set device group administrator, if not administrator"); continue; }
2248 - if (((selfMeshRights & 2) == 0) && ((command.meshadmin & 2) != 0) && ((targetMeshRights & 2) == 0)) { command.meshadmin -= 2; }
2249 -
2250 - // Add mesh to user or user group
2251 - if (newuser.links == null) { newuser.links = {}; }
2252 - if (newuser.links[command.meshid]) { newuser.links[command.meshid].rights = command.meshadmin; } else { newuser.links[command.meshid] = { rights: command.meshadmin }; }
2253 - }
2254 - if (newuserid.startsWith('user/')) { db.SetUser(newuser); }
2255 - else if (newuserid.startsWith('ugrp/')) { db.Set(newuser); }
2256 - parent.parent.DispatchEvent([newuser._id], obj, 'resubscribe');
2257 -
2258 - if (newuserid.startsWith('user/')) {
2259 - // Notify user change
2260 - var targets = ['*', 'server-users', user._id, newuser._id];
2261 - var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(newuser), action: 'accountchange', msgid: 78, msgArgs: [newuser.name], msg: 'Device group membership changed: ' + newuser.name, domain: domain.id };
2262 - 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.
2263 - parent.parent.DispatchEvent(targets, obj, event);
2264 - } else if (newuserid.startsWith('ugrp/')) {
2265 - // Notify user group change
2266 - var targets = ['*', 'server-ugroups', user._id, newuser._id];
2267 - var event = { etype: 'ugrp', username: user.name, ugrpid: newuser._id, name: newuser.name, desc: newuser.desc, action: 'usergroupchange', links: newuser.links, msgid: 79, msgArgs: [newuser.name], msg: 'User group changed: ' + newuser.name, domain: domain.id };
2268 - 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.
2269 - parent.parent.DispatchEvent(targets, obj, event);
2270 - }
2271 -
2272 - var event;
2273 - if (command.remove === true) {
2274 - // Remove userid from the mesh
2275 - delete mesh.links[newuserid];
2276 - db.Set(mesh);
2277 - event = { etype: 'mesh', username: newuser.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + newuser.name + ' from device group ' + mesh.name, domain: domain.id, invite: mesh.invite };
2278 - } else {
2279 - // Add userid to the mesh
2280 - mesh.links[newuserid] = { name: newuser.name, rights: command.meshadmin };
2281 - db.Set(mesh);
2282 - event = { etype: 'mesh', username: newuser.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to device group ' + mesh.name, domain: domain.id, invite: mesh.invite };
2283 - }
2284 -
2285 - // Notify mesh change
2286 - 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.
2287 - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id, newuserid]), obj, event);
2288 - if (command.remove === true) { msgs.push("Removed user " + newuserid.split('/')[2]); } else { msgs.push("Added user " + newuserid.split('/')[2]); }
2289 - successCount++;
2290 - } else {
2291 - msgs.push("Unknown user " + newuserid.split('/')[2]);
2292 - unknownUsers.push(newuserid.split('/')[2]);
2293 - failCount++;
2294 - }
2295 - }
2296 -
2297 - if ((successCount == 0) && (failCount == 0)) { msgs.push("Nothing done"); }
2298 -
2299 - if (unknownUsers.length > 0) {
2300 - // Send error back, user not found.
2301 - displayNotificationMessage('User' + ((unknownUsers.length > 1) ? 's' : '') + ' ' + EscapeHtml(unknownUsers.join(', ')) + ' not found.', "Device Group", 'ServerNotify', 5, (unknownUsers.length > 1) ? 16 : 15, [EscapeHtml(unknownUsers.join(', '))]);
2302 - }
2303 -
2304 - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: msgs.join(', '), success: successCount, failed: failCount })); } catch (ex) { } }
2305 - break;
2306 - }
2174 case 'adddeviceuser': {
2175 if (typeof command.userid == 'string') { command.userids = [command.userid]; }
2176 var err = null, nodeIdSplit;
@@ -3321,19 +3188,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3188 }
3189 break;
3190 }
3324 - case 'agentdisconnect':
3325 - {
3326 - if (common.validateInt(command.disconnectMode) == false) return; // Check disconnect mode
3327 -
3328 - // Get the node and the rights for this node
3329 - parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
3330 - if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != SITERIGHT_ADMIN))) return;
3331 -
3332 - // Force mesh agent disconnection
3333 - parent.forceMeshAgentDisconnect(user, domain, node._id, command.disconnectMode);
3334 - });
3335 - break;
3336 - }
3191 case 'close':
3192 {
3193 // Close the web socket session
@@ -5328,9 +5182,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5182 }
5183
5184 const serverCommands = {
5185 + 'addmeshuser': serverCommandAddMeshUser,
5186 'adduser': serverCommandAddUser,
5187 'adduserbatch': serverCommandAddUserBatch,
5188 'addusertousergroup': serverCommandAddUserToUserGroup,
5189 + 'agentdisconnect': serverCommandAgentDisconnect,
5190 'authcookie': serverCommandAuthCookie,
5191 'changeemail': serverCommandChangeEmail,
5192 'changelang': serverCommandChangeLang,
@@ -5416,6 +5272,138 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5272 'webstats': [serverUserCommandWebStats, ""]
5273 };
5274
5275 + function serverCommandAddMeshUser(command) {
5276 + var err = null, mesh, meshIdSplit;
5277 + if (typeof command.userid == 'string') { command.userids = [command.userid]; }
5278 +
5279 + // Resolve the device group name if needed
5280 + if ((typeof command.meshname == 'string') && (command.meshid == null)) {
5281 + for (var i in parent.meshes) {
5282 + var m = parent.meshes[i];
5283 + if ((m.mtype == 2) && (m.name == command.meshname) && parent.IsMeshViewable(user, m)) {
5284 + if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; }
5285 + }
5286 + }
5287 + }
5288 +
5289 + var selfMeshRights = 0;
5290 + try {
5291 + if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid groupid'; } // Check the meshid
5292 + else if (common.validateInt(command.meshadmin) == false) { err = 'Invalid group rights'; } // Mesh rights must be an integer
5293 + else if ((common.validateStrArray(command.usernames, 1, 64) == false) && (common.validateStrArray(command.userids, 1, 128) == false)) { err = 'Invalid usernames'; } // Username is between 1 and 64 characters
5294 + else {
5295 + if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
5296 + mesh = parent.meshes[command.meshid];
5297 + meshIdSplit = command.meshid.split('/');
5298 + if (mesh == null) { err = 'Unknown group'; }
5299 + else if (((selfMeshRights = parent.GetMeshRights(user, mesh)) & MESHRIGHT_MANAGEUSERS) == 0) { err = 'Permission denied'; }
5300 + else if ((meshIdSplit.length != 3) || (meshIdSplit[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
5301 + }
5302 + } catch (ex) { err = 'Validation exception: ' + ex; }
5303 +
5304 + // Handle any errors
5305 + if (err != null) {
5306 + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: err })); } catch (ex) { } }
5307 + return;
5308 + }
5309 +
5310 + // Convert user names to userid's
5311 + if (command.userids == null) {
5312 + command.userids = [];
5313 + for (var i in command.usernames) {
5314 + if (parent.users['user/' + domain.id + '/' + command.usernames[i].toLowerCase()] != null) { command.userids.push('user/' + domain.id + '/' + command.usernames[i].toLowerCase()); }
5315 + else if (parent.users['user/' + domain.id + '/' + command.usernames[i]] != null) { command.userids.push('user/' + domain.id + '/' + command.usernames[i]); }
5316 + }
5317 + }
5318 + var unknownUsers = [], successCount = 0, failCount = 0, msgs = [];
5319 + for (var i in command.userids) {
5320 + // Check if the user exists
5321 + var newuserid = command.userids[i], newuser = null;
5322 + if (newuserid.startsWith('user/')) { newuser = parent.users[newuserid]; }
5323 + else if (newuserid.startsWith('ugrp/')) { newuser = parent.userGroups[newuserid]; }
5324 +
5325 + // Search for a user name in that windows domain is the username starts with *\
5326 + if ((newuser == null) && (newuserid.startsWith('user/' + domain.id + '/*\\')) == true) {
5327 + var search = newuserid.split('/')[2].substring(1);
5328 + 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; } }
5329 + }
5330 +
5331 + // Make sure this user is in the same domain as the device group
5332 + if (meshIdSplit[1] != newuserid.split('/')[1]) { msgs.push("Mismatch domains"); continue; }
5333 +
5334 + if (newuser != null) {
5335 + // Can't add or modify self
5336 + if (newuserid == obj.user._id) { msgs.push("Can't change self"); continue; }
5337 +
5338 + var targetMeshRights = 0;
5339 + if ((newuser.links != null) && (newuser.links[command.meshid] != null) && (newuser.links[command.meshid].rights != null)) { targetMeshRights = newuser.links[command.meshid].rights; }
5340 + 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
5341 +
5342 + if (command.remove === true) {
5343 + // Remove mesh from user or user group
5344 + delete newuser.links[command.meshid];
5345 + } else {
5346 + // Adjust rights since we can't add more rights that we have outself for MESHRIGHT_MANAGEUSERS
5347 + if ((selfMeshRights != MESHRIGHT_ADMIN) && (command.meshadmin == MESHRIGHT_ADMIN)) { msgs.push("Can't set device group administrator, if not administrator"); continue; }
5348 + if (((selfMeshRights & 2) == 0) && ((command.meshadmin & 2) != 0) && ((targetMeshRights & 2) == 0)) { command.meshadmin -= 2; }
5349 +
5350 + // Add mesh to user or user group
5351 + if (newuser.links == null) { newuser.links = {}; }
5352 + if (newuser.links[command.meshid]) { newuser.links[command.meshid].rights = command.meshadmin; } else { newuser.links[command.meshid] = { rights: command.meshadmin }; }
5353 + }
5354 + if (newuserid.startsWith('user/')) { db.SetUser(newuser); }
5355 + else if (newuserid.startsWith('ugrp/')) { db.Set(newuser); }
5356 + parent.parent.DispatchEvent([newuser._id], obj, 'resubscribe');
5357 +
5358 + if (newuserid.startsWith('user/')) {
5359 + // Notify user change
5360 + var targets = ['*', 'server-users', user._id, newuser._id];
5361 + var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(newuser), action: 'accountchange', msgid: 78, msgArgs: [newuser.name], msg: 'Device group membership changed: ' + newuser.name, domain: domain.id };
5362 + 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.
5363 + parent.parent.DispatchEvent(targets, obj, event);
5364 + } else if (newuserid.startsWith('ugrp/')) {
5365 + // Notify user group change
5366 + var targets = ['*', 'server-ugroups', user._id, newuser._id];
5367 + var event = { etype: 'ugrp', username: user.name, ugrpid: newuser._id, name: newuser.name, desc: newuser.desc, action: 'usergroupchange', links: newuser.links, msgid: 79, msgArgs: [newuser.name], msg: 'User group changed: ' + newuser.name, domain: domain.id };
5368 + 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.
5369 + parent.parent.DispatchEvent(targets, obj, event);
5370 + }
5371 +
5372 + var event;
5373 + if (command.remove === true) {
5374 + // Remove userid from the mesh
5375 + delete mesh.links[newuserid];
5376 + db.Set(mesh);
5377 + event = { etype: 'mesh', username: newuser.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + newuser.name + ' from device group ' + mesh.name, domain: domain.id, invite: mesh.invite };
5378 + } else {
5379 + // Add userid to the mesh
5380 + mesh.links[newuserid] = { name: newuser.name, rights: command.meshadmin };
5381 + db.Set(mesh);
5382 + event = { etype: 'mesh', username: newuser.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to device group ' + mesh.name, domain: domain.id, invite: mesh.invite };
5383 + }
5384 +
5385 + // Notify mesh change
5386 + 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.
5387 + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id, newuserid]), obj, event);
5388 + if (command.remove === true) { msgs.push("Removed user " + newuserid.split('/')[2]); } else { msgs.push("Added user " + newuserid.split('/')[2]); }
5389 + successCount++;
5390 + } else {
5391 + msgs.push("Unknown user " + newuserid.split('/')[2]);
5392 + unknownUsers.push(newuserid.split('/')[2]);
5393 + failCount++;
5394 + }
5395 + }
5396 +
5397 + if ((successCount == 0) && (failCount == 0)) { msgs.push("Nothing done"); }
5398 +
5399 + if (unknownUsers.length > 0) {
5400 + // Send error back, user not found.
5401 + displayNotificationMessage('User' + ((unknownUsers.length > 1) ? 's' : '') + ' ' + EscapeHtml(unknownUsers.join(', ')) + ' not found.', "Device Group", 'ServerNotify', 5, (unknownUsers.length > 1) ? 16 : 15, [EscapeHtml(unknownUsers.join(', '))]);
5402 + }
5403 +
5404 + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: msgs.join(', '), success: successCount, failed: failCount })); } catch (ex) { } }
5405 + }
5406 +
5407 function serverCommandAddUser(command) {
5408 // If the email is the username, set this here.
5409 if (domain.usernameisemail) { if (command.email) { command.username = command.email; } else { command.email = command.username; } }
@@ -5703,6 +5691,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5691 if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addusertousergroup', responseid: command.responseid, result: 'ok', added: addedCount, failed: failCount })); } catch (ex) { } }
5692 }
5693
5694 + function serverCommandAgentDisconnect(command) {
5695 + if (common.validateInt(command.disconnectMode) == false) return; // Check disconnect mode
5696 +
5697 + // Get the node and the rights for this node
5698 + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
5699 + if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != SITERIGHT_ADMIN))) return;
5700 +
5701 + // Force mesh agent disconnection
5702 + parent.forceMeshAgentDisconnect(user, domain, node._id, command.disconnectMode);
5703 + });
5704 + }
5705 +
5706 function serverCommandAuthCookie(command) {
5707 try {
5708 ws.send(JSON.stringify({