334 lines
19 KiB
Handlebars
334 lines
19 KiB
Handlebars
<!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" />
|
|
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
|
<title>MeshCentral - Login</title>
|
|
</head>
|
|
<body onload="if (typeof(startup) !== 'undefined') startup();">
|
|
<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>Welcome</h1>
|
|
<p>Connect to your home or office devices from anywhere in the world using MeshCentral, the remote monitoring and management web site. You will need to download and install a special management agent on your computers. Once installed, each mesh enabled computer will show up in the "My Devices" section of this web site and you will be able to monitor them, power them on and off and take control of them.</p>
|
|
<table style=width:100%>
|
|
<tr>
|
|
<td style=width:500px valign=top>
|
|
<img alt="" height=310 src=images/mainwelcome.png width=359 style="margin-left:70px" />
|
|
</td>
|
|
<td>
|
|
<div id=loginpanel style="background-color: #979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
|
|
<form action="login" method=post>
|
|
<div id=message1>
|
|
{{{message}}}
|
|
</div>
|
|
<div>
|
|
<b>Log In</b>
|
|
</div>
|
|
<table>
|
|
<tr>
|
|
<td align=right width=100>Username:</td>
|
|
<td><input id=username type=text name=username onchange=validateLogin(1) onkeyup=validateLogin(1,event) /></td>
|
|
</tr>
|
|
<tr>
|
|
<td align=right>Password:</td>
|
|
<td><input id=password type=password name=password autocomplete=off onchange=validateLogin(2) onkeyup=validateLogin(2,event) /></td>
|
|
</tr>
|
|
<tr>
|
|
<td><div id=showPassHintLink style=display:none><a onclick=showPassHint() style="cursor:pointer">Show Hint</a></div></td>
|
|
<td align=right><input id=loginButton type=submit value="Log In" disabled="disabled" /></td>
|
|
</tr>
|
|
</table>
|
|
<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't have an account? <a onclick=xgo(2) style=cursor:pointer>Create one</a>.
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div id=createpanel style="background-color: #979797;border-radius:16px;width:300px;padding:16px;text-align:center;display:none">
|
|
<form action=createaccount method=post>
|
|
<div id=message2>
|
|
{{{message}}}
|
|
</div>
|
|
<div>
|
|
<b>Account Creation</b>
|
|
</div>
|
|
<table>
|
|
<tr>
|
|
<td align=right width=100>Username:</td>
|
|
<td><input id=ausername type=text name=username onchange=validateCreate(1) onkeydown=haltReturn(event) onkeyup=validateCreate(1,event) /></td>
|
|
</tr>
|
|
<tr>
|
|
<td align=right width=100>Email:</td>
|
|
<td><input id=aemail type=text name=email onchange=validateCreate(2) onkeydown=haltReturn(event) onkeyup=validateCreate(2,event) /></td>
|
|
</tr>
|
|
<tr>
|
|
<td align=right>Password:</td>
|
|
<td><input id=apassword1 type=password name=password1 autocomplete=off onkeydown=haltReturn(event) onchange=validateCreate(3) onkeyup=validateCreate(3,event) /></td>
|
|
</tr>
|
|
<tr>
|
|
<td align=right>Password:</td>
|
|
<td><input id=apassword2 type=password name=password2 autocomplete=off onkeydown=haltReturn(event) onchange=validateCreate(4) onkeyup=validateCreate(4,event) /></td>
|
|
</tr>
|
|
<tr>
|
|
<td align=right>Password Hint:</td>
|
|
<td><input id=apasswordhint type=text name=apasswordhint autocomplete=off maxlength=250 onkeydown=haltReturn(event) onchange=validateCreate(5) onkeyup=validateCreate(5,event) /></td>
|
|
</tr>
|
|
<tr id=newAccountPass title="Enter the account creation token">
|
|
<td align=right>Creation Token:</td>
|
|
<td><input id=anewaccountpass type=password name=anewaccountpass autocomplete=off maxlength=250 onkeydown=haltReturn(event) onchange=validateCreate(6) onkeyup=validateCreate(6,event) /></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan=2>
|
|
<div style=float:right><input id=createButton type=submit value="Create 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>
|
|
<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(event) /></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>
|
|
<br />
|
|
</div>
|
|
<div id=footer>
|
|
<table cellpadding=0 cellspacing=10 style=width:100%>
|
|
<tr>
|
|
<td style=text-align:left;color:white>
|
|
{{{footer}}}
|
|
</td>
|
|
<td style=text-align:right>
|
|
{{{rootCertLink}}}
|
|
<a href=terms>Terms & Privacy</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id=dialog style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:5px;position:fixed;top:180px;width:400px;display:none">
|
|
<div style="width:100%;background-color:#003366;color:#FFF;border-radius:5px 5px 0 0">
|
|
<div id=id_dialogclose style=float:right;padding:5px;cursor:pointer onclick=setDialogMode()><b>X</b></div>
|
|
<div id=id_dialogtitle style=padding:5px></div>
|
|
<div style=width:100%;margin:6px></div>
|
|
</div>
|
|
<div style="margin-right:16px;margin-left:8px">
|
|
<div id=dialog1 style="margin:auto;text-align:center;margin:3px">
|
|
<div id=id_dialogMessage style="padding:10px"></div>
|
|
</div>
|
|
<div id=dialog2 style="margin:auto;margin:3px">
|
|
<div id=id_dialogOptions></div>
|
|
</div>
|
|
</div>
|
|
<div id="idx_dlgButtonBar" style="padding:10px;margin-bottom:20px">
|
|
<input id="idx_dlgCancelButton" type="button" value="Cancel" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
|
|
<input id="idx_dlgOkButton" type="button" value="OK" style="float:right;width:80px" onclick="dialogclose(1)">
|
|
</div>
|
|
</div>
|
|
<script>
|
|
var passhint = "{{{passhint}}}";
|
|
var newAccountPass = {{{newAccountPass}}};
|
|
var emailCheck = {{{emailcheck}}};
|
|
var features = {{{features}}};
|
|
|
|
function startup() {
|
|
if ((features & 32) == 0) {
|
|
// Guard against other site's top frames (web bugs).
|
|
var loc = null;
|
|
try { loc = top.location.toString().toLowerCase(); } catch (e) { }
|
|
if (top != self && (loc == null || top.active == false)) { top.location = self.location; return; }
|
|
}
|
|
|
|
window.onresize = center;
|
|
center();
|
|
validateLogin();
|
|
validateCreate();
|
|
if ('{{loginmode}}' != '') { go({{loginmode}}); } else { go(1); }
|
|
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() {
|
|
messagebox("Password Hint", passhint);
|
|
}
|
|
|
|
function xgo(x) {
|
|
QV('message1', false);
|
|
QV('message2', false);
|
|
go(x);
|
|
}
|
|
|
|
function go(x) {
|
|
setDialogMode(0);
|
|
QV("showPassHintLink", false);
|
|
QV('loginpanel', x == 1);
|
|
QV('createpanel', x == 2);
|
|
QV('resetpanel', x == 3);
|
|
if (x == 1) { Q('username').focus(); }
|
|
if (x == 2) { Q('ausername').focus(); }
|
|
if (x == 3) { Q('remail').focus(); }
|
|
}
|
|
|
|
function validateLogin(box, e) {
|
|
var ok = (Q('username').value.length > 0 && Q('password').value.length > 0);
|
|
QE('loginButton', ok);
|
|
setDialogMode(0);
|
|
if ((e != null) && (e.keyCode == 13)) {
|
|
if (box == 1) { Q('password').focus(); }
|
|
if (box == 2) { Q('loginButton').click(); }
|
|
}
|
|
if (e != null) { haltEvent(e); }
|
|
}
|
|
|
|
function validateCreate(box,e) {
|
|
setDialogMode(0);
|
|
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 == '') {
|
|
QH('passWarning', '');
|
|
} else {
|
|
var passStrength = checkPasswordStrength(Q('apassword1').value);
|
|
if (passStrength >= 80) { QH('passWarning', '<span style=color:green><b>Strong Password</b><span>'); }
|
|
else if (passStrength >= 60) { QH('passWarning', '<span style=color:blue><b>Good Password</b><span>'); }
|
|
else { QH('passWarning', '<span style=color:red><b>Weak Password</b><span>'); }
|
|
}
|
|
if ((e != null) && (e.keyCode == 13)) {
|
|
if (box == 1) { Q('aemail').focus(); }
|
|
if (box == 2) { Q('apassword1').focus(); }
|
|
if (box == 3) { Q('apassword2').focus(); }
|
|
if (box == 4) { Q('apasswordhint').focus(); }
|
|
if (box == 5) {
|
|
if (newAccountPass == 1) {
|
|
Q('anewaccountpass').focus();
|
|
} else {
|
|
Q('createButton').click();
|
|
}
|
|
}
|
|
if (box == 6) {
|
|
Q('createButton').click();
|
|
}
|
|
}
|
|
if (e != null) { haltEvent(e); }
|
|
}
|
|
|
|
function validateReset(e) {
|
|
setDialogMode(0);
|
|
var x = checkEmail(Q('remail').value);
|
|
QE('eresetButton', x);
|
|
if ((e != null) && (e.keyCode == 13) && (x == true)) {
|
|
Q('eresetButton').click();
|
|
}
|
|
if (e != null) { haltEvent(e); }
|
|
}
|
|
|
|
// 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) }
|
|
if (!password) return 0;
|
|
for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
|
|
for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
|
|
return parseInt(r + (varCount - 1) * 10);
|
|
}
|
|
|
|
|
|
//
|
|
// POPUP DIALOG
|
|
//
|
|
|
|
// undefined = Hidden, 1 = Generic Message
|
|
var xxdialogMode;
|
|
var xxdialogFunc;
|
|
var xxdialogButtons;
|
|
var xxdialogTag;
|
|
var xxcurrentView = 0;
|
|
|
|
// Display a dialog box
|
|
// Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
|
|
function setDialogMode(x, y, b, f, c, tag) {
|
|
xxdialogMode = x;
|
|
xxdialogFunc = f;
|
|
xxdialogButtons = b;
|
|
xxdialogTag = tag;
|
|
QE('idx_dlgOkButton', true);
|
|
QV('idx_dlgOkButton', b & 1);
|
|
QV('idx_dlgCancelButton', b & 2);
|
|
QV('id_dialogclose', (b & 2) || (b & 8));
|
|
QV('idx_dlgButtonBar', b & 7);
|
|
if (y) QH('id_dialogtitle', y);
|
|
for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
|
|
QV('dialog', x);
|
|
if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
|
|
}
|
|
|
|
function dialogclose(x) {
|
|
var f = xxdialogFunc;
|
|
var b = xxdialogButtons;
|
|
var t = xxdialogTag;
|
|
setDialogMode();
|
|
if (((b & 8) || x) && f) f(x, t);
|
|
}
|
|
|
|
function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + "px"); }
|
|
function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
|
|
function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
|
|
function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
|
|
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
|
|
function haltReturn(e) { if (e.keyCode == 13) { haltEvent(e); } }
|
|
|
|
</script>
|
|
</body>
|
|
</html> |