mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-02-12 11:01:52 +00:00
Started work on per-user session recording. #3064
This commit is contained in:
parent
9386ae9a04
commit
e6b6bd061e
7 changed files with 92 additions and 25 deletions
|
@ -675,6 +675,7 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"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." },
|
"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" },
|
"filepath": { "type": "string" },
|
||||||
"index": { "type": "boolean", "default": false },
|
"index": { "type": "boolean", "default": false },
|
||||||
|
|
|
@ -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))))) {
|
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
|
// Check again to make sure we need to start recording
|
||||||
if (domain.sessionrecording.onlyselecteddevicegroups === true) {
|
if ((domain.sessionrecording.onlyselecteddevicegroups === true) || (domain.sessionrecording.onlyselectedusers === true)) {
|
||||||
var mesh = parent.meshes[obj.meshid];
|
var record = false;
|
||||||
if ((mesh.flags == null) || ((mesh.flags & 4) == 0)) { func(false); return; } // Do not record the session
|
|
||||||
|
// 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());
|
var now = new Date(Date.now());
|
||||||
|
|
46
meshrelay.js
46
meshrelay.js
|
@ -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.
|
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 ((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) {
|
if (recordSession) {
|
||||||
// Get the computer name
|
// Get the computer name
|
||||||
parent.db.Get(obj.req.query.nodeid, function (err, nodes) {
|
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); }
|
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
|
// Check again if we need to do messenger recording
|
||||||
if ((node == null) || (domain.sessionrecording.onlyselecteddevicegroups === true)) {
|
if ((domain.sessionrecording.onlyselectedusers === true) || (domain.sessionrecording.onlyselecteddevicegroups === true)) {
|
||||||
var mesh = null;
|
record = false;
|
||||||
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) { }
|
|
||||||
|
|
||||||
// Send any stored push messages
|
// Check if this device group needs to be recorded
|
||||||
obj.pushStoredMessages();
|
if ((node == null) || (domain.sessionrecording.onlyselecteddevicegroups === true)) {
|
||||||
relayinfo.peer1.pushStoredMessages();
|
var mesh = null;
|
||||||
|
if (node != null) { mesh = parent.meshes[node.meshid]; }
|
||||||
// Send other peer's image
|
if ((node != null) && (mesh != null) && (mesh.flags != null) && ((mesh.flags & 4) != 0)) { record = true; }
|
||||||
obj.sendPeerImage();
|
|
||||||
relayinfo.peer1.sendPeerImage();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// Get the username and make it acceptable as a filename
|
||||||
|
|
|
@ -492,7 +492,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||||
serverinfo.languages = parent.renderLanguages;
|
serverinfo.languages = parent.renderLanguages;
|
||||||
serverinfo.tlshash = Buffer.from(parent.webCertificateFullHashs[domain.id], 'binary').toString('hex').toUpperCase(); // SHA384 of server HTTPS certificate
|
serverinfo.tlshash = Buffer.from(parent.webCertificateFullHashs[domain.id], 'binary').toString('hex').toUpperCase(); // SHA384 of server HTTPS certificate
|
||||||
serverinfo.agentCertHash = parent.agentCertificateHashBase64;
|
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)) {
|
if ((parent.parent.config.domains[domain.id].amtacmactivation != null) && (parent.parent.config.domains[domain.id].amtacmactivation.acmmatch != null)) {
|
||||||
var matchingDomains = [];
|
var matchingDomains = [];
|
||||||
for (var i in parent.parent.config.domains[domain.id].amtacmactivation.acmmatch) {
|
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.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.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.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
|
// 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.
|
if (common.validateInt(command.siteadmin) && (chguser._id !== user._id) && (chguser.siteadmin != command.siteadmin)) { // We can't change our own siteadmin permissions.
|
||||||
|
|
|
@ -311,6 +311,7 @@
|
||||||
},
|
},
|
||||||
"_agentConfig": [ "webSocketMaskOverride=1", "coreDumpEnabled=1" ],
|
"_agentConfig": [ "webSocketMaskOverride=1", "coreDumpEnabled=1" ],
|
||||||
"_sessionRecording": {
|
"_sessionRecording": {
|
||||||
|
"_onlySelectedUsers": true,
|
||||||
"_onlySelectedDeviceGroups": true,
|
"_onlySelectedDeviceGroups": true,
|
||||||
"_filepath": "C:\\temp",
|
"_filepath": "C:\\temp",
|
||||||
"_index": true,
|
"_index": true,
|
||||||
|
|
|
@ -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() />');
|
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" />');
|
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');
|
if (user.quota) x += addDeviceAttribute("Server Quota", EscapeHtml(parseInt(user.quota) / 1024) + ' k');
|
||||||
x += addDeviceAttribute("Creation", printDateTime(new Date(user.creation * 1000)));
|
x += addDeviceAttribute("Creation", printDateTime(new Date(user.creation * 1000)));
|
||||||
|
@ -14165,6 +14176,24 @@
|
||||||
p30editPhoneValidate();
|
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) {
|
function p30editPhoneValidate(x) {
|
||||||
var ok = (Q('d2phoneinput').value == '') || (isPhoneNumber(Q('d2phoneinput').value));
|
var ok = (Q('d2phoneinput').value == '') || (isPhoneNumber(Q('d2phoneinput').value));
|
||||||
QE('idx_dlgOkButton', ok);
|
QE('idx_dlgOkButton', ok);
|
||||||
|
|
18
webserver.js
18
webserver.js
|
@ -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
|
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
|
// Check again if we need to do recording
|
||||||
var record = true;
|
var record = true;
|
||||||
if (domain.sessionrecording.onlyselecteddevicegroups === true) {
|
|
||||||
var mesh = obj.meshes[node.meshid];
|
// Check user or device group recording
|
||||||
if ((mesh.flags == null) || ((mesh.flags & 4) == 0)) { record = false; } // Do not record the session
|
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) {
|
if (record == true) {
|
||||||
|
|
Loading…
Reference in a new issue