mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-11-26 07:57:56 +03:00
More work on agent invite by codes.
This commit is contained in:
parent
474d71b820
commit
edb6011efe
@ -282,6 +282,7 @@
|
|||||||
<Content Include="views\download.handlebars" />
|
<Content Include="views\download.handlebars" />
|
||||||
<Content Include="views\error404-mobile.handlebars" />
|
<Content Include="views\error404-mobile.handlebars" />
|
||||||
<Content Include="views\error404.handlebars" />
|
<Content Include="views\error404.handlebars" />
|
||||||
|
<Content Include="views\invite.handlebars" />
|
||||||
<Content Include="views\login-mobile.handlebars" />
|
<Content Include="views\login-mobile.handlebars" />
|
||||||
<Content Include="views\login.handlebars" />
|
<Content Include="views\login.handlebars" />
|
||||||
<Content Include="views\message.handlebars" />
|
<Content Include="views\message.handlebars" />
|
||||||
|
15
meshuser.js
15
meshuser.js
@ -2272,9 +2272,22 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||||||
if ((common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Group "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
|
if ((common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Group "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
|
||||||
if ((common.validateInt(command.flags) == true) && (command.flags != mesh.flags)) { if (change != '') change += ' and flags changed'; else change += 'Group "' + mesh.name + '" flags changed'; mesh.flags = command.flags; }
|
if ((common.validateInt(command.flags) == true) && (command.flags != mesh.flags)) { if (change != '') change += ' and flags changed'; else change += 'Group "' + mesh.name + '" flags changed'; mesh.flags = command.flags; }
|
||||||
if ((common.validateInt(command.consent) == true) && (command.consent != mesh.consent)) { if (change != '') change += ' and consent changed'; else change += 'Group "' + mesh.name + '" consent changed'; mesh.consent = command.consent; }
|
if ((common.validateInt(command.consent) == true) && (command.consent != mesh.consent)) { if (change != '') change += ' and consent changed'; else change += 'Group "' + mesh.name + '" consent changed'; mesh.consent = command.consent; }
|
||||||
|
|
||||||
|
if (command.invite === '*') {
|
||||||
|
// Clear invite codes
|
||||||
|
if (mesh.invite != null) { delete mesh.invite; }
|
||||||
|
if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; }
|
||||||
|
} else if (typeof command.invite === 'object') {
|
||||||
|
// Set invite codes
|
||||||
|
if ((mesh.invite == null) || (mesh.invite.codes != command.invite.codes) || (mesh.invite.flags != command.invite.flags)) {
|
||||||
|
mesh.invite = { codes: command.invite.codes, flags: command.invite.flags };
|
||||||
|
if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (change != '') {
|
if (change != '') {
|
||||||
db.Set(common.escapeLinksFieldName(mesh));
|
db.Set(common.escapeLinksFieldName(mesh));
|
||||||
var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id };
|
var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite };
|
||||||
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
|
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
|
||||||
parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, event);
|
parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, event);
|
||||||
}
|
}
|
||||||
|
@ -22018,4 +22018,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -2319,6 +2319,7 @@
|
|||||||
if (message.event.consent != null) { meshes[message.event.meshid].consent = message.event.consent; }
|
if (message.event.consent != null) { meshes[message.event.meshid].consent = message.event.consent; }
|
||||||
if (message.event.links) { meshes[message.event.meshid].links = message.event.links; }
|
if (message.event.links) { meshes[message.event.meshid].links = message.event.links; }
|
||||||
if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; }
|
if (message.event.amt) { meshes[message.event.meshid].amt = message.event.amt; }
|
||||||
|
if (message.event.invite != null) { meshes[message.event.meshid].invite = message.event.invite; } else { delete meshes[message.event.meshid].invite; }
|
||||||
|
|
||||||
// Check if we lost rights to this mesh in this change.
|
// Check if we lost rights to this mesh in this change.
|
||||||
if (IsMeshViewable(message.event.meshid) == false) {
|
if (IsMeshViewable(message.event.meshid) == false) {
|
||||||
@ -8136,7 +8137,7 @@
|
|||||||
x += addHtmlValue("User Consent", addLinkConditional(meshFeatures, 'p20editmeshconsent()', meshrights & 1));
|
x += addHtmlValue("User Consent", addLinkConditional(meshFeatures, 'p20editmeshconsent()', meshrights & 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display user consent
|
// Display user notification
|
||||||
var meshNotify = 0, meshNotifyStr = [];
|
var meshNotify = 0, meshNotifyStr = [];
|
||||||
if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
|
if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
|
||||||
if (meshNotify & 2) { meshNotifyStr.push("Connect"); }
|
if (meshNotify & 2) { meshNotifyStr.push("Connect"); }
|
||||||
@ -8145,6 +8146,14 @@
|
|||||||
if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "None" + '</i>'); }
|
if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "None" + '</i>'); }
|
||||||
x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
|
x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
|
||||||
|
|
||||||
|
// Display invitation codes
|
||||||
|
if (features & 0x01000000) {
|
||||||
|
var inviteCodeStr = '<i>' + "None" + '</i>', icodes = false;
|
||||||
|
if (currentMesh.invite != null) { icodes = true; inviteCodeStr = currentMesh.invite.codes.join(', '); /* + ', ' + currentMesh.invite.flags;*/ }
|
||||||
|
//x += addHtmlValue("Invite Codes", addLink(inviteCodeStr, 'p20editmeshInviteCode()'));
|
||||||
|
x += addHtmlValue("Invite Codes", addLinkConditional(inviteCodeStr, 'p20editmeshInviteCode()', (meshrights & 1) || (icodes)));
|
||||||
|
}
|
||||||
|
|
||||||
// Intel AMT setup
|
// Intel AMT setup
|
||||||
var intelAmtPolicy = "No Policy";
|
var intelAmtPolicy = "No Policy";
|
||||||
if (currentMesh.amt) {
|
if (currentMesh.amt) {
|
||||||
@ -8659,6 +8668,63 @@
|
|||||||
function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); return false; }
|
function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); return false; }
|
||||||
function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
|
function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
|
||||||
|
|
||||||
|
function p20editmeshInviteCode() {
|
||||||
|
if (xxdialogMode) return false;
|
||||||
|
var meshrights = GetMeshRights(currentMesh);
|
||||||
|
|
||||||
|
var servername = serverinfo.name;
|
||||||
|
if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
|
||||||
|
var url;
|
||||||
|
if (serverinfo.https == true) {
|
||||||
|
var portStr = (serverinfo.port == 443) ? '' : (':' + serverinfo.port);
|
||||||
|
url = 'https://' + servername + portStr + domainUrl + 'invite';
|
||||||
|
} else {
|
||||||
|
var portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port);
|
||||||
|
url = 'http://' + servername + portStr + domainUrl + 'invite';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meshrights & 1) {
|
||||||
|
// We can edit the mesh invite codes
|
||||||
|
var x = "When enabled, invitation codes can be used by anyone to join devices to this device group using the following public link:" + '<br /><br />';
|
||||||
|
x += '<div style=width:100%;text-align:center><a target=_blank href="' + url + '">' + url + '</a></div><br />';
|
||||||
|
x += '<div style=margin-bottom:5px><label><input id=agentJoinCheck type=checkbox onclick=p20editmeshInviteCodeValidate() />' + "Enable Invite Codes" + '</label></div>';
|
||||||
|
x += addHtmlValue("Invite Codes", '<input id=agentInviteCode style=width:236px onkeyup=p20editmeshInviteCodeValidate() placeholder="code1, code2, code3" />');
|
||||||
|
x += addHtmlValue("Installation Type", '<select id=agentInviteType style=width:236px><option value=0>' + "Background and interactive" + '</option><option value=2>' + "Background only" + '</option><option value=1>' + "Interactive only" + '</option></select>');
|
||||||
|
setDialogMode(2, "Invite Codes", 3, p20editmeshInviteCodeEx, x);
|
||||||
|
if (currentMesh.invite != null) {
|
||||||
|
Q('agentJoinCheck').checked = true;
|
||||||
|
Q('agentInviteCode').value = currentMesh.invite.codes.join(', ');
|
||||||
|
Q('agentInviteType').value = (currentMesh.invite.flags & 3);
|
||||||
|
}
|
||||||
|
p20editmeshInviteCodeValidate();
|
||||||
|
} else {
|
||||||
|
// View codes only
|
||||||
|
var x = "Invitation codes can be used by anyone to join devices to this device group using the following public link:" + '<br /><br />';
|
||||||
|
x += '<div style=width:100%;text-align:center><a target=_blank href="' + url + '">' + url + '</a></div><br />';
|
||||||
|
x += addHtmlValue("Invite Codes", currentMesh.invite.codes.join(', '));
|
||||||
|
x += addHtmlValue("Installation Type", ["Background and interactive", "Background only", "Interactive only"][currentMesh.invite.flags & 3]);
|
||||||
|
setDialogMode(2, "Invite Codes", 1, null, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function p20editmeshInviteCodeValidate() {
|
||||||
|
var ok = true, codes = Q('agentInviteCode').value.split(',');
|
||||||
|
for (var i in codes) { codes[i] = codes[i].trim(); if (codes[i] == '') { ok = false; } }
|
||||||
|
QE('agentInviteCode', Q('agentJoinCheck').checked);
|
||||||
|
QE('agentInviteType', Q('agentJoinCheck').checked);
|
||||||
|
QE('idx_dlgOkButton', (Q('agentJoinCheck').checked == false) || (ok));
|
||||||
|
}
|
||||||
|
|
||||||
|
function p20editmeshInviteCodeEx() {
|
||||||
|
if (Q('agentJoinCheck').checked == true) {
|
||||||
|
var codes = Q('agentInviteCode').value.split(',');
|
||||||
|
for (var i in codes) { codes[i] = codes[i].trim(); }
|
||||||
|
meshserver.send({ action: 'editmesh', meshid: currentMesh._id, invite: { codes: codes, flags: parseInt(Q('agentInviteType').value) } });
|
||||||
|
} else {
|
||||||
|
meshserver.send({ action: 'editmesh', meshid: currentMesh._id, invite: '*' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function p20editMeshNotify() {
|
function p20editMeshNotify() {
|
||||||
if (xxdialogMode) return false;
|
if (xxdialogMode) return false;
|
||||||
var meshNotify = 0;
|
var meshNotify = 0;
|
||||||
|
17
webserver.js
17
webserver.js
@ -1270,8 +1270,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||||
if ((req.body.inviteCode == null) || (req.body.inviteCode == '')) { render(req, res, getRenderPage('invite', req), getRenderArgs({ messageid: 0 }, domain)); return; } // No invitation code
|
if ((req.body.inviteCode == null) || (req.body.inviteCode == '')) { render(req, res, getRenderPage('invite', req), getRenderArgs({ messageid: 0 }, domain)); return; } // No invitation code
|
||||||
|
|
||||||
// Send invitation link, valid for 1 minute.
|
// Each for a device group that has this invite code.
|
||||||
//res.redirect(domain.url + 'agentinvite?c=' + parent.encodeCookie({ a: 4, mid: 'mesh//xxxxx', f: 0, expire: 1 }, parent.invitationLinkEncryptionKey));
|
for (var i in obj.meshes) {
|
||||||
|
if ((obj.meshes[i].invite != null) && (obj.meshes[i].invite.codes.indexOf(req.body.inviteCode) >= 0)) {
|
||||||
|
// Send invitation link, valid for 1 minute.
|
||||||
|
res.redirect(domain.url + 'agentinvite?c=' + parent.encodeCookie({ a: 4, mid: i, f: obj.meshes[i].invite.flags, expire: 1 }, parent.invitationLinkEncryptionKey) + (req.query.key ? ('&key=' + req.query.key) : ''));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render(req, res, getRenderPage('invite', req), getRenderArgs({ messageid: 100 }, domain)); // Bad invitation code
|
render(req, res, getRenderPage('invite', req), getRenderArgs({ messageid: 100 }, domain)); // Bad invitation code
|
||||||
}
|
}
|
||||||
@ -1639,6 +1645,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
if (domain.usernameisemail) { features += 0x00200000; } // Username is email address
|
if (domain.usernameisemail) { features += 0x00200000; } // Username is email address
|
||||||
if (parent.mqttbroker != null) { features += 0x00400000; } // This server supports MQTT channels
|
if (parent.mqttbroker != null) { features += 0x00400000; } // This server supports MQTT channels
|
||||||
if (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (parent.mailserver != null)) { features += 0x00800000; } // using email for 2FA is allowed
|
if (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (parent.mailserver != null)) { features += 0x00800000; } // using email for 2FA is allowed
|
||||||
|
if (domain.agentinvitecodes == true) { features += 0x01000000; } // Support for agent invite codes
|
||||||
|
|
||||||
// Create a authentication cookie
|
// Create a authentication cookie
|
||||||
const authCookie = obj.parent.encodeCookie({ userid: user._id, domainid: domain.id, ip: cleanRemoteAddr(req.ip) }, obj.parent.loginCookieEncryptionKey);
|
const authCookie = obj.parent.encodeCookie({ userid: user._id, domainid: domain.id, ip: cleanRemoteAddr(req.ip) }, obj.parent.loginCookieEncryptionKey);
|
||||||
@ -3609,8 +3616,6 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
obj.app.post(url + 'resetpassword', handleResetPasswordRequest);
|
obj.app.post(url + 'resetpassword', handleResetPasswordRequest);
|
||||||
obj.app.post(url + 'resetaccount', handleResetAccountRequest);
|
obj.app.post(url + 'resetaccount', handleResetAccountRequest);
|
||||||
obj.app.get(url + 'checkmail', handleCheckMailRequest);
|
obj.app.get(url + 'checkmail', handleCheckMailRequest);
|
||||||
obj.app.get(url + 'invite', handleInviteRequest);
|
|
||||||
obj.app.post(url + 'invite', handleInviteRequest);
|
|
||||||
obj.app.get(url + 'agentinvite', handleAgentInviteRequest);
|
obj.app.get(url + 'agentinvite', handleAgentInviteRequest);
|
||||||
obj.app.post(url + 'amtevents.ashx', obj.handleAmtEventRequest);
|
obj.app.post(url + 'amtevents.ashx', obj.handleAmtEventRequest);
|
||||||
obj.app.get(url + 'meshagents', obj.handleMeshAgentRequest);
|
obj.app.get(url + 'meshagents', obj.handleMeshAgentRequest);
|
||||||
@ -3636,6 +3641,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||||||
obj.app.get(url + 'player.htm', handlePlayerRequest);
|
obj.app.get(url + 'player.htm', handlePlayerRequest);
|
||||||
obj.app.get(url + 'player', handlePlayerRequest);
|
obj.app.get(url + 'player', handlePlayerRequest);
|
||||||
obj.app.ws(url + 'amtactivate', handleAmtActivateWebSocket);
|
obj.app.ws(url + 'amtactivate', handleAmtActivateWebSocket);
|
||||||
|
if (parent.config.domains[i].agentinvitecodes == true) {
|
||||||
|
obj.app.get(url + 'invite', handleInviteRequest);
|
||||||
|
obj.app.post(url + 'invite', handleInviteRequest);
|
||||||
|
}
|
||||||
if (parent.pluginHandler != null) {
|
if (parent.pluginHandler != null) {
|
||||||
obj.app.get(url + 'pluginadmin.ashx', obj.handlePluginAdminReq);
|
obj.app.get(url + 'pluginadmin.ashx', obj.handlePluginAdminReq);
|
||||||
obj.app.post(url + 'pluginadmin.ashx', obj.handlePluginAdminPostReq);
|
obj.app.post(url + 'pluginadmin.ashx', obj.handlePluginAdminPostReq);
|
||||||
|
Loading…
Reference in New Issue
Block a user