mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
Integrated MeshMessenger for user-to-user.
This commit is contained in:
parent
b1a5d95413
commit
fb48cb3945
@ -183,7 +183,8 @@ function CreateMeshCentralServer(config, args) {
|
||||
xprocess.stdout.on('data', function (data) { if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } if (data.indexOf('Updating settings folder...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Updating server certificates...') >= 0) { xprocess.xrestart = 1; } else if (data.indexOf('Server Ctrl-C exit...') >= 0) { xprocess.xrestart = 2; } else if (data.indexOf('Starting self upgrade...') >= 0) { xprocess.xrestart = 3; } console.log(data); });
|
||||
xprocess.stderr.on('data', function (data) {
|
||||
if (data.startsWith('le.challenges[tls-sni-01].loopback')) { return; } // Ignore this error output from GreenLock
|
||||
if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); } obj.fs.appendFileSync(obj.getConfigFilePath('mesherrors.txt'), '-------- ' + new Date().toLocaleString() + ' ---- ' + obj.currentVer + ' --------\r\n\r\n' + data + '\r\n\r\n\r\n');
|
||||
if (data[data.length - 1] == '\n') { data = data.substring(0, data.length - 1); }
|
||||
try { obj.fs.appendFileSync(obj.getConfigFilePath('mesherrors.txt'), '-------- ' + new Date().toLocaleString() + ' ---- ' + obj.currentVer + ' --------\r\n\r\n' + data + '\r\n\r\n\r\n'); } catch (ex) { console.log('ERROR: Unable to write to mesherrors.txt.'); }
|
||||
});
|
||||
xprocess.on('close', function (code) { if ((code != 0) && (code != 123)) { /* console.log("Exited with code " + code); */ } });
|
||||
};
|
||||
|
@ -94,6 +94,13 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
||||
if (obj.id == null) { try { obj.close(); } catch (e) { } return null; } // Attempt to connect without id, drop this.
|
||||
ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive
|
||||
|
||||
// If this is a MeshMessenger session, the ID is the two userid's and authentication must match one of them.
|
||||
if (obj.id.startsWith('meshmessenger/')) {
|
||||
if (obj.user == null) { try { obj.close(); } catch (e) { } return null; }
|
||||
var x = obj.id.split('/'), user1 = x[1] + '/' + x[2] + '/' + x[3], user2 = x[4] + '/' + x[5] + '/' + x[6];
|
||||
if ((obj.user._id != user1) && (obj.user._id != user2)) { try { obj.close(); } catch (e) { } return null; }
|
||||
}
|
||||
|
||||
// Validate that the id is valid, we only need to do this on non-authenticated sessions.
|
||||
// TODO: Figure out when this needs to be done.
|
||||
/*
|
||||
|
19
meshuser.js
19
meshuser.js
@ -592,6 +592,25 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
var sessions = obj.parent.wssessions[command.userid];
|
||||
if (sessions != null) { for (i in sessions) { try { sessions[i].send(JSON.stringify(notification)); } catch (ex) { } } }
|
||||
|
||||
if (obj.parent.parent.multiServer != null) {
|
||||
// TODO: Add multi-server support
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'meshmessenger':
|
||||
{
|
||||
// Send a notification message to a user
|
||||
if ((user.siteadmin & 2) == 0) break;
|
||||
if (obj.common.validateString(command.userid, 1, 2048) == false) break;
|
||||
|
||||
// Create the notification message
|
||||
var notification = {
|
||||
"action": "msg", "type": "notify", "value": "<b>" + user.name + "</b>: Chat Request, Click here to accept.", "userid": user._id, "username": user.name, "tag": 'meshmessenger/' + encodeURIComponent(command.userid) + '/' + encodeURIComponent(user._id) };
|
||||
|
||||
// Get the list of sessions for this user
|
||||
var sessions = obj.parent.wssessions[command.userid];
|
||||
if (sessions != null) { for (i in sessions) { try { sessions[i].send(JSON.stringify(notification)); } catch (ex) { } } }
|
||||
|
||||
if (obj.parent.parent.multiServer != null) {
|
||||
// TODO: Add multi-server support
|
||||
}
|
||||
|
BIN
public/images/icon-chat.png
Normal file
BIN
public/images/icon-chat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 578 B |
@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html style=height:100%>
|
||||
<head>
|
||||
<title>MeshMessenger</title>
|
||||
<meta http-equiv=X-UA-Compatible content="IE=edge">
|
||||
<meta content="text/html;charset=utf-8" http-equiv=Content-Type>
|
||||
<meta name=format-detection content="telephone=no">
|
||||
@ -8,7 +9,7 @@
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
</head>
|
||||
<body style="font-family:Arial,Helvetica,sans-serif">
|
||||
<div id="xtop" style="position:absolute;left:0;right:0;top:0;height:30px;background-color:#036;color:#c8c8c8"><div style="padding-top:6px;padding-left:6px;font-size:medium"><b>Messenger<span id="xtitle"></span></b></div></div>
|
||||
<div id="xtop" style="position:absolute;left:0;right:0;top:0;height:30px;background-color:#036;color:#c8c8c8"><div style="padding-top:6px;padding-left:6px;font-size:medium"><b>MeshMessenger<span id="xtitle"></span></b></div></div>
|
||||
<div id="xmiddle" style="position:absolute;left:0;right:0;top:30px;bottom:30px">
|
||||
<div id="xmsg" style="position:absolute;left:0;right:0;top:0px;bottom:0px;padding:5px;overflow-y:scroll"></div>
|
||||
</div>
|
||||
@ -25,7 +26,7 @@
|
||||
var state = 0;
|
||||
|
||||
// Set the title
|
||||
if (args.title) { QH('xtitle', ' - ' + args.title); }
|
||||
if (args.title) { QH('xtitle', ' - ' + args.title); document.title = document.title + ' - ' + args.title; }
|
||||
|
||||
// Trap document key presses
|
||||
document.onkeypress = function ondockeypress(e) {
|
||||
@ -76,31 +77,34 @@
|
||||
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
||||
function parseUriArgs() { var name, r = {}, parsedUri = window.document.location.href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = parsedUri[x]; break; } case 1: { r[name] = parsedUri[x]; var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } } } return r; }
|
||||
|
||||
// Get started
|
||||
enableControls(false);
|
||||
if ((typeof args.id == 'string') && (args.id.length > 0)) {
|
||||
xcontrol('Connecting...');
|
||||
socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + '/meshrelay.ashx?id=' + args.id);
|
||||
socket.onopen = function () { xcontrol('Waiting for other user...'); }
|
||||
socket.onerror = function (e) { console.error(e); }
|
||||
socket.onclose = function () { enableControls(false); xcontrol('Connection closed.'); socket = null; }
|
||||
socket.onmessage = function (msg) {
|
||||
if ((state == 0) && (typeof msg.data == 'string')) { enableControls(true); xcontrol('Connected.'); state = 1; return; }
|
||||
if (state == 1) {
|
||||
if (typeof msg.data == 'string') {
|
||||
var obj = JSON.parse(msg.data);
|
||||
switch (obj.action) {
|
||||
case 'chat': { xrecv(obj.msg); break; }
|
||||
function start() {
|
||||
// Get started
|
||||
enableControls(false);
|
||||
if ((typeof args.id == 'string') && (args.id.length > 0)) {
|
||||
//xcontrol('Connecting...');
|
||||
socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + '/meshrelay.ashx?id=' + args.id);
|
||||
socket.onopen = function () { state = 1; xcontrol('Waiting for other user...'); }
|
||||
socket.onerror = function (e) { console.error(e); }
|
||||
socket.onclose = function () { enableControls(false); if (state > 0) { xcontrol('Connection closed.'); } socket = null; if (state > 1) { setTimeout(start, 500); } state = 0; }
|
||||
socket.onmessage = function (msg) {
|
||||
if ((state < 2) && (typeof msg.data == 'string')) { enableControls(true); xcontrol('Connected.'); state = 2; return; }
|
||||
if (state == 2) {
|
||||
if (typeof msg.data == 'string') {
|
||||
var obj = JSON.parse(msg.data);
|
||||
switch (obj.action) {
|
||||
case 'chat': { xrecv(obj.msg); break; }
|
||||
}
|
||||
} else {
|
||||
//xrecv(JSON.stringify(msg));
|
||||
}
|
||||
} else {
|
||||
//xrecv(JSON.stringify(msg));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
xcontrol('Error: No connection key specified.');
|
||||
}
|
||||
} else {
|
||||
xcontrol('Error: No connection key specified.');
|
||||
}
|
||||
|
||||
start();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1195,6 +1195,7 @@
|
||||
var n = { text:message.value };
|
||||
if (message.nodeid != null) { n.nodeid = message.nodeid; }
|
||||
if (message.tag != null) { n.tag = message.tag; }
|
||||
if (message.username != null) { n.username = message.username; }
|
||||
addNotification(n);
|
||||
} else if (message.type == 'ps') {
|
||||
showDeskToolsProcesses(message);
|
||||
@ -1204,6 +1205,7 @@
|
||||
if (message.type == 'notify') { // This is a notification message.
|
||||
var n = { text:message.value };
|
||||
if (message.tag != null) { n.tag = message.tag; }
|
||||
if (message.username != null) { n.username = message.username; }
|
||||
addNotification(n);
|
||||
}
|
||||
}
|
||||
@ -5720,10 +5722,13 @@
|
||||
}
|
||||
|
||||
function addUserHtml(user, sessions) {
|
||||
var x = '', gray = ' gray', icon = 'm2', msg = '', self = (user.name != userinfo.name);
|
||||
var x = '', gray = ' gray', icon = 'm2', msg = '', msg2 = '', self = (user.name != userinfo.name);
|
||||
if (sessions != null) {
|
||||
gray = '';
|
||||
if (self) { msg += "<a onclick=showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")>"; }
|
||||
if (self) {
|
||||
msg2 = "<span style=float:right;margin-top:1px;margin-left:4px;margin-right:4px title=Chat><a onclick=userChat(event,\"" + encodeURIComponent(user._id) + "\",\"" + encodeURIComponent(user.name) + "\")><img src='images/icon-chat.png' height=16 width=16 style=padding-top:2px /></a></span>";
|
||||
msg += "<a onclick=showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")>";
|
||||
}
|
||||
if (sessions == 1) { msg += '1 active session'; } else { msg += sessions + ' active sessions'; }
|
||||
if (self) { msg += "</a>"; }
|
||||
} else {
|
||||
@ -5752,7 +5757,7 @@
|
||||
x += '<div class=bar style=height:24px;width:100%;font-size:medium>';
|
||||
x += '<div style=float:left;height:24px;width:24px;background-color:white><div class="' + icon + gray + '" style=width:16px;margin-top:4px;margin-left:2px;height:16px></div></div>';
|
||||
x += '<div class=g1 style=height:24px;float:left></div><div class=g2 style=height:24px;float:right></div>';
|
||||
x += '<div><span>' + username + '</span><span style=float:right>' + msg + '</span></div></div>'; // </td></tr>
|
||||
x += '<div><span>' + username + '</span>' + msg2 + '<span style=float:right>' + msg + '</span></div></div>'; // </td></tr>
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -5765,6 +5770,13 @@
|
||||
element.children[0].children[0].style['background-color'] = ((over == 0) ? '#c9c9c9' : '#b9b9b9');
|
||||
}
|
||||
|
||||
function userChat(e, userid, name) {
|
||||
haltEvent(e);
|
||||
window.open('/messenger.htm?id=meshmessenger/' + userid + '/' + encodeURIComponent(userinfo._id) + '&title=' + name, 'meshmessenger:' + userid);
|
||||
meshserver.send({ action: 'meshmessenger', userid: decodeURIComponent(userid) });
|
||||
return false;
|
||||
}
|
||||
|
||||
function showUserAlertDialog(e, userid) {
|
||||
if (xxdialogMode) return;
|
||||
haltEvent(e);
|
||||
@ -6223,6 +6235,11 @@
|
||||
else if (n.tag == 'intelamt') gotoDevice(n.nodeid, 14); // Intel AMT
|
||||
else if (n.tag == 'console') gotoDevice(n.nodeid, 15); // Files
|
||||
else gotoDevice(n.nodeid, 10); // General
|
||||
} else {
|
||||
if (n.tag.startsWith('meshmessenger/')) {
|
||||
window.open('/messenger.htm?id=' + n.tag + '&title=' + encodeURIComponent(n.username), n.tag.split('/')[2]);
|
||||
notificationDelete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
|
||||
QV('newAccountDiv', '{{{newAccount}}}' != '0' );
|
||||
QV('newAccountDiv', ('{{{newAccount}}}' != '0') && ('{{{newAccount}}}' != 'false')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passhint != null) && (passhint.length > 0)) { QV("showPassHintLink", true); }
|
||||
QV("newAccountPass", (newAccountPass == 1));
|
||||
QV("resetAccountDiv", (emailCheck == true));
|
||||
|
@ -276,7 +276,7 @@
|
||||
validateLogin();
|
||||
validateCreate();
|
||||
if ('{{loginmode}}' != '') { go(parseInt('{{loginmode}}')); } else { go(1); }
|
||||
QV('newAccountDiv', '{{{newAccount}}}' != '0' );
|
||||
QV('newAccountDiv', ('{{{newAccount}}}' != '0') && ('{{{newAccount}}}' != 'false')); // If new accounts are not allowed, don't display the new account link.
|
||||
if ((passhint != null) && (passhint.length > 0)) { QV("showPassHintLink", true); }
|
||||
QV("newAccountPass", (newAccountPass == 1));
|
||||
QV("resetAccountDiv", (emailCheck == true));
|
||||
|
@ -220,7 +220,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
for (i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; }
|
||||
for (i in parent.config.domains) {
|
||||
if (domainUserCount[i] == 0) {
|
||||
if (parent.config.domains[i].newaccounts == 0) { parent.config.domains[i].newaccounts = 2; }
|
||||
// If newaccounts is set to no new accounts, but no accounts exists, temporarly allow account creation.
|
||||
if ((parent.config.domains[i].newaccounts === 0) || (parent.config.domains[i].newaccounts === false)) { parent.config.domains[i].newaccounts = 2; }
|
||||
console.log('Server ' + ((i == '') ? '' : (i + ' ')) + 'has no users, next new account will be site administrator.');
|
||||
}
|
||||
}
|
||||
@ -390,7 +391,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
function handleCreateAccountRequest(req, res) {
|
||||
var domain = checkUserIpAddress(req, res);
|
||||
if (domain == null) return;
|
||||
if (domain.newaccounts == 0) { res.sendStatus(401); return; }
|
||||
if ((domain.newaccounts === 0) || (domain.newaccounts === false)) { res.sendStatus(401); return; }
|
||||
if (!obj.common.validateUsername(req.body.username, 1, 64) || !obj.common.validateEmail(req.body.email, 1, 256) || !obj.common.validateString(req.body.password1, 1, 256) || !obj.common.validateString(req.body.password2, 1, 256) || (req.body.password1 != req.body.password2) || req.body.username == '~') {
|
||||
req.session.loginmode = 2;
|
||||
req.session.error = '<b style=color:#8C001A>Unable to create account.</b>';
|
||||
@ -420,7 +421,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
var user = { type: 'user', _id: 'user/' + domain.id + '/' + req.body.username.toLowerCase(), name: req.body.username, email: req.body.email, creation: Date.now(), login: Date.now(), domain: domain.id, passhint: hint };
|
||||
var usercount = 0;
|
||||
for (var i in obj.users) { if (obj.users[i].domain == domain.id) { usercount++; } }
|
||||
if (usercount == 0) { user.siteadmin = 0xFFFFFFFF; if (domain.newaccounts == 2) { domain.newaccounts = 0; } } // If this is the first user, give the account site admin.
|
||||
if (usercount == 0) { user.siteadmin = 0xFFFFFFFF; if (domain.newaccounts === 2) { domain.newaccounts = 0; } } // If this is the first user, give the account site admin.
|
||||
obj.users[user._id] = user;
|
||||
req.session.userid = user._id;
|
||||
req.session.domainid = domain.id;
|
||||
@ -444,7 +445,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
function handleResetAccountRequest(req, res) {
|
||||
var domain = checkUserIpAddress(req, res);
|
||||
if (domain == null) return;
|
||||
if (domain.newaccounts == 0) { res.sendStatus(401); return; }
|
||||
if ((domain.newaccounts === 0) || (domain.newaccounts === false)) { res.sendStatus(401); return; }
|
||||
if (!req.body.email || checkEmail(req.body.email) == false) {
|
||||
req.session.loginmode = 3;
|
||||
req.session.error = '<b style=color:#8C001A>Invalid email.</b>';
|
||||
|
Loading…
Reference in New Issue
Block a user