User permission fixes, user list export feature.
This commit is contained in:
parent
dfdded4c3b
commit
d8548920bc
27
meshuser.js
27
meshuser.js
|
@ -61,7 +61,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
var user = parent.users[obj.user._id];
|
||||
if (user) {
|
||||
if (parent.parent.multiServer == null) {
|
||||
parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: obj.user.name, count: parent.wssessions[obj.user._id].length, nolog: 1, domain: domain.id });
|
||||
var targets = ['*', 'server-users'];
|
||||
if (obj.user.groups) { for (var i in obj.user.groups) { targets.push('server-users:' + i); } }
|
||||
parent.parent.DispatchEvent(targets, obj, { action: 'wssessioncount', username: obj.user.name, count: parent.wssessions[obj.user._id].length, nolog: 1, domain: domain.id });
|
||||
} else {
|
||||
parent.recountSessions(ws.sessionId); // Recount sessions
|
||||
}
|
||||
|
@ -203,7 +205,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
parent.wssessions2[ws.sessionId] = ws;
|
||||
if (!parent.wssessions[user._id]) { parent.wssessions[user._id] = [ws]; } else { parent.wssessions[user._id].push(ws); }
|
||||
if (parent.parent.multiServer == null) {
|
||||
parent.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: user.name, count: parent.wssessions[user._id].length, nolog: 1, domain: domain.id });
|
||||
var targets = ['*', 'server-users'];
|
||||
if (obj.user.groups) { for (var i in obj.user.groups) { targets.push('server-users:' + i); } }
|
||||
parent.parent.DispatchEvent(targets, obj, { action: 'wssessioncount', username: user.name, count: parent.wssessions[user._id].length, nolog: 1, domain: domain.id });
|
||||
} else {
|
||||
parent.recountSessions(ws.sessionId); // Recount sessions
|
||||
}
|
||||
|
@ -1004,15 +1008,28 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
var chguser = parent.users[command.id];
|
||||
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;
|
||||
|
||||
// Can only perform this operation on other users of our group.
|
||||
if (user.siteadmin != 0xFFFFFFFF) {
|
||||
if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) return;
|
||||
}
|
||||
|
||||
// Validate input
|
||||
if (common.validateString(command.email, 1, 256) && (chguser.email != command.email)) { chguser.email = command.email; change = 1; }
|
||||
|
||||
// Make changes
|
||||
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 ((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.
|
||||
|
||||
// Site admins can change any server rights, user managers can only change AccountLock, NoMeshCmd and NoNewGroups
|
||||
var chgusersiteadmin = chguser.siteadmin ? chguser.siteadmin : 0;
|
||||
if (((user.siteadmin == 0xFFFFFFFF) || ((user.siteadmin & 2) && (((chgusersiteadmin ^ command.siteadmin) & 0xFFFFFF1F) == 0))) && common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; }
|
||||
|
||||
// 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) || (user.siteadmin == 0xFFFFFFFF))) {
|
||||
if (command.groups.length == 0) {
|
||||
// Remove the user groups
|
||||
if (chguser.groups != null) { delete chguser.groups; change = 1; }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.3.3-r",
|
||||
"version": "0.3.3-s",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -300,6 +300,7 @@
|
|||
<td class="style14">
|
||||
<div style="float:right">
|
||||
<input type=button onclick=showUserBroadcastDialog() style=margin-right:6px value="Broadcast" />
|
||||
<img onclick=p4downloadUserInfo() style="cursor:pointer" title="Download user information" src="images/link4.png" />
|
||||
</div>
|
||||
<div>
|
||||
<input id=UserNewAccountButton type=button style=margin-left:6px onclick=showCreateNewAccountDialog() value="New Account..." />
|
||||
|
@ -1252,6 +1253,7 @@
|
|||
function addLetterS(x) { return (x > 1) ? 's' : ''; }
|
||||
|
||||
function onMessage(server, message) {
|
||||
console.log(message);
|
||||
switch (message.action) {
|
||||
case 'serverstats': {
|
||||
updateGeneralServerStats(message);
|
||||
|
@ -6820,6 +6822,35 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
function p4downloadUserInfo() {
|
||||
if (xxdialogMode) return;
|
||||
var x = 'Download the list of users with one of the file formats below.<br /><br />';
|
||||
x += addHtmlValue('CSV Format', '<a style=cursor:pointer onclick=p4downloadUserInfoCSV()>userlist.csv</a>');
|
||||
x += addHtmlValue('JSON Format', '<a style=cursor:pointer onclick=p4downloadUserInfoJSON()>userlist.json</a>');
|
||||
setDialogMode(2, "User List Export", 1, null, x);
|
||||
}
|
||||
|
||||
function p4downloadUserInfoCSV() {
|
||||
var csv = "id, name, email, creation, lastlogin, groups, authfactors\r\n";
|
||||
for (var i in users) {
|
||||
var multiFactor = false, factors = [];
|
||||
if ((users[i].otpsecret > 0) || (users[i].otphkeys > 0)) {
|
||||
multiFactor = true;
|
||||
if (users[i].otpsecret > 0) { factors.push('AuthApp'); }
|
||||
if (users[i].otphkeys > 0) { factors.push('SecurityKey'); }
|
||||
if (users[i].otpkeys > 0) { factors.push('BackupCodes'); }
|
||||
}
|
||||
csv += '\"' + users[i]._id + '\",\"' + users[i].name + '\",\"' + (users[i].email ? users[i].email : '') + '\",\"' + (users[i].creation ? new Date(users[i].creation * 1000) : '') + '\",\"' + (users[i].login ? new Date(users[i].login * 1000) : '') + '\",\"' + (users[i].groups ? users[i].groups.join(',') : '') + '\",\"' + (multiFactor ? factors.join(',') : '') + '\"\r\n';
|
||||
}
|
||||
saveAs(new Blob([csv], { type: "application/octet-stream" }), "userlist.csv");
|
||||
}
|
||||
|
||||
function p4downloadUserInfoJSON() {
|
||||
var r = []
|
||||
for (var i in users) { r.push(users[i]); }
|
||||
saveAs(new Blob([JSON.stringify(r)], { type: "application/octet-stream" }), "userlist.json");
|
||||
}
|
||||
|
||||
function showUserBroadcastDialog() {
|
||||
if (xxdialogMode) return;
|
||||
var x = 'Broadcast a message to all connected users.<textarea id=broadcastMessage value="" maxlength="256"/></textarea>';
|
||||
|
@ -6923,10 +6954,11 @@
|
|||
QE('ua_manageusers', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_serverrestore', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_fileaccess', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_fileaccessquota', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_serverupdate', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_lockedaccount', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_nonewgroups', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_nomeshcmd', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QE('ua_lockedaccount', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id));
|
||||
QE('ua_nonewgroups', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id));
|
||||
QE('ua_nomeshcmd', (userinfo.siteadmin & 2) && (user.siteadmin != 0xFFFFFFFF) && (userinfo._id != user._id));
|
||||
Q('ua_fileaccessquota').value = (user.quota != null)?(user.quota / 1024):'';
|
||||
showUserAdminDialogValidate();
|
||||
return false;
|
||||
|
@ -6994,7 +7026,11 @@
|
|||
var email = user.email?EscapeHtml(user.email):'<i>Not set</i>', everify = '';
|
||||
if (serverinfo.emailcheck) { everify = ((user.emailVerified == true)?'<b style=color:green;cursor:pointer title="Email is verified">🗸</b> ':'<b style=color:red;cursor:pointer title="Email not verified">🗴</b> '); }
|
||||
if (user.name.toLowerCase() != user._id.split('/')[2]) { x += addDeviceAttribute('User Identifier', user._id.split('/')[2]); }
|
||||
if ((user.siteadmin != 0xFFFFFFFF) || (userinfo.siteadmin == 0xFFFFFFFF)) { // If we are not site admin, we can't change a admin email.
|
||||
x += addDeviceAttribute('Email', everify + "<a style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"" + userid + "\")>" + email + '</a> <a style=cursor:pointer onclick=doemail(event,\"' + user.email + '\")><img class=hoverButton src="images/link1.png" /></a>');
|
||||
} else {
|
||||
x += addDeviceAttribute('Email', everify + email + ' <a style=cursor:pointer onclick=doemail(event,\"' + user.email + '\")><img class=hoverButton src="images/link1.png" /></a>');
|
||||
}
|
||||
x += addDeviceAttribute('Server Rights', premsg + "<a style=cursor:pointer onclick=showUserAdminDialog(event,\"" + userid + "\")>" + msg.join(', ') + "</a>");
|
||||
if (user.quota) x += addDeviceAttribute('Server Quota', EscapeHtml(parseInt(user.quota) / 1024) + ' k');
|
||||
x += addDeviceAttribute('Creation', new Date(user.creation * 1000).toLocaleString());
|
||||
|
@ -7013,7 +7049,7 @@
|
|||
// User Groups
|
||||
var userGroups = '<i>None</i>';
|
||||
if (user.groups) { userGroups = ''; for (var i in user.groups) { userGroups += '<span class="tagSpan">' + user.groups[i] + '</span>'; } }
|
||||
x += addDeviceAttribute('User Groups', addLinkConditional(userGroups, 'showUserGroupDialog(event,\"' + userid + '\")', ((userinfo.groups == null) && (userinfo.siteadmin & 2) && (userinfo._id != user._id))));
|
||||
x += addDeviceAttribute('User Groups', addLinkConditional(userGroups, 'showUserGroupDialog(event,\"' + userid + '\")', (userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.groups == null) && (userinfo.siteadmin & 2) && (userinfo._id != user._id) && (user._id != 0xFFFFFFFF))));
|
||||
|
||||
var multiFactor = 0;
|
||||
if ((user.otpsecret > 0) || (user.otphkeys > 0)) {
|
||||
|
@ -7070,7 +7106,7 @@
|
|||
if (serverinfo.emailcheck) { x += addHtmlValue('Status', '<select id=dp30verified style=width:230px onchange=p30validateEmail()><option value=0>Not verified</option><option value=1>Verified</option></select>'); }
|
||||
setDialogMode(2, "Change Email for " + EscapeHtml(currentUser.name), 3, p30showUserEmailChangeDialogEx, x);
|
||||
Q('dp30email').focus();
|
||||
Q('dp30email').value = currentUser.email;
|
||||
Q('dp30email').value = (currentUser.email?currentUser.email:'');
|
||||
if (serverinfo.emailcheck) { Q('dp30verified').value = currentUser.emailVerified?1:0; }
|
||||
p30validateEmail();
|
||||
}
|
||||
|
|
27
webserver.js
27
webserver.js
|
@ -727,7 +727,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
// Save login time
|
||||
user.login = Math.floor(Date.now() / 1000);
|
||||
obj.db.SetUser(user);
|
||||
obj.parent.DispatchEvent(['*'], obj, { etype: 'user', username: user.name, account: obj.CloneSafeUser(user), action: 'login', msg: 'Account login', domain: domain.id });
|
||||
|
||||
// Notify account login
|
||||
var targets = ['*', 'server-users'];
|
||||
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||
obj.parent.DispatchEvent(targets, obj, { etype: 'user', username: user.name, account: obj.CloneSafeUser(user), action: 'login', msg: 'Account login', domain: domain.id });
|
||||
|
||||
// Regenerate session when signing in to prevent fixation
|
||||
//req.session.regenerate(function () {
|
||||
|
@ -3027,7 +3031,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (oldcount == null) { oldcount = 0; } else { delete obj.sessionsCount[userid]; }
|
||||
if (newcount != oldcount) {
|
||||
x = userid.split('/');
|
||||
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
|
||||
var u = users[userid];
|
||||
if (u) {
|
||||
var targets = ['*', 'server-users'];
|
||||
if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } }
|
||||
obj.parent.DispatchEvent(targets, obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3036,7 +3045,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
oldcount = obj.sessionsCount[userid];
|
||||
if ((oldcount != null) && (oldcount != 0)) {
|
||||
x = userid.split('/');
|
||||
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: 0, domain: x[1], nolog: 1, nopeers: 1 });
|
||||
var u = users[userid];
|
||||
if (u) {
|
||||
var targets = ['*', 'server-users'];
|
||||
if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } }
|
||||
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: 0, domain: x[1], nolog: 1, nopeers: 1 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3056,10 +3070,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
// If the count changed, update and event
|
||||
if (newcount != oldcount) {
|
||||
x = userid.split('/');
|
||||
obj.parent.DispatchEvent(['*'], obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
|
||||
var u = users[userid];
|
||||
if (u) {
|
||||
var targets = ['*', 'server-users'];
|
||||
if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } }
|
||||
obj.parent.DispatchEvent(targets, obj, { action: 'wssessioncount', username: x[2], count: newcount, domain: x[1], nolog: 1, nopeers: 1 });
|
||||
obj.sessionsCount[userid] = newcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Clone a safe version of a user object, remove everything that is secret.
|
||||
|
|
Loading…
Reference in New Issue