mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-27 07:53:23 +03:00
Added session sharing guest names to event log.
This commit is contained in:
parent
19da3051f6
commit
89071f2454
@ -482,6 +482,7 @@ function MeshServerLog(msg, state) {
|
|||||||
if (state.username) { msg.username = state.username; }
|
if (state.username) { msg.username = state.username; }
|
||||||
if (state.sessionid) { msg.sessionid = state.sessionid; }
|
if (state.sessionid) { msg.sessionid = state.sessionid; }
|
||||||
if (state.remoteaddr) { msg.remoteaddr = state.remoteaddr; }
|
if (state.remoteaddr) { msg.remoteaddr = state.remoteaddr; }
|
||||||
|
if (state.guestname) { msg.guestname = state.guestname; }
|
||||||
}
|
}
|
||||||
mesh.SendCommand(msg);
|
mesh.SendCommand(msg);
|
||||||
}
|
}
|
||||||
@ -494,6 +495,7 @@ function MeshServerLogEx(id, args, msg, state) {
|
|||||||
if (state.username) { msg.username = state.username; }
|
if (state.username) { msg.username = state.username; }
|
||||||
if (state.sessionid) { msg.sessionid = state.sessionid; }
|
if (state.sessionid) { msg.sessionid = state.sessionid; }
|
||||||
if (state.remoteaddr) { msg.remoteaddr = state.remoteaddr; }
|
if (state.remoteaddr) { msg.remoteaddr = state.remoteaddr; }
|
||||||
|
if (state.guestname) { msg.guestname = state.guestname; }
|
||||||
}
|
}
|
||||||
mesh.SendCommand(msg);
|
mesh.SendCommand(msg);
|
||||||
}
|
}
|
||||||
@ -2210,7 +2212,7 @@ function onTunnelData(data) {
|
|||||||
if (this.ws.httprequest.desktop.kvm.connectionBar) {
|
if (this.ws.httprequest.desktop.kvm.connectionBar) {
|
||||||
this.ws.httprequest.desktop.kvm.connectionBar.httprequest = this.ws.httprequest;
|
this.ws.httprequest.desktop.kvm.connectionBar.httprequest = this.ws.httprequest;
|
||||||
this.ws.httprequest.desktop.kvm.connectionBar.on('close', function () {
|
this.ws.httprequest.desktop.kvm.connectionBar.on('close', function () {
|
||||||
MeshServerLogEx(33, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
MeshServerLogEx(29, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
||||||
for (var i in this.httprequest.desktop.kvm._pipedStreams) {
|
for (var i in this.httprequest.desktop.kvm._pipedStreams) {
|
||||||
this.httprequest.desktop.kvm._pipedStreams[i].end();
|
this.httprequest.desktop.kvm._pipedStreams[i].end();
|
||||||
}
|
}
|
||||||
@ -2249,15 +2251,15 @@ function onTunnelData(data) {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace('{0}', this.httprequest.desktop.kvm.rusers.join(', ')).replace('{1}', this.httprequest.desktop.kvm.users.join(', ')), require('MeshAgent')._tsid);
|
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace('{0}', this.httprequest.desktop.kvm.rusers.join(', ')).replace('{1}', this.httprequest.desktop.kvm.users.join(', ')), require('MeshAgent')._tsid);
|
||||||
MeshServerLogEx(37, null, "Remote Desktop Connection Bar Activated/Updated (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
MeshServerLogEx(38, null, "Remote Desktop Connection Bar Failed or not Supported (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
MeshServerLogEx(32, null, "Remote Desktop Connection Bar Failed or not Supported (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
||||||
}
|
}
|
||||||
if (this.httprequest.desktop.kvm.connectionBar) {
|
if (this.httprequest.desktop.kvm.connectionBar) {
|
||||||
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
|
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
|
||||||
this.httprequest.desktop.kvm.connectionBar.on('close', function () {
|
this.httprequest.desktop.kvm.connectionBar.on('close', function () {
|
||||||
MeshServerLogEx(39, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
MeshServerLogEx(29, null, "Remote Desktop Connection forcefully closed by local user (" + this.httprequest.remoteaddr + ")", this.httprequest);
|
||||||
for (var i in this.httprequest.desktop.kvm._pipedStreams) {
|
for (var i in this.httprequest.desktop.kvm._pipedStreams) {
|
||||||
this.httprequest.desktop.kvm._pipedStreams[i].end();
|
this.httprequest.desktop.kvm._pipedStreams[i].end();
|
||||||
}
|
}
|
||||||
|
@ -1310,6 +1310,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
|||||||
if ((typeof command.msg == 'string') && (command.msg.length < 4096)) {
|
if ((typeof command.msg == 'string') && (command.msg.length < 4096)) {
|
||||||
var event = { etype: 'node', action: 'agentlog', nodeid: obj.dbNodeKey, domain: domain.id, msg: command.msg };
|
var event = { etype: 'node', action: 'agentlog', nodeid: obj.dbNodeKey, domain: domain.id, msg: command.msg };
|
||||||
if (typeof command.msgid == 'number') { event.msgid = command.msgid; }
|
if (typeof command.msgid == 'number') { event.msgid = command.msgid; }
|
||||||
|
if (typeof command.guestname == 'string') { event.guestname = command.guestname; }
|
||||||
if (Array.isArray(command.msgArgs)) { event.msgArgs = command.msgArgs; }
|
if (Array.isArray(command.msgArgs)) { event.msgArgs = command.msgArgs; }
|
||||||
if (typeof command.remoteaddr == 'string') { event.remoteaddr = command.remoteaddr; }
|
if (typeof command.remoteaddr == 'string') { event.remoteaddr = command.remoteaddr; }
|
||||||
var targets = parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]);
|
var targets = parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]);
|
||||||
|
@ -475,6 +475,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
|
|||||||
else if (obj.req.query.p == 2) { msg = 'Started desktop session'; msgid = 15; }
|
else if (obj.req.query.p == 2) { msg = 'Started desktop session'; msgid = 15; }
|
||||||
else if (obj.req.query.p == 5) { msg = 'Started file management session'; msgid = 16; }
|
else if (obj.req.query.p == 5) { msg = 'Started file management session'; msgid = 16; }
|
||||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: sessionUser._id, username: sessionUser.name, msgid: msgid, msgArgs: [obj.id, obj.peer.req.clientIp, req.clientIp], msg: msg + ' \"' + obj.id + '\" from ' + obj.peer.req.clientIp + ' to ' + req.clientIp, protocol: req.query.p, nodeid: req.query.nodeid };
|
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: sessionUser._id, username: sessionUser.name, msgid: msgid, msgArgs: [obj.id, obj.peer.req.clientIp, req.clientIp], msg: msg + ' \"' + obj.id + '\" from ' + obj.peer.req.clientIp + ' to ' + req.clientIp, protocol: req.query.p, nodeid: req.query.nodeid };
|
||||||
|
if (obj.guestname) { event.guestname = obj.guestname; } else if (relayinfo.peer1.guestname) { event.guestname = relayinfo.peer1.guestname; } // If this is a sharing session, set the guest name here.
|
||||||
parent.parent.DispatchEvent(['*', sessionUser._id], obj, event);
|
parent.parent.DispatchEvent(['*', sessionUser._id], obj, event);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -653,9 +654,11 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
|
|||||||
else if (obj.req.query.p == 200) { msg = 'Ended messenger session', msgid = 112; }
|
else if (obj.req.query.p == 200) { msg = 'Ended messenger session', msgid = 112; }
|
||||||
if (user) {
|
if (user) {
|
||||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: user._id, username: user.name, msgid: msgid, msgArgs: [obj.id, obj.req.clientIp, obj.peer.req.clientIp, Math.floor((Date.now() - ws.time) / 1000)], msg: msg + ' \"' + obj.id + '\" from ' + obj.req.clientIp + ' to ' + obj.peer.req.clientIp + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: obj.req.query.p, nodeid: obj.req.query.nodeid };
|
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: user._id, username: user.name, msgid: msgid, msgArgs: [obj.id, obj.req.clientIp, obj.peer.req.clientIp, Math.floor((Date.now() - ws.time) / 1000)], msg: msg + ' \"' + obj.id + '\" from ' + obj.req.clientIp + ' to ' + obj.peer.req.clientIp + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: obj.req.query.p, nodeid: obj.req.query.nodeid };
|
||||||
|
if (obj.guestname) { event.guestname = obj.guestname; } else if (peer.guestname) { event.guestname = peer.guestname; } // If this is a sharing session, set the guest name here.
|
||||||
parent.parent.DispatchEvent(['*', user._id], obj, event);
|
parent.parent.DispatchEvent(['*', user._id], obj, event);
|
||||||
} else if (peer.user) {
|
} else if (peer.user) {
|
||||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: peer.user._id, username: peer.user.name, msgid: msgid, msgArgs: [obj.id, obj.req.clientIp, obj.peer.req.clientIp, Math.floor((Date.now() - ws.time) / 1000)], msg: msg + ' \"' + obj.id + '\" from ' + obj.req.clientIp + ' to ' + obj.peer.req.clientIp + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: obj.req.query.p, nodeid: obj.req.query.nodeid };
|
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: peer.user._id, username: peer.user.name, msgid: msgid, msgArgs: [obj.id, obj.req.clientIp, obj.peer.req.clientIp, Math.floor((Date.now() - ws.time) / 1000)], msg: msg + ' \"' + obj.id + '\" from ' + obj.req.clientIp + ' to ' + obj.peer.req.clientIp + ', ' + Math.floor((Date.now() - ws.time) / 1000) + ' second(s)', protocol: obj.req.query.p, nodeid: obj.req.query.nodeid };
|
||||||
|
if (obj.guestname) { event.guestname = obj.guestname; } else if (peer.guestname) { event.guestname = peer.guestname; } // If this is a sharing session, set the guest name here.
|
||||||
parent.parent.DispatchEvent(['*', peer.user._id], obj, event);
|
parent.parent.DispatchEvent(['*', peer.user._id], obj, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -888,6 +891,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
|
|||||||
if (obj.id == null) { obj.id = ('' + Math.random()).substring(2); }
|
if (obj.id == null) { obj.id = ('' + Math.random()).substring(2); }
|
||||||
const rcookie = parent.parent.encodeCookie({ ruserid: user._id, nodeid: node._id }, parent.parent.loginCookieEncryptionKey);
|
const rcookie = parent.parent.encodeCookie({ ruserid: user._id, nodeid: node._id }, parent.parent.loginCookieEncryptionKey);
|
||||||
const command = { nodeid: node._id, action: 'msg', type: 'tunnel', userid: user._id, value: '*/' + xdomain + 'meshrelay.ashx?p=' + cookie.p + '&id=' + obj.id + '&rauth=' + rcookie + '&nodeid=' + node._id, soptions: {}, rights: cookie.r, guestname: cookie.gn, consent: cookie.cf, remoteaddr: cleanRemoteAddr(obj.req.clientIp) };
|
const command = { nodeid: node._id, action: 'msg', type: 'tunnel', userid: user._id, value: '*/' + xdomain + 'meshrelay.ashx?p=' + cookie.p + '&id=' + obj.id + '&rauth=' + rcookie + '&nodeid=' + node._id, soptions: {}, rights: cookie.r, guestname: cookie.gn, consent: cookie.cf, remoteaddr: cleanRemoteAddr(obj.req.clientIp) };
|
||||||
|
obj.guestname = cookie.gn;
|
||||||
|
|
||||||
// Limit what this relay connection can do
|
// Limit what this relay connection can do
|
||||||
if (typeof cookie.p == 'number') {
|
if (typeof cookie.p == 'number') {
|
||||||
@ -1114,6 +1118,7 @@ function CreateLocalRelayEx(parent, ws, req, domain, user, cookie) {
|
|||||||
else if (req.query.p == 12) { protocolStr = 'VNC'; }
|
else if (req.query.p == 12) { protocolStr = 'VNC'; }
|
||||||
else if (req.query.p == 13) { protocolStr = 'SSH-FILES'; }
|
else if (req.query.p == 13) { protocolStr = 'SSH-FILES'; }
|
||||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: obj.user._id, username: obj.user.name, msgid: 121, msgArgs: [obj.id, protocolStr, obj.host, Math.floor((Date.now() - obj.time) / 1000)], msg: 'Ended local relay session \"' + obj.id + '\", protocol ' + protocolStr + ' to ' + obj.host + ', ' + Math.floor((Date.now() - obj.time) / 1000) + ' second(s)', nodeid: obj.req.query.nodeid, protocol: req.query.p, in: inTraffc, out: outTraffc };
|
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: obj.user._id, username: obj.user.name, msgid: 121, msgArgs: [obj.id, protocolStr, obj.host, Math.floor((Date.now() - obj.time) / 1000)], msg: 'Ended local relay session \"' + obj.id + '\", protocol ' + protocolStr + ' to ' + obj.host + ', ' + Math.floor((Date.now() - obj.time) / 1000) + ' second(s)', nodeid: obj.req.query.nodeid, protocol: req.query.p, in: inTraffc, out: outTraffc };
|
||||||
|
if (obj.guestname) { event.guestname = obj.guestname; } // If this is a sharing session, set the guest name here.
|
||||||
parent.parent.DispatchEvent(['*', user._id], obj, event);
|
parent.parent.DispatchEvent(['*', user._id], obj, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,6 +1173,7 @@ function CreateLocalRelayEx(parent, ws, req, domain, user, cookie) {
|
|||||||
else if (req.query.p == 13) { protocolStr = 'SSH-FILES'; }
|
else if (req.query.p == 13) { protocolStr = 'SSH-FILES'; }
|
||||||
obj.time = Date.now();
|
obj.time = Date.now();
|
||||||
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: obj.user._id, username: obj.user.name, msgid: 120, msgArgs: [obj.id, protocolStr, obj.host], msg: 'Started local relay session \"' + obj.id + '\", protocol ' + protocolStr + ' to ' + obj.host, nodeid: req.query.nodeid, protocol: req.query.p };
|
var event = { etype: 'relay', action: 'relaylog', domain: domain.id, userid: obj.user._id, username: obj.user.name, msgid: 120, msgArgs: [obj.id, protocolStr, obj.host], msg: 'Started local relay session \"' + obj.id + '\", protocol ' + protocolStr + ' to ' + obj.host, nodeid: req.query.nodeid, protocol: req.query.p };
|
||||||
|
if (obj.guestname) { event.guestname = obj.guestname; } // If this is a sharing session, set the guest name here.
|
||||||
parent.parent.DispatchEvent(['*', obj.user._id, obj.meshid, obj.nodeid], obj, event);
|
parent.parent.DispatchEvent(['*', obj.user._id, obj.meshid, obj.nodeid], obj, event);
|
||||||
|
|
||||||
// Count the session
|
// Count the session
|
||||||
|
@ -9782,10 +9782,12 @@
|
|||||||
msg = EscapeHtml(msg).split('(R)').join('®');
|
msg = EscapeHtml(msg).split('(R)').join('®');
|
||||||
}
|
}
|
||||||
if (event.username) {
|
if (event.username) {
|
||||||
|
var guestname = '';
|
||||||
|
if (event.guestname) { guestname = ' / <span title="' + "This is a guest sharing session" + '">' + EscapeHtml(event.guestname) + '</span>'; }
|
||||||
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
||||||
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponentEx(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a> → ' + msg;
|
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponentEx(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a>' + guestname + ' → ' + msg;
|
||||||
} else {
|
} else {
|
||||||
msg = EscapeHtml(event.username) + ' → ' + msg;
|
msg = EscapeHtml(event.username) + guestname + ' → ' + msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
|
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
|
||||||
@ -12514,13 +12516,13 @@
|
|||||||
30: "Starting remote desktop after local user accepted",
|
30: "Starting remote desktop after local user accepted",
|
||||||
31: "Remote Desktop Connection Bar Activated/Updated",
|
31: "Remote Desktop Connection Bar Activated/Updated",
|
||||||
32: "Remote Desktop Connection Bar Failed or Not Supported",
|
32: "Remote Desktop Connection Bar Failed or Not Supported",
|
||||||
33: "Remote Desktop Connection forcefully closed by local user",
|
33: "Remote Desktop Connection forcefully closed by local user", // No longer used, 29 must be used instead.
|
||||||
34: "Failed to start remote desktop after local user rejected",
|
34: "Failed to start remote desktop after local user rejected",
|
||||||
35: "Started remote desktop with toast notification",
|
35: "Started remote desktop with toast notification",
|
||||||
36: "Started remote desktop without notification",
|
36: "Started remote desktop without notification",
|
||||||
37: "Remote Desktop Connection Bar Activated/Updated",
|
37: "Remote Desktop Connection Bar Activated/Updated", // No longer used, 31 must be used instead.
|
||||||
38: "Remote Desktop Connection Bar Failed or not Supported",
|
38: "Remote Desktop Connection Bar Failed or not Supported", // No longer used, 33 must be used instead.
|
||||||
39: "Remote Desktop Connection forcefully closed by local user",
|
39: "Remote Desktop Connection forcefully closed by local user", // No longer used, 29 must be used instead.
|
||||||
40: "Starting remote files after local user accepted",
|
40: "Starting remote files after local user accepted",
|
||||||
41: "Failed to start remote files after local user rejected",
|
41: "Failed to start remote files after local user rejected",
|
||||||
42: "Started remote files with toast notification",
|
42: "Started remote files with toast notification",
|
||||||
@ -12652,10 +12654,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.username) {
|
if (event.username) {
|
||||||
|
var guestname = '';
|
||||||
|
if (event.guestname) { guestname = ' / <span title="' + "This is a guest sharing session" + '">' + EscapeHtml(event.guestname) + '</span>'; }
|
||||||
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
||||||
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponentEx(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a> → ' + msg;
|
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponentEx(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a>' + guestname + ' → ' + msg;
|
||||||
} else {
|
} else {
|
||||||
msg = EscapeHtml(event.username) + ' → ' + msg;
|
msg = EscapeHtml(event.username) + guestname + ' → ' + msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.remoteaddr) { msg += ' (' + event.remoteaddr + ')'; }
|
if (event.remoteaddr) { msg += ' (' + event.remoteaddr + ')'; }
|
||||||
@ -14276,11 +14280,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.username && (event.username != currentUser.name)) {
|
if (event.username && (event.username != currentUser.name)) {
|
||||||
|
var guestname = '';
|
||||||
|
if (event.guestname) { guestname = ' / <span title="' + "This is a guest sharing session" + '">' + EscapeHtml(event.guestname) + '</span>'; }
|
||||||
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
if ((userinfo.siteadmin & 2) && (event.userid)) {
|
||||||
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponentEx(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a> → ' + msg;
|
msg = '<a href=# onclick=\'gotoUser("' + encodeURIComponentEx(event.userid) + '");haltEvent(event);\'>' + EscapeHtml(event.username) + '</a>' + guestname + ' → ' + msg;
|
||||||
} else {
|
} else {
|
||||||
msg = EscapeHtml(event.username) + ' → ' + msg;
|
msg = EscapeHtml(event.guestname) + ' → ' + msg;
|
||||||
}
|
}
|
||||||
|
} else if (event.guestname) {
|
||||||
|
msg = '<span title="' + "This is a guest sharing session" + '">' + EscapeHtml(event.guestname) + '</span> → ' + msg;
|
||||||
}
|
}
|
||||||
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
|
if (event.etype == 'relay' || event.action == 'relaylog') icon = 'relayIcon16';
|
||||||
x += '<tr onclick=showEventDetails(' + event.h + ',3) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1> </td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2> </td></tr><tr style=height:2px></tr>';
|
x += '<tr onclick=showEventDetails(' + event.h + ',3) onmouseover=eventMouseHover(this,1) onmouseout=eventMouseHover(this,0) style=cursor:pointer><td style=width:18px><div class=' + icon + '></div></td><td class=g1> </td><td class=style10>' + printTime(time) + ' - ' + msg + '</td><td class=g2> </td></tr><tr style=height:2px></tr>';
|
||||||
|
Loading…
Reference in New Issue
Block a user