diff --git a/meshmail.js b/meshmail.js
index 02806410..d4580663 100644
--- a/meshmail.js
+++ b/meshmail.js
@@ -39,9 +39,12 @@ module.exports.CreateMeshMail = function (parent) {
// Set default mail templates
// You can override these by placing a file with the same name in "meshcentral-data/mail"
// If the server hash many domains, just add the domainid to the file like this: 'account-check-customer1.html', 'mesh-invite-customer1.txt'.
+ obj.mailTemplates['account-invite.html'] = '
[[[SERVERNAME]]] - Account Invitation\r\n
[[[SERVERNAME]]] - Account Invitation
An account was created for you on server [[[SERVERNAME]]], you can access it now with:
To install the software, click here and follow the instructions.
[[[/AREA-LINK]]]
If you did not initiate this request, please ignore this mail.
Best regards, [[[USERNAME]]]
';
+
+ obj.mailTemplates['account-invite.txt'] = '[[[SERVERNAME]]] - Account Invitation\r\nAn account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username \"[[[ACCOUNTNAME]]]\" and password \"[[[PASSWORD]]]\".\r\n\r\nBest regards,\r\n[[[USERNAME]]]';
obj.mailTemplates['account-check.txt'] = '[[[SERVERNAME]]] - Email Verification\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]\r\n\r\nIf you did not initiate this request, please ignore this mail.\r\n';
obj.mailTemplates['account-reset.txt'] = '[[[SERVERNAME]]] - Account Reset\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]\r\n\r\nIf you did not initiate this request, please ignore this mail.';
obj.mailTemplates['mesh-invite.txt'] = '[[[SERVERNAME]]] - Invitation\r\n[[[AREA-NAME]]]Hello [[[NAME]]],\r\n\r\n[[[/AREA-NAME]]]User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session.[[[AREA-MSG]]]\r\n\r\nMessage: [[[MSG]]]\r\n\r\n[[[/AREA-MSG]]][[[AREA-WINDOWS]]]For Windows, nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]\r\n\r\n[[[/AREA-WINDOWS]]][[[AREA-OSX]]]For Apple OSX, nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]\r\n\r\n[[[/AREA-OSX]]][[[AREA-LINUX]]]For Linux, cut & paste the following in a terminal to install the agent:\r\n\r\nwget -q [[[SERVERURL]]]/meshagents?script=1 --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'\r\n\r\n[[[/AREA-LINUX]]][[[AREA-LINK]]]To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions.\r\n\r\n[[[/AREA-LINK]]]If you did not initiate this request, please ignore this mail.\r\n\r\nBest regards,\r\n[[[USERNAME]]]';
@@ -126,6 +129,19 @@ module.exports.CreateMeshMail = function (parent) {
sendNextMail();
};
+ // Send account invitation mail
+ obj.sendAccountInviteMail = function (domain, username, accountname, email, password) {
+ var template = getTemplateEx('account-invite', domain);
+ if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, invitation not possible.
+
+ // Set all the options.
+ var options = { username: username, accountname: accountname, email: email, servername: domain.title, password: password };
+
+ // Send the email
+ obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) });
+ sendNextMail();
+ };
+
// Send account check mail
obj.sendAccountCheckMail = function (domain, username, email) {
var template = getTemplateEx('account-check', domain);
diff --git a/meshuser.js b/meshuser.js
index e26b071a..1d66b12c 100644
--- a/meshuser.js
+++ b/meshuser.js
@@ -1139,6 +1139,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// If the email is the username, set this here.
if (domain.usernameisemail) { if (command.email) { command.username = command.email; } else { command.email = command.username; } }
+ // Randomize the password if needed
+ if (command.randomPassword === true) { command.pass = getRandomPassword(); }
+
// Add a new user account
var err = null, newusername, newuserid;
try {
@@ -1147,7 +1150,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
else if (common.validateUsername(command.username, 1, 256) == false) { err = 'Invalid username'; } // Username is between 1 and 64 characters, no spaces
else if (common.validateString(command.pass, 1, 256) == false) { err = 'Invalid password'; } // Password is between 1 and 256 characters
else if (command.username.indexOf('/') >= 0) { err = 'Invalid username'; } // Usernames can't have '/'
- else if (common.checkPasswordRequirements(command.pass, domain.passwordrequirements) == false) { err = 'Invalid password'; } // Password does not meet requirements
+ else if ((command.randomPassword !== true) && (common.checkPasswordRequirements(command.pass, domain.passwordrequirements) == false)) { err = 'Invalid password'; } // Password does not meet requirements
else if ((command.email != null) && (common.validateEmail(command.email, 1, 1024) == false)) { err = 'Invalid email'; } // Check if this is a valid email address
else {
newusername = command.username;
@@ -1210,6 +1213,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if (parent.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to create the user. Another event will come.
parent.parent.DispatchEvent(targets, obj, event);
+ // Perform email invitation
+ if ((command.emailInvitation == true) && (command.emailVerified == true) && command.email && parent.parent.mailserver) {
+ parent.parent.mailserver.sendAccountInviteMail(domain, user.name, newusername, command.email.toLowerCase(), command.pass);
+ }
+
// OK Response
if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'adduser', responseid: command.responseid, result: 'ok' })); } catch (ex) { } }
} else {
@@ -2857,6 +2865,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Clean a IPv6 address that encodes a IPv4 address
function cleanRemoteAddr(addr) { if (addr.startsWith('::ffff:')) { return addr.substring(7); } else { return addr; } }
+ function getRandomPassword() { return Buffer.from(parent.crypto.randomBytes(9), 'binary').toString('base64').split('/').join('@'); }
return obj;
};
\ No newline at end of file
diff --git a/package.json b/package.json
index 24fbcb18..dd2675dc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "meshcentral",
- "version": "0.3.8-h",
+ "version": "0.3.8-i",
"keywords": [
"Remote Management",
"Intel AMT",
diff --git a/views/default-min.handlebars b/views/default-min.handlebars
index 64666d70..13b72073 100644
--- a/views/default-min.handlebars
+++ b/views/default-min.handlebars
@@ -1 +1 @@
- {{{title}}}
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
Remote computer is not powered on, click here to issue a power command.
Disconnected
Files -
Disconnected
✓
✗
Intel® AMT -
Events -
Show
General -
General -
Events -
Show
My Server Stats
Log-X
✖
File Selection
Upload File
Agent Remote Desktop
Quality
Scaling
Frame rate
Intel® AMT Hardware KVM
Image Encoding
Other Settings
\ No newline at end of file
diff --git a/views/default.handlebars b/views/default.handlebars
index 99994c7c..c1ab3031 100644
--- a/views/default.handlebars
+++ b/views/default.handlebars
@@ -7365,8 +7365,12 @@
x += addHtmlValue('Email', '');
x += addHtmlValue('Password', '');
x += addHtmlValue('Password', '');
- x += '
Force password reset on next login.
';
- if (serverinfo.emailcheck) { x += '
Email is verified.
'; }
+ x += '
Randomize the password.
';
+ x += '
Force password reset on next login.
';
+ if (serverinfo.emailcheck) {
+ x += '
Email is verified.
';
+ x += '
Send invitation email.
';
+ }
if (passRequirements) {
var r = [], rc = 0;
@@ -7380,18 +7384,31 @@
}
function showCreateNewAccountDialogValidate(x) {
- if ((x == null) && (Q('p4email').value.length > 0) && (validateEmail(Q('p4email').value)) == false) { QE('idx_dlgOkButton', false); return; }
+ var ve = validateEmail(Q('p4email').value);
+ if (serverinfo.emailcheck) {
+ QE('p4verifiedEmail', ve);
+ QE('p4invitationEmail', ve && Q('p4resetNextLogin').checked && Q('p4verifiedEmail').checked);
+ if (ve == false) { Q('p4verifiedEmail').checked = false; }
+ if ((Q('p4resetNextLogin').checked == false) || (Q('p4verifiedEmail').checked == false)) { Q('p4invitationEmail').checked = false; }
+ }
+ QE('p4pass1', !Q('p4randomPassword').checked);
+ QE('p4pass2', !Q('p4randomPassword').checked);
+
+ if ((x == null) && (Q('p4email').value.length > 0) && (ve == false)) { QE('idx_dlgOkButton', false); return; }
var ok = true;
if ((features & 0x200000) == 0) { ok &= (!Q('p4name') || ((Q('p4name').value.length > 0) && (Q('p4name').value.indexOf(' ') == -1))); }
- ok &= (Q('p4pass1').value.length > 0 && Q('p4pass1').value == Q('p4pass2').value && checkPasswordRequirements(Q('p4pass1').value, passRequirements));
+ if (Q('p4randomPassword').checked == false) { ok &= (Q('p4pass1').value.length > 0 && Q('p4pass1').value == Q('p4pass2').value && checkPasswordRequirements(Q('p4pass1').value, passRequirements)); }
if (ok && passRequirements) { if (checkPasswordRequirements(Q('p4pass1').value, passRequirements) == false) { ok = false; } }
QE('idx_dlgOkButton', ok);
}
function showCreateNewAccountDialogEx() {
var username = ((features & 0x200000) == 0) ? Q('p4name').value : Q('p4email').value;
- var x = { action: 'adduser', username: username, email: Q('p4email').value, pass: Q('p4pass1').value, resetNextLogin: Q('p4resetNextLogin').checked };
- if (serverinfo.emailcheck) { x.emailVerified = Q('p4verifiedEmail').checked; }
+ var x = { action: 'adduser', username: username, email: Q('p4email').value, pass: Q('p4pass1').value, resetNextLogin: Q('p4resetNextLogin').checked, randomPassword: Q('p4randomPassword').checked };
+ if (serverinfo.emailcheck) {
+ x.emailVerified = Q('p4verifiedEmail').checked;
+ x.emailInvitation = Q('p4invitationEmail').checked;
+ }
meshserver.send(x);
}