Added SMTP email support, email verification and password reset support

This commit is contained in:
Ylian Saint-Hilaire
2017-12-12 16:04:54 -08:00
parent e740045b39
commit 72ee422623
24 changed files with 2586 additions and 166 deletions

View File

@@ -167,6 +167,8 @@
<div id="p2AccountActions">
<p><strong><img alt="" width=150 height=103 src=images/mainaccount.png style=margin-bottom:10px;margin-right:20px;float:right />Account actions</strong></p>
<p style="margin-left:40px">
<a onclick="account_showChangeEmail()" style="cursor:pointer">Change email address</a><br />
<span id="verifyEmailId" style="display:none"><a onclick="account_showVerifyEmail()" style="cursor:pointer">Verify email</a><br /></span>
<a onclick="account_showChangePassword()" style="cursor:pointer">Change password</a><br />
<a onclick="account_showDeleteAccount()" style="cursor:pointer">Delete account</a><br />
</p>
@@ -686,6 +688,22 @@
if (t != null) { desktopsettings = JSON.parse(t); }
applyDesktopSettings();
// Mouse Scroll on desktop
if (navigator.userAgent.match(/mozilla/i)) {
Q('Desk').addEventListener('DOMMouseScroll', function (e) {
return dmousewheel(e);
//if (loginState == 3) { SendMouseMsg(KeyAction.SCROLL, e); return false; }
//return true;
});
}
else {
Q('Desk').addEventListener('mousewheel', function (e) {
return dmousewheel(e);
//if (loginState == 3) { SendMouseMsg(KeyAction.SCROLL, e); return false; }
//return true;
});
}
// Terminal special keys
var x = '';
for (var c = 1; c < 27; c++) x += "<option value='" + c + "'>Ctrl-" + String.fromCharCode(64 + c) + " (" + c + ")</option>";
@@ -760,13 +778,14 @@
function onMessage(server, message) {
switch (message.action) {
case 'serverinfo': {
serverinfo = message.serverinfo;
break;
}
case 'userinfo': {
userinfo = message.userinfo;
updateSiteAdmin();
break;
}
case 'serverinfo': {
serverinfo = message.serverinfo;
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
break;
}
case 'users': {
@@ -910,6 +929,7 @@
if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.Send({ action: 'files' }); }
userinfo = message.event.account;
if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
}
if (users == null) break;
users[message.event.account._id] = message.event.account;
@@ -2971,6 +2991,7 @@
function dmousedown(e) { if (!xxdialogMode && desktop != undefined) desktop.m.mousedown(e) }
function dmouseup(e) { if (!xxdialogMode && desktop != undefined) desktop.m.mouseup(e) }
function dmousemove(e) { if (!xxdialogMode && desktop != undefined) desktop.m.mousemove(e) }
function dmousewheel(e) { if (!xxdialogMode && desktop != undefined) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; }
function drotate(x) { if (!xxdialogMode && desktop != undefined) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
//
@@ -3646,6 +3667,34 @@
// MY ACCOUNT
//
function account_showVerifyEmail() {
if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return;
var x = "Click ok to send a verification mail to:<br /><div style=padding:8px><b>" + EscapeHtml(userinfo.email) + "</b></div>Please wait a few minute to receive the verification.";
setDialogMode(2, "Email Verification", 3, account_showVerifyEmailEx, x);
}
function account_showVerifyEmailEx() {
meshserver.Send({ action: 'verifyemail', email: userinfo.email });
}
function account_showChangeEmail() {
if (xxdialogMode) return;
var x = "Change your account e-mail address here.<br /><br />";
x += addHtmlValue('Email', '<input id=dp2email style=width:230px maxlength=32 onchange=account_validateEmail() onkeyup=account_validateEmail() />');
setDialogMode(2, "Email Address Change", 3, account_changeEmail, x);
if (userinfo.email != null) { Q('dp2email').value = userinfo.email; }
account_validateEmail();
}
function account_validateEmail() {
var x = Q('dp2email').value.split('@');
QE('idx_dlgOkButton', (x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2) && (Q('dp2email').value.length < 1024) && (Q('dp2email').value != userinfo.email));
}
function account_changeEmail() {
meshserver.Send({ action: 'changeemail', email: Q('dp2email').value });
}
function account_showDeleteAccount() {
if (xxdialogMode) return;
var x = "To delete this account, type in the account password in both boxes below and hit ok.<br /><br />";
@@ -4229,7 +4278,7 @@
if ((user.quota != undefined) && ((user.siteadmin & 8) != 0)) { msg += ", " + (user.quota / 1024) + " k"; }
if (user.name != userinfo.name) { msg += "</a>"; }
if (user.email != null) {
msg = '<table style=width:100%><tr><td>' + EscapeHtml(user.name) + ', <a onclick=doemail(event,\"' + user.email + '\")>' + user.email + '</a><td align=right>' + msg + '</table>';
msg = '<table style=width:100%><tr><td>' + EscapeHtml(user.name) + ', <a onclick=doemail(event,\"' + user.email + '\")>' + user.email + '</a>' + (((serverinfo.emailcheck == true) && (user.emailVerified != true))?' (unverified)':'') + '<td align=right>' + msg + '</table>';
} else {
msg = '<table style=width:100%><tr><td>' + EscapeHtml(user.name) + '<td align=right>' + msg + '</table>';
}

View File

@@ -53,8 +53,12 @@
<td align=right><input id=loginButton type=submit value="Log In" disabled="disabled" /></td>
</tr>
</table>
<div id="newAccountDiv" style="display:none">
<hr />Don&#39;t have an account? <a onclick=xgo(2) style=cursor:pointer>Create one</a>.
<div id="hrAccountDiv" style="display:none"><hr /></div>
<div id="resetAccountDiv" style="display:none;padding:2px">
Forgot username/password? <a onclick=xgo(3) style=cursor:pointer>Reset account</a>.
</div>
<div id="newAccountDiv" style="display:none;padding:2px">
Don&#39;t have an account? <a onclick=xgo(2) style=cursor:pointer>Create one</a>.
</div>
</form>
</div>
@@ -101,6 +105,29 @@
<hr /><a onclick=xgo(1) style=cursor:pointer>Back to login</a>
</form>
</div>
<div id=resetpanel style="background-color: #979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
<form action=resetaccount method=post>
<div id=message3>
{{{message}}}
</div>
<div>
<b>Account Reset</b>
</div>
<table>
<tr>
<td align=right width=100>Email:</td>
<td><input id=remail type=text name=email onchange=validateReset() onkeyup=validateReset() /></td>
</tr>
<tr>
<td colspan=2>
<div style=float:right><input id=eresetButton type=submit value="Reset Account" disabled="disabled" /></div>
<div id=passWarning style="padding-top:6px"></div>
</td>
</tr>
</table>
<hr /><a onclick=xgo(1) style=cursor:pointer>Back to login</a>
</form>
</div>
</td>
</tr>
</table>
@@ -141,6 +168,7 @@
<script>
var passhint = "{{{passhint}}}";
var newAccountPass = {{{newAccountPass}}};
var emailCheck = {{{emailcheck}}};
function startup() {
window.onresize = center;
@@ -151,6 +179,8 @@
QV('newAccountDiv', '{{{newAccount}}}' != '0' );
if ((passhint != null) && (passhint.length > 0)) { QV("showPassHintLink", true); }
QV("newAccountPass", (newAccountPass == 1));
QV("resetAccountDiv", (emailCheck == true));
QV("hrAccountDiv", (emailCheck == true) || (newAccountPass == 1))
}
function showPassHint() {
@@ -168,6 +198,7 @@
QV("showPassHintLink", false);
QV('loginpanel', x == 1);
QV('createpanel', x == 2);
QV('resetpanel', x == 3);
}
function validateLogin() {
@@ -178,7 +209,7 @@
function validateCreate() {
setDialogMode(0);
var ok = (Q('ausername').value.length > 0 && Q('aemail').value.length > 0 && Q('apassword1').value.length > 0 && (Q('apassword2').value == Q('apassword1').value));
var ok = ((Q('ausername').value.length > 0) && (checkEmail(Q('aemail').value) == true) && (Q('apassword1').value.length > 0) && (Q('apassword2').value == Q('apassword1').value));
if ((newAccountPass == 1) && (Q('anewaccountpass').value.length == 0)) { ok = false; }
QE('createButton', ok);
if (Q('apassword1').value == '') {
@@ -191,6 +222,19 @@
}
}
function validateReset() {
setDialogMode(0);
QE('eresetButton', checkEmail(Q('remail').value));
}
// Return true is the input string looks like an email address
function checkEmail(str) {
var x = str.split('@');
var ok = ((x.length == 2) && (x[0].length > 0) && (x[1].split('.').length > 1) && (x[1].length > 2));
if (ok == true) { var y = x[1].split('.'); for (var i in y) { if (y[i].length == 0) { ok = false; } } }
return ok;
}
// Return a password strength score
function checkPasswordStrength(password) {
var r = 0, letters = {}, varCount = 0, variations = { digits: /\d/.test(password), lower: /[a-z]/.test(password), upper: /[A-Z]/.test(password), nonWords: /\W/.test(password) }

42
views/message.handlebars Normal file
View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv=X-UA-Compatible content="IE=edge" />
<meta content="text/html;charset=utf-8" http-equiv=Content-Type />
<meta name=viewport content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
<meta name=apple-mobile-web-app-capable content=yes />
<meta name=format-detection content="telephone=no" />
<link type=text/css href="/styles/style.css" media="screen" rel="stylesheet" title="CSS" />
<title>MeshCentral - {{{title3}}}</title>
</head>
<body>
<div id=container style=max-height:100vh>
<div id=mastheadx></div>
<div id=masthead style="background:url(/images/logoback.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden">
<div style=float:left;height:66px;color:#c8c8c8;padding-left:20px;padding-top:8px>
<strong><font style="font-size:46px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
</div>
<div style=float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:14px>
<strong><font style="font-size:14px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
</div>
</div>
<div id=page_content style=max-height:calc(100vh-138px)>
<div id=column_l>
<h1>{{{title3}}}</h1>
<p style=margin-left:20px>{{{message}}}</p>
<br />
</div>
<div id=footer>
<table cellpadding=0 cellspacing=10 style=width:100%>
<tr>
<td style=text-align:left></td>
<td style=text-align:right>
<a href=terms>Terms &amp; Privacy</a>
</td>
</tr>
</table>
</div>
</div>
</div>
</body>
</html>