mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
First version with user groups enforcement.
This commit is contained in:
parent
214e2bbd56
commit
17a580c4e8
141
meshuser.js
141
meshuser.js
@ -715,7 +715,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
var docs = [];
|
var docs = [];
|
||||||
for (i in parent.users) {
|
for (i in parent.users) {
|
||||||
if ((parent.users[i].domain == domain.id) && (parent.users[i].name != '~')) {
|
if ((parent.users[i].domain == domain.id) && (parent.users[i].name != '~')) {
|
||||||
docs.push(parent.CloneSafeUser(parent.users[i]));
|
// If we are part of a user group, we can only see other members of our own group
|
||||||
|
if ((user.groups == null) || (user.groups.length == 0) || ((parent.users[i].groups != null) && (findOne(parent.users[i].groups, user.groups)))) {
|
||||||
|
docs.push(parent.CloneSafeUser(parent.users[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try { ws.send(JSON.stringify({ action: 'users', users: docs, tag: command.tag })); } catch (ex) { }
|
try { ws.send(JSON.stringify({ action: 'users', users: docs, tag: command.tag })); } catch (ex) { }
|
||||||
@ -723,7 +726,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
}
|
}
|
||||||
case 'changeemail':
|
case 'changeemail':
|
||||||
{
|
{
|
||||||
// Change the email address
|
// Change our own email address
|
||||||
if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) return;
|
if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) return;
|
||||||
if (common.validateEmail(command.email, 1, 256) == false) return;
|
if (common.validateEmail(command.email, 1, 256) == false) return;
|
||||||
if (parent.users[req.session.userid].email != command.email) {
|
if (parent.users[req.session.userid].email != command.email) {
|
||||||
@ -746,7 +749,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
} else {
|
} else {
|
||||||
message.msg = 'Set email of user ' + user.name + ' to ' + user.email;
|
message.msg = 'Set email of user ' + user.name + ' to ' + user.email;
|
||||||
}
|
}
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, message);
|
|
||||||
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, message);
|
||||||
|
|
||||||
// Send the verification email
|
// Send the verification email
|
||||||
if (parent.parent.mailserver != null) { parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); }
|
if (parent.parent.mailserver != null) { parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); }
|
||||||
@ -773,10 +779,36 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
if ((user.siteadmin & 2) == 0) break;
|
if ((user.siteadmin & 2) == 0) break;
|
||||||
if (parent.parent.multiServer == null) {
|
if (parent.parent.multiServer == null) {
|
||||||
// No peering, use simple session counting
|
// No peering, use simple session counting
|
||||||
for (i in parent.wssessions) { if (parent.wssessions[i][0].domainid == domain.id) { wssessions[i] = parent.wssessions[i].length; } }
|
for (i in parent.wssessions) {
|
||||||
|
if (parent.wssessions[i][0].domainid == domain.id) {
|
||||||
|
if ((user.groups == null) || (user.groups.length == 0)) {
|
||||||
|
// No user groups, count everything
|
||||||
|
wssessions[i] = parent.wssessions[i].length;
|
||||||
|
} else {
|
||||||
|
// Only count if session is for a user in our user groups
|
||||||
|
var sessionUser = parent.users[parent.wssessions[i][0].userid];
|
||||||
|
if ((sessionUser != null) && findOne(sessionUser.groups, user.groups)) {
|
||||||
|
wssessions[i] = parent.wssessions[i].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// We have peer servers, use more complex session counting
|
// We have peer servers, use more complex session counting
|
||||||
for (i in parent.sessionsCount) { if (i.split('/')[1] == domain.id) { wssessions[i] = parent.sessionsCount[i]; } }
|
for (i in parent.sessionsCount) {
|
||||||
|
if (i.split('/')[1] == domain.id) {
|
||||||
|
if ((user.groups == null) || (user.groups.length == 0)) {
|
||||||
|
// No user groups, count everything
|
||||||
|
wssessions[i] = parent.sessionsCount[i];
|
||||||
|
} else {
|
||||||
|
// Only count if session is for a user in our user groups
|
||||||
|
var sessionUser = parent.users[i];
|
||||||
|
if ((sessionUser != null) && findOne(sessionUser.groups, user.groups)) {
|
||||||
|
wssessions[i] = parent.sessionsCount[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try { ws.send(JSON.stringify({ action: 'wssessioncount', wssessions: wssessions, tag: command.tag })); } catch (ex) { } // wssessions is: userid --> count
|
try { ws.send(JSON.stringify({ action: 'wssessioncount', wssessions: wssessions, tag: command.tag })); } catch (ex) { } // wssessions is: userid --> count
|
||||||
break;
|
break;
|
||||||
@ -789,6 +821,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
var delusersplit = command.userid.split('/'), deluserid = command.userid, deluser = parent.users[deluserid];
|
var delusersplit = command.userid.split('/'), deluserid = command.userid, deluser = parent.users[deluserid];
|
||||||
if ((deluser == null) || (delusersplit.length != 3) || (delusersplit[1] != domain.id)) break; // Invalid domain, operation only valid for current domain
|
if ((deluser == null) || (delusersplit.length != 3) || (delusersplit[1] != domain.id)) break; // Invalid domain, operation only valid for current domain
|
||||||
if ((deluser.siteadmin != null) && (deluser.siteadmin > 0) && (user.siteadmin != 0xFFFFFFFF)) break; // Need full admin to remote another administrator
|
if ((deluser.siteadmin != null) && (deluser.siteadmin > 0) && (user.siteadmin != 0xFFFFFFFF)) break; // Need full admin to remote another administrator
|
||||||
|
if ((user.groups != null) && (user.groups.length > 0) && ((deluser.groups == null) || (findOne(deluser.groups, user.groups) == false))) break; // Can only perform this operation on other users of our group.
|
||||||
|
|
||||||
// Remove all the mesh links to this user
|
// Remove all the mesh links to this user
|
||||||
if (deluser.links != null) {
|
if (deluser.links != null) {
|
||||||
@ -816,7 +849,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
|
|
||||||
db.Remove(deluserid);
|
db.Remove(deluserid);
|
||||||
delete parent.users[deluserid];
|
delete parent.users[deluserid];
|
||||||
parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', userid: deluserid, username: deluser.name, action: 'accountremove', msg: 'Account removed', domain: domain.id });
|
|
||||||
|
var targets = ['*', 'server-users'];
|
||||||
|
if (deluser.groups) { for (var i in deluser.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', userid: deluserid, username: deluser.name, action: 'accountremove', msg: 'Account removed', domain: domain.id });
|
||||||
parent.parent.DispatchEvent([deluserid], obj, 'close');
|
parent.parent.DispatchEvent([deluserid], obj, 'close');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -833,7 +869,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
// Send the notification on all user sessions for this server
|
// Send the notification on all user sessions for this server
|
||||||
for (var i in parent.wssessions2) {
|
for (var i in parent.wssessions2) {
|
||||||
try {
|
try {
|
||||||
if (parent.wssessions2[i].domainid == domain.id) { parent.wssessions2[i].send(JSON.stringify(notification)); }
|
if (parent.wssessions2[i].domainid == domain.id) {
|
||||||
|
if ((user.groups == null) || (user.groups.length == 0)) {
|
||||||
|
// We are part of no user groups, send to everyone.
|
||||||
|
parent.wssessions2[i].send(JSON.stringify(notification));
|
||||||
|
} else {
|
||||||
|
// We are part of user groups, only send to sessions of users in our groups.
|
||||||
|
var sessionUser = parent.users[parent.wssessions2[i].userid];
|
||||||
|
if ((sessionUser != null) && findOne(sessionUser.groups, user.groups)) {
|
||||||
|
parent.wssessions2[i].send(JSON.stringify(notification));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (ex) { }
|
} catch (ex) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,6 +917,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
var newuser = { type: 'user', _id: newuserid, name: newusername, creation: Math.floor(Date.now() / 1000), domain: domain.id };
|
var newuser = { type: 'user', _id: newuserid, name: newusername, creation: Math.floor(Date.now() / 1000), domain: domain.id };
|
||||||
if (command.email != null) { newuser.email = command.email; } // Email
|
if (command.email != null) { newuser.email = command.email; } // Email
|
||||||
if (command.resetNextLogin === true) { newuser.passchange = -1; } else { newuser.passchange = Math.floor(Date.now() / 1000); }
|
if (command.resetNextLogin === true) { newuser.passchange = -1; } else { newuser.passchange = Math.floor(Date.now() / 1000); }
|
||||||
|
if ((user.groups != null) && (user.groups.length > 0)) { newuser.groups = user.groups; } // New account are automatically part of our groups.
|
||||||
parent.users[newuserid] = newuser;
|
parent.users[newuserid] = newuser;
|
||||||
|
|
||||||
// Create a user, generate a salt and hash the password
|
// Create a user, generate a salt and hash the password
|
||||||
@ -878,7 +926,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
newuser.salt = salt;
|
newuser.salt = salt;
|
||||||
newuser.hash = hash;
|
newuser.hash = hash;
|
||||||
db.SetUser(newuser);
|
db.SetUser(newuser);
|
||||||
parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: newusername, account: parent.CloneSafeUser(newuser), action: 'accountcreate', msg: 'Account created, email is ' + command.email, domain: domain.id });
|
|
||||||
|
var targets = ['*', 'server-users'];
|
||||||
|
if (newuser.groups) { for (var i in newuser.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: newusername, account: parent.CloneSafeUser(newuser), action: 'accountcreate', msg: 'Account created, email is ' + command.email, domain: domain.id });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -895,7 +946,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
if ((command.emailVerified === true || command.emailVerified === false) && (chguser.emailVerified != command.emailVerified)) { chguser.emailVerified = command.emailVerified; change = 1; }
|
if ((command.emailVerified === true || command.emailVerified === false) && (chguser.emailVerified != command.emailVerified)) { chguser.emailVerified = command.emailVerified; change = 1; }
|
||||||
if ((common.validateInt(command.quota, 0) || command.quota == null) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; }
|
if ((common.validateInt(command.quota, 0) || command.quota == null) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; }
|
||||||
if ((user.siteadmin == 0xFFFFFFFF) && common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; }
|
if ((user.siteadmin == 0xFFFFFFFF) && common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; }
|
||||||
|
if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) break; // Can only perform this operation on other users of our group.
|
||||||
|
|
||||||
|
// Went 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)) {
|
if ((Array.isArray(command.groups)) && (user._id != command.id)) {
|
||||||
if (command.groups.length == 0) {
|
if (command.groups.length == 0) {
|
||||||
// Remove the user groups
|
// Remove the user groups
|
||||||
@ -913,6 +967,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
|
|
||||||
// Set the user groups
|
// Set the user groups
|
||||||
if (chguser.groups != groups2) { chguser.groups = groups2; change = 1; }
|
if (chguser.groups != groups2) { chguser.groups = groups2; change = 1; }
|
||||||
|
|
||||||
|
// Add any missing groups in the target list
|
||||||
|
if (allTargetGroups == null) { allTargetGroups = []; }
|
||||||
|
for (var i in groups2) { if (allTargetGroups.indexOf(i) == -1) { allTargetGroups.push(i); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,7 +978,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
// Update the user
|
// Update the user
|
||||||
db.SetUser(chguser);
|
db.SetUser(chguser);
|
||||||
parent.parent.DispatchEvent([chguser._id], obj, 'resubscribe');
|
parent.parent.DispatchEvent([chguser._id], obj, 'resubscribe');
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id, chguser._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'Account changed: ' + chguser.name, domain: domain.id });
|
|
||||||
|
var targets = ['*', 'server-users', user._id, chguser._id];
|
||||||
|
if (allTargetGroups) { for (var i in allTargetGroups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'Account changed: ' + chguser.name, domain: domain.id });
|
||||||
}
|
}
|
||||||
if ((chguser.siteadmin) && (chguser.siteadmin != 0xFFFFFFFF) && (chguser.siteadmin & 32)) {
|
if ((chguser.siteadmin) && (chguser.siteadmin != 0xFFFFFFFF) && (chguser.siteadmin & 32)) {
|
||||||
// If the user is locked out of this account, disconnect now
|
// If the user is locked out of this account, disconnect now
|
||||||
@ -958,7 +1019,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
user.passchange = Math.floor(Date.now() / 1000);
|
user.passchange = Math.floor(Date.now() / 1000);
|
||||||
delete user.passtype;
|
delete user.passtype;
|
||||||
db.SetUser(user);
|
db.SetUser(user);
|
||||||
parent.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Account password changed: ' + user.name, domain: domain.id });
|
|
||||||
|
var targets = ['*', 'server-users'];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Account password changed: ' + user.name, domain: domain.id });
|
||||||
|
|
||||||
// Send user notification of password change
|
// Send user notification of password change
|
||||||
displayNotificationMessage('Password changed.');
|
displayNotificationMessage('Password changed.');
|
||||||
@ -975,14 +1039,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
{
|
{
|
||||||
// Change a user's password
|
// Change a user's password
|
||||||
if (user.siteadmin != 0xFFFFFFFF) break;
|
if (user.siteadmin != 0xFFFFFFFF) break;
|
||||||
if (common.validateString(command.user, 1, 256) == false) break;
|
if (common.validateString(command.userid, 1, 256) == false) break;
|
||||||
if (common.validateString(command.pass, 1, 256) == false) break;
|
if (common.validateString(command.pass, 1, 256) == false) break;
|
||||||
if ((command.hint != null) && (common.validateString(command.hint, 0, 256) == false)) break;
|
if ((command.hint != null) && (common.validateString(command.hint, 0, 256) == false)) break;
|
||||||
if (typeof command.removeMultiFactor != 'boolean') break;
|
if (typeof command.removeMultiFactor != 'boolean') break;
|
||||||
if (common.checkPasswordRequirements(command.pass, domain.passwordrequirements) == false) break; // Password does not meet requirements
|
if (common.checkPasswordRequirements(command.pass, domain.passwordrequirements) == false) break; // Password does not meet requirements
|
||||||
|
|
||||||
var chguser = parent.users['user/' + domain.id + '/' + command.user.toLowerCase()];
|
var chguser = parent.users[command.userid];
|
||||||
if (chguser) {
|
if (chguser) {
|
||||||
|
// 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;
|
||||||
|
|
||||||
// Compute the password hash & save it
|
// Compute the password hash & save it
|
||||||
require('./pass').hash(command.pass, function (err, salt, hash) {
|
require('./pass').hash(command.pass, function (err, salt, hash) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
@ -1001,7 +1068,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
if (chguser.otpkeys) { delete chguser.otpkeys; }
|
if (chguser.otpkeys) { delete chguser.otpkeys; }
|
||||||
}
|
}
|
||||||
db.SetUser(chguser);
|
db.SetUser(chguser);
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id, chguser._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'Changed account credentials.', domain: domain.id });
|
|
||||||
|
var targets = ['*', 'server-users', user._id, chguser._id];
|
||||||
|
if (chguser.groups) { for (var i in chguser.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(chguser), action: 'accountchange', msg: 'Changed account credentials.', domain: domain.id });
|
||||||
} else {
|
} else {
|
||||||
// Report that the password change failed
|
// Report that the password change failed
|
||||||
// TODO
|
// TODO
|
||||||
@ -1017,6 +1087,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
if (common.validateString(command.userid, 1, 2048) == false) break;
|
if (common.validateString(command.userid, 1, 2048) == false) break;
|
||||||
if (common.validateString(command.msg, 1, 4096) == false) break;
|
if (common.validateString(command.msg, 1, 4096) == false) break;
|
||||||
|
|
||||||
|
// Can only perform this operation on other users of our group.
|
||||||
|
var chguser = parent.users[command.userid];
|
||||||
|
if (chguser == null) break; // This user does not exists
|
||||||
|
if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) break;
|
||||||
|
|
||||||
// Create the notification message
|
// Create the notification message
|
||||||
var notification = { "action": "msg", "type": "notify", "value": "<b>" + user.name + "</b>: " + EscapeHtml(command.msg), "userid": user._id, "username": user.name };
|
var notification = { "action": "msg", "type": "notify", "value": "<b>" + user.name + "</b>: " + EscapeHtml(command.msg), "userid": user._id, "username": user.name };
|
||||||
|
|
||||||
@ -1037,6 +1112,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
// Setup a user-to-user session
|
// Setup a user-to-user session
|
||||||
if (common.validateString(command.userid, 1, 2048)) {
|
if (common.validateString(command.userid, 1, 2048)) {
|
||||||
|
|
||||||
|
// Can only perform this operation on other users of our group.
|
||||||
|
var chguser = parent.users[command.userid];
|
||||||
|
if (chguser == null) break; // This user does not exists
|
||||||
|
if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) break;
|
||||||
|
|
||||||
// Create the notification message
|
// Create the notification message
|
||||||
var notification = {
|
var notification = {
|
||||||
"action": "msg", "type": "notify", "value": "<b>" + user.name + "</b>: Chat Request, Click here to accept.", "userid": user._id, "username": user.name, "tag": 'meshmessenger/' + encodeURIComponent(command.userid) + '/' + encodeURIComponent(user._id)
|
"action": "msg", "type": "notify", "value": "<b>" + user.name + "</b>: Chat Request, Click here to accept.", "userid": user._id, "username": user.name, "tag": 'meshmessenger/' + encodeURIComponent(command.userid) + '/' + encodeURIComponent(user._id)
|
||||||
@ -1836,6 +1916,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
if (common.validateString(command.notes, 1) == false) {
|
if (common.validateString(command.notes, 1) == false) {
|
||||||
db.Remove('nt' + command.id); // Delete the note for this node
|
db.Remove('nt' + command.id); // Delete the note for this node
|
||||||
} else {
|
} else {
|
||||||
|
// Can only perform this operation on other users of our group.
|
||||||
|
var chguser = parent.users[command.id];
|
||||||
|
if (chguser == null) break; // This user does not exists
|
||||||
|
if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) break;
|
||||||
db.Set({ _id: 'nt' + command.id, type: 'note', value: command.notes }); // Set the note for this user
|
db.Set({ _id: 'nt' + command.id, type: 'note', value: command.notes }); // Set the note for this user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1873,7 +1957,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
ws.send(JSON.stringify({ action: 'otpauth-setup', success: true })); // Report success
|
ws.send(JSON.stringify({ action: 'otpauth-setup', success: true })); // Report success
|
||||||
|
|
||||||
// Notify change
|
// Notify change
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added authentication application.', domain: domain.id });
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added authentication application.', domain: domain.id });
|
||||||
} else {
|
} else {
|
||||||
ws.send(JSON.stringify({ action: 'otpauth-setup', success: false })); // Report fail
|
ws.send(JSON.stringify({ action: 'otpauth-setup', success: false })); // Report fail
|
||||||
}
|
}
|
||||||
@ -1892,7 +1978,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
ws.send(JSON.stringify({ action: 'otpauth-clear', success: true })); // Report success
|
ws.send(JSON.stringify({ action: 'otpauth-clear', success: true })); // Report success
|
||||||
|
|
||||||
// Notify change
|
// Notify change
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Removed authentication application.', domain: domain.id });
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Removed authentication application.', domain: domain.id });
|
||||||
} else {
|
} else {
|
||||||
ws.send(JSON.stringify({ action: 'otpauth-clear', success: false })); // Report fail
|
ws.send(JSON.stringify({ action: 'otpauth-clear', success: false })); // Report fail
|
||||||
}
|
}
|
||||||
@ -1927,7 +2015,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify change
|
// Notify change
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'otp-hkey-get':
|
case 'otp-hkey-get':
|
||||||
@ -1958,7 +2048,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify change
|
// Notify change
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Removed security key.', domain: domain.id });
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Removed security key.', domain: domain.id });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'otp-hkey-yubikey-add':
|
case 'otp-hkey-yubikey-add':
|
||||||
@ -2004,7 +2096,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
ws.send(JSON.stringify({ action: 'otp-hkey-yubikey-add', result: true, name: command.name, index: keyIndex }));
|
ws.send(JSON.stringify({ action: 'otp-hkey-yubikey-add', result: true, name: command.name, index: keyIndex }));
|
||||||
|
|
||||||
// Notify change TODO: Should be done on all sessions/servers for this user.
|
// Notify change TODO: Should be done on all sessions/servers for this user.
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
||||||
} else {
|
} else {
|
||||||
ws.send(JSON.stringify({ action: 'otp-hkey-yubikey-add', result: false, name: command.name }));
|
ws.send(JSON.stringify({ action: 'otp-hkey-yubikey-add', result: false, name: command.name }));
|
||||||
}
|
}
|
||||||
@ -2061,7 +2155,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
delete obj.hardwareKeyRegistrationRequest;
|
delete obj.hardwareKeyRegistrationRequest;
|
||||||
|
|
||||||
// Notify change
|
// Notify change
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: false, error: error, name: command.name, index: keyIndex }));
|
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: false, error: error, name: command.name, index: keyIndex }));
|
||||||
delete obj.hardwareKeyRegistrationRequest;
|
delete obj.hardwareKeyRegistrationRequest;
|
||||||
@ -2128,7 +2224,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: true, name: command.name, index: keyIndex }));
|
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: true, name: command.name, index: keyIndex }));
|
||||||
|
|
||||||
// Notify change
|
// Notify change
|
||||||
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
var targets = ['*', 'server-users', user._id];
|
||||||
|
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||||
|
parent.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: 'Added security key.', domain: domain.id });
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
console.log('webauthn-endregister-error', error);
|
console.log('webauthn-endregister-error', error);
|
||||||
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: false, error: error, name: command.name, index: keyIndex }));
|
ws.send(JSON.stringify({ action: 'otp-hkey-setup-response', result: false, error: error, name: command.name, index: keyIndex }));
|
||||||
@ -2360,5 +2458,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return true if at least one element of arr2 is in arr1
|
||||||
|
function findOne(arr1, arr2) { if ((arr1 == null) || (arr2 == null)) return false; return arr2.some(function (v) { return arr1.indexOf(v) >= 0; }); };
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.3.2-n",
|
"version": "0.3.2-o",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
@ -1609,12 +1609,32 @@
|
|||||||
var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
|
var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
|
||||||
var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
|
var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
|
||||||
if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
|
if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
|
||||||
|
var oldgroups = userinfo.groups;
|
||||||
userinfo = message.event.account;
|
userinfo = message.event.account;
|
||||||
if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
|
if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
|
||||||
updateSelf();
|
updateSelf();
|
||||||
|
|
||||||
|
if ((userinfo.siteadmin & 2) != 0) {
|
||||||
|
// Compare our groups
|
||||||
|
var og = oldgroups ? oldgroups : [];
|
||||||
|
var ng = userinfo.groups ? userinfo.groups : [];
|
||||||
|
if (og.join(',') != ng.join(',')) {
|
||||||
|
// Our groups have changed, re-ask for a list of users.
|
||||||
|
users = wssessions = null;
|
||||||
|
meshserver.send({ action: 'users' });
|
||||||
|
meshserver.send({ action: 'wssessioncount' });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (users == null) break;
|
if (users == null) break;
|
||||||
users[message.event.account._id] = message.event.account;
|
|
||||||
|
// Check if the account if part of our user group
|
||||||
|
if ((userinfo.groups == null) || (userinfo.groups.length == 0) || (findOne(message.event.account.groups, userinfo.groups) == true)) {
|
||||||
|
users[message.event.account._id] = message.event.account; // Part of our groups, update this user.
|
||||||
|
} else {
|
||||||
|
delete users[message.event.account._id]; // No longer part of our groups, remove this user.
|
||||||
|
}
|
||||||
|
|
||||||
updateUsers();
|
updateUsers();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -7037,7 +7057,7 @@
|
|||||||
var removeMultiFactor = false;
|
var removeMultiFactor = false;
|
||||||
if ((tag == 1) && (Q('p4twoFactorRemove').checked == true)) { removeMultiFactor = true; }
|
if ((tag == 1) && (Q('p4twoFactorRemove').checked == true)) { removeMultiFactor = true; }
|
||||||
if (Q('p4pass1').value == Q('p4pass2').value) {
|
if (Q('p4pass1').value == Q('p4pass2').value) {
|
||||||
var r = { action: 'changeuserpass', user: currentUser.name, pass: Q('p4pass1').value, removeMultiFactor: removeMultiFactor, resetNextLogin: Q('p4resetNextLogin').checked };
|
var r = { action: 'changeuserpass', userid: currentUser._id, pass: Q('p4pass1').value, removeMultiFactor: removeMultiFactor, resetNextLogin: Q('p4resetNextLogin').checked };
|
||||||
if (features & 0x00010000) { r.hint = Q('p4hint').value; }
|
if (features & 0x00010000) { r.hint = Q('p4hint').value; }
|
||||||
meshserver.send(r);
|
meshserver.send(r);
|
||||||
}
|
}
|
||||||
@ -7694,6 +7714,7 @@
|
|||||||
function validateEmail(v) { 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(v); } // New version
|
function validateEmail(v) { 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(v); } // New version
|
||||||
function isPrivateIP(a) { return (a.startsWith('10.') || a.startsWith('172.16.') || a.startsWith('192.168.')); }
|
function isPrivateIP(a) { return (a.startsWith('10.') || a.startsWith('172.16.') || a.startsWith('192.168.')); }
|
||||||
function u2fSupported() { return (window.u2f && ((navigator.userAgent.indexOf('Chrome/') > 0) || (navigator.userAgent.indexOf('Firefox/') > 0) || (navigator.userAgent.indexOf('Opera/') > 0) || (navigator.userAgent.indexOf('Safari/') > 0))); }
|
function u2fSupported() { return (window.u2f && ((navigator.userAgent.indexOf('Chrome/') > 0) || (navigator.userAgent.indexOf('Firefox/') > 0) || (navigator.userAgent.indexOf('Opera/') > 0) || (navigator.userAgent.indexOf('Safari/') > 0))); }
|
||||||
|
function findOne(arr1, arr2) { if ((arr1 == null) || (arr2 == null)) return false; return arr2.some(function (v) { return arr1.indexOf(v) >= 0; }); };
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
10
webserver.js
10
webserver.js
@ -1770,7 +1770,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
const subscriptions = [userid, 'server-global'];
|
const subscriptions = [userid, 'server-global'];
|
||||||
if (user.siteadmin != null) {
|
if (user.siteadmin != null) {
|
||||||
if (user.siteadmin == 0xFFFFFFFF) subscriptions.push('*');
|
if (user.siteadmin == 0xFFFFFFFF) subscriptions.push('*');
|
||||||
if ((user.siteadmin & 2) != 0) subscriptions.push('server-users');
|
if ((user.siteadmin & 2) != 0) {
|
||||||
|
if ((user.groups == null) || (user.groups.length == 0)) {
|
||||||
|
// Subscribe to all user changes
|
||||||
|
subscriptions.push('server-users');
|
||||||
|
} else {
|
||||||
|
// Subscribe to user changes for some groups
|
||||||
|
for (var i in user.groups) { subscriptions.push('server-users:' + i); }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (user.links != null) { for (var i in user.links) { subscriptions.push(i); } }
|
if (user.links != null) { for (var i in user.links) { subscriptions.push(i); } }
|
||||||
obj.parent.RemoveAllEventDispatch(target);
|
obj.parent.RemoveAllEventDispatch(target);
|
||||||
|
Loading…
Reference in New Issue
Block a user