Started work on per-user session recording. #3064

This commit is contained in:
Ylian Saint-Hilaire 2021-08-26 12:42:09 -07:00
parent 9386ae9a04
commit e6b6bd061e
7 changed files with 92 additions and 25 deletions

View File

@ -675,6 +675,7 @@
"type": "object",
"additionalProperties": false,
"properties": {
"onlySelectedUsers": { "type": "boolean", "default": false, "description": "When enabled, only device users with the session recording feature turned on will be recorded. When false, all users are recorded." },
"onlySelectedDeviceGroups": { "type": "boolean", "default": false, "description": "When enabled, only device groups with the session recording feature turned on will be recorded. When false, all devices are recorded." },
"filepath": { "type": "string" },
"index": { "type": "boolean", "default": false },

View File

@ -731,9 +731,21 @@ function CreateDesktopMultiplexor(parent, domain, nodeid, func) {
if ((domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(2) >= 0))))) {
// Check again to make sure we need to start recording
if (domain.sessionrecording.onlyselecteddevicegroups === true) {
var mesh = parent.meshes[obj.meshid];
if ((mesh.flags == null) || ((mesh.flags & 4) == 0)) { func(false); return; } // Do not record the session
if ((domain.sessionrecording.onlyselecteddevicegroups === true) || (domain.sessionrecording.onlyselectedusers === true)) {
var record = false;
// Check user recording
if (domain.sessionrecording.onlyselectedusers === true) {
// TODO: Check recording ???
}
// Check device group recording
if (domain.sessionrecording.onlyselecteddevicegroups === true) {
var mesh = parent.meshes[obj.meshid];
if ((mesh.flags != null) && ((mesh.flags & 4) != 0)) { record = true; }
}
if (record == false) { func(false); return; } // Do not record the session
}
var now = new Date(Date.now());

View File

@ -349,31 +349,41 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
xtextSession = 2; // 1 = Raw recording of all strings, 2 = Record chat session messages only.
}
if ((obj.req.query.p != null) && (obj.req.query.nodeid != null) && (sessionUser != null) && (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf(parseInt(obj.req.query.p)) >= 0))))) { recordSession = true; }
if (recordSession) {
// Get the computer name
parent.db.Get(obj.req.query.nodeid, function (err, nodes) {
var xusername = '', xdevicename = '', xdevicename2 = null, node = null;
var xusername = '', xdevicename = '', xdevicename2 = null, node = null, record = true;
if ((nodes != null) && (nodes.length == 1)) { node = nodes[0]; xdevicename2 = node.name; xdevicename = '-' + parent.common.makeFilename(node.name); }
// Check again if we need to do recording
if ((node == null) || (domain.sessionrecording.onlyselecteddevicegroups === true)) {
var mesh = null;
if (node != null) { mesh = parent.meshes[node.meshid]; }
if ((node == null) || (mesh == null) || (mesh.flags == null) || ((mesh.flags & 4) == 0)) {
// Do not record the session, just send session start
try { ws.send('c'); } catch (ex) { } // Send connect to both peers
try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
// Check again if we need to do messenger recording
if ((domain.sessionrecording.onlyselectedusers === true) || (domain.sessionrecording.onlyselecteddevicegroups === true)) {
record = false;
// Send any stored push messages
obj.pushStoredMessages();
relayinfo.peer1.pushStoredMessages();
// Send other peer's image
obj.sendPeerImage();
relayinfo.peer1.sendPeerImage();
return;
// Check if this device group needs to be recorded
if ((node == null) || (domain.sessionrecording.onlyselecteddevicegroups === true)) {
var mesh = null;
if (node != null) { mesh = parent.meshes[node.meshid]; }
if ((node != null) && (mesh != null) && (mesh.flags != null) && ((mesh.flags & 4) != 0)) { record = true; }
}
// Check if this user needs to be recorded
if ((sessionUser != null) && (sessionUser.flags != null) && ((sessionUser.flags & 2) != 0)) { record = true; }
}
// Do not record the session, just send session start
if (record == false) {
try { ws.send('c'); } catch (ex) { } // Send connect to both peers
try { relayinfo.peer1.ws.send('c'); } catch (ex) { }
// Send any stored push messages
obj.pushStoredMessages();
relayinfo.peer1.pushStoredMessages();
// Send other peer's image
obj.sendPeerImage();
relayinfo.peer1.sendPeerImage();
return;
}
// Get the username and make it acceptable as a filename

View File

@ -492,7 +492,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
serverinfo.languages = parent.renderLanguages;
serverinfo.tlshash = Buffer.from(parent.webCertificateFullHashs[domain.id], 'binary').toString('hex').toUpperCase(); // SHA384 of server HTTPS certificate
serverinfo.agentCertHash = parent.agentCertificateHashBase64;
if ((domain.sessionrecording) && (domain.sessionrecording.onlyselecteddevicegroups === true)) { serverinfo.devGroupSessionRecording = 1; } // Allow enabling of session recording
if ((domain.sessionrecording) && (domain.sessionrecording.onlyselectedusers === true)) { serverinfo.usersSessionRecording = 1; } // Allow enabling of session recording for user groups
if ((domain.sessionrecording) && (domain.sessionrecording.onlyselecteddevicegroups === true)) { serverinfo.devGroupSessionRecording = 1; } // Allow enabling of session recording for device groups
if ((parent.parent.config.domains[domain.id].amtacmactivation != null) && (parent.parent.config.domains[domain.id].amtacmactivation.acmmatch != null)) {
var matchingDomains = [];
for (var i in parent.parent.config.domains[domain.id].amtacmactivation.acmmatch) {
@ -1581,6 +1582,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if (command.resetNextLogin === true) { chguser.passchange = -1; }
if ((command.consent != null) && (typeof command.consent == 'number')) { if (command.consent == 0) { delete chguser.consent; } else { chguser.consent = command.consent; } change = 1; }
if ((command.phone != null) && (typeof command.phone == 'string') && ((command.phone == '') || isPhoneNumber(command.phone))) { if (command.phone == '') { delete chguser.phone; } else { chguser.phone = command.phone; } change = 1; }
if ((command.flags != null) && (typeof command.flags == 'number')) { if (command.flags == 0) { delete chguser.flags; } else { chguser.flags = command.flags; } change = 1; } // Flags: 1 = Account Image, 2 = Session Recording
// Site admins can change any server rights, user managers can only change AccountLock, NoMeshCmd and NoNewGroups
if (common.validateInt(command.siteadmin) && (chguser._id !== user._id) && (chguser.siteadmin != command.siteadmin)) { // We can't change our own siteadmin permissions.

View File

@ -311,6 +311,7 @@
},
"_agentConfig": [ "webSocketMaskOverride=1", "coreDumpEnabled=1" ],
"_sessionRecording": {
"_onlySelectedUsers": true,
"_onlySelectedDeviceGroups": true,
"_filepath": "C:\\temp",
"_index": true,

View File

@ -14051,6 +14051,17 @@
x += addDeviceAttribute("Phone Number", (user.phone?user.phone:('<i>' + "None" + '</i>')) + ' <img class=hoverButton style=cursor:pointer src="images/link5.png" onclick=p30editPhone() />');
}
// Display features
if (serverinfo.usersSessionRecording == 1) {
var userFeatures = [];
if (user.flags) {
if ((serverinfo.usersSessionRecording == 1) && (user.flags & 2)) { userFeatures.push("Record Sessions"); }
}
userFeatures = userFeatures.join(', ');
if (userFeatures == '') { userFeatures = '<i>' + "None" + '</i>'; }
x += addDeviceAttribute("Features", addLink(userFeatures, 'p20edituserfeatures()'));
}
x += addDeviceAttribute("Server Rights", premsg + msg.join(', ') + ' <img style=cursor:pointer class=hoverButton onclick=\'return showUserAdminDialog(event,"' + encodeURIComponentEx(user._id) + '")\' src="images/link5.png" />');
if (user.quota) x += addDeviceAttribute("Server Quota", EscapeHtml(parseInt(user.quota) / 1024) + ' k');
x += addDeviceAttribute("Creation", printDateTime(new Date(user.creation * 1000)));
@ -14165,6 +14176,24 @@
p30editPhoneValidate();
}
function p20edituserfeatures() {
if (xxdialogMode) return;
var flags = (currentUser.flags)?currentUser.flags:0, x = ''; // Flags: 1 = Account Image, 2 = Session Recording
if (serverinfo.usersSessionRecording == 1) {
x += '<div><label><input type=checkbox id=d20flag2 onchange=p20edituserfeaturesValidate() ' + ((flags & 2) ? 'checked' : '') + '>' + "Record sessions" + '</label><br></div>';
}
setDialogMode(2, "Edit User Features", 3, p20edituserfeaturesEx, x);
}
function p20edituserfeaturesValidate() { }
// Send to the server the new user's real name
function p20edituserfeaturesEx() {
var f = currentUser.flags & 1; // Flags: 1 = Account Image, 2 = Session Recording
if (Q('d20flag2').checked) { f += 2; }
meshserver.send({ action: 'edituser', id: currentUser._id, flags: f });
}
function p30editPhoneValidate(x) {
var ok = (Q('d2phoneinput').value == '') || (isPhoneNumber(Q('d2phoneinput').value));
QE('idx_dlgOkButton', ok);

View File

@ -3943,9 +3943,21 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
if (domain.sessionrecording == true || ((typeof domain.sessionrecording == 'object') && ((domain.sessionrecording.protocols == null) || (domain.sessionrecording.protocols.indexOf((req.query.p == 2) ? 101 : 100) >= 0)))) { // TODO 100
// Check again if we need to do recording
var record = true;
if (domain.sessionrecording.onlyselecteddevicegroups === true) {
var mesh = obj.meshes[node.meshid];
if ((mesh.flags == null) || ((mesh.flags & 4) == 0)) { record = false; } // Do not record the session
// Check user or device group recording
if ((domain.sessionrecording.onlyselectedusers === true) || (domain.sessionrecording.onlyselecteddevicegroups === true)) {
record = false;
// Check device group recording
if (domain.sessionrecording.onlyselecteddevicegroups === true) {
var mesh = obj.meshes[node.meshid];
if ((mesh.flags != null) && ((mesh.flags & 4) != 0)) { record = true; } // Record the session
}
// Check user recording
if (domain.sessionrecording.onlyselectedusers === true) {
if ((user.flags != null) && ((user.flags & 2) != 0)) { record = true; } // Record the session
}
}
if (record == true) {