Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Disconnected
Files -
Disconnected
✓
✗
Intel® AMT -
Events -
Show
General -
General -
Events -
Show
My Server Stats
Log-X
✖
File Selection
Upload File
Agent Remote Desktop
Quality
Scaling
Frame rate
Intel® AMT Hardware KVM
Image Encoding
Other Settings
\ No newline at end of file
diff --git a/views/default.handlebars b/views/default.handlebars
index b7ce816b..2c33a05c 100644
--- a/views/default.handlebars
+++ b/views/default.handlebars
@@ -300,6 +300,7 @@
+
@@ -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.
';
+ x += addHtmlValue('CSV Format', 'userlist.csv');
+ x += addHtmlValue('JSON Format', 'userlist.json');
+ 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.';
@@ -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):'Not set', everify = '';
if (serverinfo.emailcheck) { everify = ((user.emailVerified == true)?'🗸 ':'🗴 '); }
if (user.name.toLowerCase() != user._id.split('/')[2]) { x += addDeviceAttribute('User Identifier', user._id.split('/')[2]); }
- x += addDeviceAttribute('Email', everify + "" + email + '');
+ if ((user.siteadmin != 0xFFFFFFFF) || (userinfo.siteadmin == 0xFFFFFFFF)) { // If we are not site admin, we can't change a admin email.
+ x += addDeviceAttribute('Email', everify + "" + email + '');
+ } else {
+ x += addDeviceAttribute('Email', everify + email + ' ');
+ }
x += addDeviceAttribute('Server Rights', premsg + "" + msg.join(', ') + "");
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 = 'None';
if (user.groups) { userGroups = ''; for (var i in user.groups) { userGroups += '' + user.groups[i] + ''; } }
- 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', ''); }
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();
}
diff --git a/webserver.js b/webserver.js
index 2c4e2c66..c4af5581 100644
--- a/webserver.js
+++ b/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,8 +3070,13 @@ 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 });
- obj.sessionsCount[userid] = newcount;
+ 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;
+ }
}
}
};