mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 06:05:53 -05:00
Can now batch add users to a device group.
This commit is contained in:
parent
078745b97a
commit
b0e2914f92
@ -154,7 +154,7 @@ module.exports.validateArray = function (array, minlen, maxlen) { return ((array
|
|||||||
module.exports.validateStrArray = function (array, minlen, maxlen) { if (((array != null) && Array.isArray(array)) == false) return false; for (var i in array) { if ((typeof array[i] != 'string') && ((minlen == null) || (array[i].length >= minlen)) && ((maxlen == null) || (array[i].length <= maxlen))) return false; } return true; };
|
module.exports.validateStrArray = function (array, minlen, maxlen) { if (((array != null) && Array.isArray(array)) == false) return false; for (var i in array) { if ((typeof array[i] != 'string') && ((minlen == null) || (array[i].length >= minlen)) && ((maxlen == null) || (array[i].length <= maxlen))) return false; } return true; };
|
||||||
module.exports.validateObject = function (obj) { return ((obj != null) && (typeof obj == 'object')); };
|
module.exports.validateObject = function (obj) { return ((obj != null) && (typeof obj == 'object')); };
|
||||||
module.exports.validateEmail = function (email, minlen, maxlen) { if (module.exports.validateString(email, minlen, maxlen) == false) return false; var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(email); };
|
module.exports.validateEmail = function (email, minlen, maxlen) { if (module.exports.validateString(email, minlen, maxlen) == false) return false; var emailReg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailReg.test(email); };
|
||||||
module.exports.validateUsername = function (username, minlen, maxlen) { return (module.exports.validateString(username, minlen, maxlen) && (username.indexOf(' ') == -1)); };
|
module.exports.validateUsername = function (username, minlen, maxlen) { return (module.exports.validateString(username, minlen, maxlen) && (username.indexOf(' ') == -1) && (username.indexOf('"') == -1) && (username.indexOf(',') == -1)); };
|
||||||
|
|
||||||
// Check password requirements
|
// Check password requirements
|
||||||
module.exports.checkPasswordRequirements = function(password, requirements) {
|
module.exports.checkPasswordRequirements = function(password, requirements) {
|
||||||
|
4
db.js
4
db.js
@ -545,6 +545,10 @@ module.exports.CreateDB = function (parent, func) {
|
|||||||
obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } };
|
obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } };
|
||||||
obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }).toArray(func); };
|
obj.getLocalAmtNodes = function (func) { obj.file.find({ type: 'node', host: { $exists: true, $ne: null }, intelamt: { $exists: true } }).toArray(func); };
|
||||||
obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }).toArray(func); };
|
obj.getAmtUuidNode = function (meshid, uuid, func) { obj.file.find({ type: 'node', meshid: meshid, 'intelamt.uuid': uuid }).toArray(func); };
|
||||||
|
|
||||||
|
// TODO: Starting in MongoDB 4.0.3, you should use countDocuments() instead of count() that is deprecated. We should detect MongoDB version and switch.
|
||||||
|
// https://docs.mongodb.com/manual/reference/method/db.collection.countDocuments/
|
||||||
|
//obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.countDocuments({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
|
||||||
obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
|
obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { obj.file.count({ type: type, domain: domainid }, function (err, count) { func((err != null) || (count > max)); }); } }
|
||||||
|
|
||||||
// Database actions on the events collection
|
// Database actions on the events collection
|
||||||
|
48
meshuser.js
48
meshuser.js
@ -1478,16 +1478,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
case 'addmeshuser':
|
case 'addmeshuser':
|
||||||
{
|
{
|
||||||
if (common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
|
if (common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
|
||||||
if (common.validateString(command.username, 1, 64) == false) break; // Username is between 1 and 64 characters
|
|
||||||
if (common.validateInt(command.meshadmin) == false) break; // Mesh rights must be an integer
|
if (common.validateInt(command.meshadmin) == false) break; // Mesh rights must be an integer
|
||||||
|
if (common.validateStrArray(command.usernames, 1, 64) == false) break; // Username is between 1 and 64 characters
|
||||||
// Check if the user exists
|
|
||||||
var newuserid = 'user/' + domain.id + '/' + command.username.toLowerCase(), newuser = parent.users[newuserid];
|
|
||||||
if (newuser == null) {
|
|
||||||
// Send error back, user not found.
|
|
||||||
displayNotificationMessage('User "' + EscapeHtml(command.username) + '" not found.', 'Device Group', 'ServerNotify');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the mesh
|
// Get the mesh
|
||||||
mesh = parent.meshes[command.meshid];
|
mesh = parent.meshes[command.meshid];
|
||||||
@ -1496,20 +1488,34 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 2) == 0)) return;
|
if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 2) == 0)) return;
|
||||||
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||||
|
|
||||||
// Add mesh to user
|
var unknownUsers = [];
|
||||||
if (newuser.links == null) newuser.links = {};
|
for (var i in command.usernames) {
|
||||||
newuser.links[command.meshid] = { rights: command.meshadmin };
|
// Check if the user exists
|
||||||
db.SetUser(newuser);
|
var newuserid = 'user/' + domain.id + '/' + command.usernames[i].toLowerCase(), newuser = parent.users[newuserid];
|
||||||
parent.parent.DispatchEvent([newuser._id], obj, 'resubscribe');
|
if (newuser != null) {
|
||||||
|
// Add mesh to user
|
||||||
|
if (newuser.links == null) newuser.links = {};
|
||||||
|
newuser.links[command.meshid] = { rights: command.meshadmin };
|
||||||
|
db.SetUser(newuser);
|
||||||
|
parent.parent.DispatchEvent([newuser._id], obj, 'resubscribe');
|
||||||
|
|
||||||
// Add a user to the mesh
|
// Add a user to the mesh
|
||||||
mesh.links[newuserid] = { userid: newuser.id, name: newuser.name, rights: command.meshadmin };
|
mesh.links[newuserid] = { userid: newuser.id, name: newuser.name, rights: command.meshadmin };
|
||||||
db.Set(common.escapeLinksFieldName(mesh));
|
db.Set(common.escapeLinksFieldName(mesh));
|
||||||
|
|
||||||
// Notify mesh change
|
// Notify mesh change
|
||||||
var event = { etype: 'mesh', username: newuser.name, userid: command.userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to mesh ' + mesh.name, domain: domain.id };
|
var event = { etype: 'mesh', username: newuser.name, userid: command.userid, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to mesh ' + mesh.name, domain: domain.id };
|
||||||
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.
|
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.
|
||||||
parent.parent.DispatchEvent(['*', mesh._id, user._id, newuserid], obj, event);
|
parent.parent.DispatchEvent(['*', mesh._id, user._id, newuserid], obj, event);
|
||||||
|
} else {
|
||||||
|
unknownUsers.push(command.usernames[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unknownUsers.length > 0) {
|
||||||
|
// Send error back, user not found.
|
||||||
|
displayNotificationMessage('User' + ((unknownUsers.length > 1)?'s':'') + ' ' + EscapeHtml(unknownUsers.join(', ')) + ' not found.', 'Device Group', 'ServerNotify');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.3.5-n",
|
"version": "0.3.5-o",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -6183,7 +6183,7 @@
|
|||||||
for (var i in sortedusers) {
|
for (var i in sortedusers) {
|
||||||
var trash = '', rights = 'Partial Rights', r = sortedusers[i].rights;
|
var trash = '', rights = 'Partial Rights', r = sortedusers[i].rights;
|
||||||
if (r == 0xFFFFFFFF) rights = 'Full Administrator'; else if (r == 0) rights = 'No Rights';
|
if (r == 0xFFFFFFFF) rights = 'Full Administrator'; else if (r == 0) rights = 'No Rights';
|
||||||
if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") title="Remote user rights to this mesh" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
|
if ((sortedusers[i].id != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") title="Remote user rights to this mesh" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
|
||||||
x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td><div title="User" class=m2></div><div> ' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div></td><td><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
|
x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td><div title="User" class=m2></div><div> ' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div></td><td><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
@ -6335,10 +6335,10 @@
|
|||||||
|
|
||||||
function p20showAddMeshUserDialog() {
|
function p20showAddMeshUserDialog() {
|
||||||
if (xxdialogMode) return;
|
if (xxdialogMode) return;
|
||||||
var x = "Allow a user to manage this device group and devices in this group.";
|
var x = "Allow users to manage this device group and devices in this group.";
|
||||||
if (features & 0x00080000) { x += " Users need to login to this server once before they can be added to a device group." }
|
if (features & 0x00080000) { x += " Users need to login to this server once before they can be added to a device group." }
|
||||||
x += "<br /><br />";
|
x += "<br /><br />";
|
||||||
x += addHtmlValue('User Name', '<input id=dp20username style=width:230px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() />');
|
x += addHtmlValue('User Names', '<input id=dp20username style=width:230px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() placeholder="user1, user2, user3" />');
|
||||||
x += '<br><div style="height:120px;overflow-y:scroll;border:1px solid gray">';
|
x += '<br><div style="height:120px;overflow-y:scroll;border:1px solid gray">';
|
||||||
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Full Administrator<br>';
|
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20fulladmin>Full Administrator<br>';
|
||||||
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>Edit Device Group<br>';
|
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editmesh>Edit Device Group<br>';
|
||||||
@ -6355,14 +6355,16 @@
|
|||||||
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Wake Devices<br>';
|
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Wake Devices<br>';
|
||||||
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Device Notes<br>';
|
x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Device Notes<br>';
|
||||||
x += '</div>';
|
x += '</div>';
|
||||||
setDialogMode(2, "Add User to Device Group", 3, p20showAddMeshUserDialogEx, x);
|
setDialogMode(2, "Add Users to Device Group", 3, p20showAddMeshUserDialogEx, x);
|
||||||
p20validateAddMeshUserDialog();
|
p20validateAddMeshUserDialog();
|
||||||
Q('dp20username').focus();
|
Q('dp20username').focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function p20validateAddMeshUserDialog() {
|
function p20validateAddMeshUserDialog() {
|
||||||
var meshrights = currentMesh.links[userinfo._id].rights;
|
var meshrights = currentMesh.links[userinfo._id].rights;
|
||||||
QE('idx_dlgOkButton', (Q('dp20username').value.length > 0));
|
var ok = true, users = Q('dp20username').value.split(',');
|
||||||
|
for (var i in users) { var user = users[i].trim(); if (user.length == 0) { ok = false; } else if (user.indexOf('"') >= 0) { ok = false; } }
|
||||||
|
QE('idx_dlgOkButton', ok);
|
||||||
QE('p20fulladmin', meshrights == 0xFFFFFFFF);
|
QE('p20fulladmin', meshrights == 0xFFFFFFFF);
|
||||||
QE('p20editmesh', (!Q('p20fulladmin').checked) && (meshrights == 0xFFFFFFFF));
|
QE('p20editmesh', (!Q('p20fulladmin').checked) && (meshrights == 0xFFFFFFFF));
|
||||||
QE('p20manageusers', !Q('p20fulladmin').checked);
|
QE('p20manageusers', !Q('p20fulladmin').checked);
|
||||||
@ -6396,7 +6398,10 @@
|
|||||||
if (Q('p20noamt').checked == true) meshadmin += 2048;
|
if (Q('p20noamt').checked == true) meshadmin += 2048;
|
||||||
if (Q('p20remotelimitedinput').checked == true) meshadmin += 4096;
|
if (Q('p20remotelimitedinput').checked == true) meshadmin += 4096;
|
||||||
}
|
}
|
||||||
meshserver.send({ action: 'addmeshuser', meshid: currentMesh._id, meshname: currentMesh.name, username: Q('dp20username').value , meshadmin: meshadmin});
|
|
||||||
|
var users = Q('dp20username').value.split(','), users2 = [];
|
||||||
|
for (var i in users) { users2.push(users[i].trim()); }
|
||||||
|
meshserver.send({ action: 'addmeshuser', meshid: currentMesh._id, meshname: currentMesh.name, usernames: users2, meshadmin: meshadmin });
|
||||||
}
|
}
|
||||||
|
|
||||||
function p20viewuser(userid) {
|
function p20viewuser(userid) {
|
||||||
@ -6421,9 +6426,9 @@
|
|||||||
r = r.substring(2);
|
r = r.substring(2);
|
||||||
if (r == '') { r = 'No Rights'; }
|
if (r == '') { r = 'No Rights'; }
|
||||||
var uname = userid.split('/')[2];
|
var uname = userid.split('/')[2];
|
||||||
if (users) { uname = users[userid].name; }
|
if (users && users[userid]) { uname = users[userid].name; }
|
||||||
if (userinfo._id == userid) { uname = userinfo.name; }
|
if (userinfo._id == userid) { uname = userinfo.name; }
|
||||||
var buttons = 1, x = addHtmlValue('User Name', EscapeHtml(uname));
|
var buttons = 1, x = addHtmlValue('User Name', EscapeHtml(decodeURIComponent(uname)));
|
||||||
if (userid.split('/')[2] != uname) { x += addHtmlValue('User Identifier', EscapeHtml(userid.split('/')[2])); }
|
if (userid.split('/')[2] != uname) { x += addHtmlValue('User Identifier', EscapeHtml(userid.split('/')[2])); }
|
||||||
|
|
||||||
x += addHtmlValue('Permissions', r);
|
x += addHtmlValue('Permissions', r);
|
||||||
@ -6431,9 +6436,15 @@
|
|||||||
setDialogMode(2, "Device Group User", buttons, p20viewuserEx, x, userid);
|
setDialogMode(2, "Device Group User", buttons, p20viewuserEx, x, userid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, "Confirm removal of user " + userid.split('/')[2] + "?", userid); }
|
function p20viewuserEx(button, userid) {
|
||||||
|
if (button != 2) return;
|
||||||
|
var uname = userid.split('/')[2];
|
||||||
|
if (users && users[userid]) { uname = users[userid].name; }
|
||||||
|
if (userinfo._id == userid) { uname = userinfo.name; }
|
||||||
|
setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, "Confirm removal of user " + EscapeHtml(decodeURIComponent(uname)) + "?", userid);
|
||||||
|
}
|
||||||
function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
|
function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
|
||||||
function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid}); }
|
function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// MY FILES
|
// MY FILES
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -391,7 +391,7 @@
|
|||||||
|
|
||||||
function validateCreate(box,e) {
|
function validateCreate(box,e) {
|
||||||
setDialogMode(0);
|
setDialogMode(0);
|
||||||
var ok = ((Q('ausername').value.length > 0) && (Q('ausername').value.indexOf(' ') == -1) && (validateEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
|
var ok = ((Q('ausername').value.length > 0) && (Q('ausername').value.indexOf('"') == -1) && (Q('ausername').value.indexOf(',') == -1) && (Q('ausername').value.indexOf(' ') == -1) && (validateEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
|
||||||
if ((newAccountPass == 1) && (Q('anewaccountpass').value.length == 0)) { ok = false; }
|
if ((newAccountPass == 1) && (Q('anewaccountpass').value.length == 0)) { ok = false; }
|
||||||
if (Q('apassword1').value == '') {
|
if (Q('apassword1').value == '') {
|
||||||
QH('passWarning', '');
|
QH('passWarning', '');
|
||||||
|
@ -402,7 +402,7 @@
|
|||||||
|
|
||||||
function validateCreate(box, e) {
|
function validateCreate(box, e) {
|
||||||
setDialogMode(0);
|
setDialogMode(0);
|
||||||
var userok = (Q('ausername').value.length > 0) && (Q('ausername').value.indexOf(' ') == -1);
|
var userok = (Q('ausername').value.length > 0) && (Q('ausername').value.indexOf(' ') == -1) && (Q('ausername').value.indexOf('"') == -1) && (Q('ausername').value.indexOf(',') == -1);
|
||||||
var emailok = (validateEmail(Q('aemail').value) == true);
|
var emailok = (validateEmail(Q('aemail').value) == true);
|
||||||
var pass1ok = (Q('apassword1').value.length > 0);
|
var pass1ok = (Q('apassword1').value.length > 0);
|
||||||
var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
|
var pass2ok = (Q('apassword2').value.length > 0) && (Q('apassword2').value == Q('apassword1').value);
|
||||||
|
Loading…
Reference in New Issue
Block a user