2020-09-02 15:23:32 +00:00
|
|
|
<style>
|
|
|
|
.title {
|
|
|
|
margin: 1em;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.subtitle {
|
|
|
|
margin: 2em;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.login {
|
|
|
|
margin: 0 auto;
|
|
|
|
max-width: 32em;
|
|
|
|
}
|
|
|
|
|
|
|
|
.login #loginOtp {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
|
2020-09-02 18:30:08 +00:00
|
|
|
#loginForm.is-twofactor #loginOtp {
|
2020-09-02 15:23:32 +00:00
|
|
|
display: block
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
<h1 class="title">{{hostname}}</h1>
|
2014-08-26 11:31:45 +00:00
|
|
|
|
2015-04-28 11:11:41 +00:00
|
|
|
{% if no_users_exist or no_admins_exist %}
|
2014-10-21 10:56:52 +00:00
|
|
|
<div class="row">
|
2014-08-26 11:31:45 +00:00
|
|
|
<div class="col-md-offset-2 col-md-8">
|
2015-04-28 11:11:41 +00:00
|
|
|
{% if no_users_exist %}
|
|
|
|
<p class="text-danger">There are no users on this system! To make an administrative user,
|
|
|
|
log into this machine using SSH (like when you first set it up) and run:</p>
|
|
|
|
<pre>cd mailinabox
|
2020-10-29 19:10:11 +00:00
|
|
|
sudo management/cli.py user add me@{{hostname}}
|
|
|
|
sudo management/cli.py user make-admin me@{{hostname}}</pre>
|
2015-04-28 11:11:41 +00:00
|
|
|
{% else %}
|
2014-08-26 11:31:45 +00:00
|
|
|
<p class="text-danger">There are no administrative users on this system! To make an administrative user,
|
|
|
|
log into this machine using SSH (like when you first set it up) and run:</p>
|
|
|
|
<pre>cd mailinabox
|
2020-10-29 19:10:11 +00:00
|
|
|
sudo management/cli.py user make-admin me@{{hostname}}</pre>
|
2015-04-28 11:11:41 +00:00
|
|
|
{% endif %}
|
2014-08-26 11:31:45 +00:00
|
|
|
<hr>
|
|
|
|
</div>
|
2019-05-12 12:10:34 +00:00
|
|
|
</div>
|
2014-08-26 11:31:45 +00:00
|
|
|
{% endif %}
|
|
|
|
|
2020-09-02 15:23:32 +00:00
|
|
|
<p class="subtitle">Log in here for your Mail-in-a-Box control panel.</p>
|
2014-08-17 22:43:57 +00:00
|
|
|
|
2020-09-02 15:23:32 +00:00
|
|
|
<div class="login">
|
|
|
|
<form id="loginForm" class="form-horizontal" role="form" onsubmit="do_login(); return false;" method="get">
|
2014-08-17 22:43:57 +00:00
|
|
|
<div class="form-group">
|
2014-10-21 10:56:52 +00:00
|
|
|
<label for="inputEmail3" class="col-sm-3 control-label">Email</label>
|
|
|
|
<div class="col-sm-9">
|
2014-08-17 22:43:57 +00:00
|
|
|
<input name="email" type="email" class="form-control" id="loginEmail" placeholder="Email">
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="form-group">
|
2014-10-21 10:56:52 +00:00
|
|
|
<label for="inputPassword3" class="col-sm-3 control-label">Password</label>
|
|
|
|
<div class="col-sm-9">
|
2014-08-17 22:43:57 +00:00
|
|
|
<input name="password" type="password" class="form-control" id="loginPassword" placeholder="Password">
|
|
|
|
</div>
|
|
|
|
</div>
|
2020-09-27 12:31:23 +00:00
|
|
|
<div class="form-group" id="loginOtp">
|
|
|
|
<label for="loginOtpInput" class="col-sm-3 control-label">Code</label>
|
|
|
|
<div class="col-sm-9">
|
2021-07-28 20:39:40 +00:00
|
|
|
<input type="text" class="form-control" id="loginOtpInput" placeholder="6-digit code" autocomplete="off">
|
2020-09-27 12:31:23 +00:00
|
|
|
<div class="help-block" style="margin-top: 5px; font-size: 90%">Enter the six-digit code generated by your two factor authentication app.</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2014-08-17 22:43:57 +00:00
|
|
|
<div class="form-group">
|
2014-10-21 10:56:52 +00:00
|
|
|
<div class="col-sm-offset-3 col-sm-9">
|
2014-08-17 22:43:57 +00:00
|
|
|
<div class="checkbox">
|
|
|
|
<label>
|
|
|
|
<input name='remember' type="checkbox" id="loginRemember"> Remember me
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="form-group">
|
2014-10-21 10:56:52 +00:00
|
|
|
<div class="col-sm-offset-3 col-sm-9">
|
2014-08-17 22:43:57 +00:00
|
|
|
<button type="submit" class="btn btn-default">Sign in</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
function do_login() {
|
|
|
|
if ($('#loginEmail').val() == "") {
|
2015-08-27 20:06:14 +00:00
|
|
|
show_modal_error("Login Failed", "Enter your email address.", function() {
|
2020-09-02 18:30:08 +00:00
|
|
|
$('#loginEmail').focus();
|
2015-08-27 20:06:14 +00:00
|
|
|
});
|
2014-08-17 22:43:57 +00:00
|
|
|
return false;
|
|
|
|
}
|
2020-09-02 18:30:08 +00:00
|
|
|
|
2014-08-17 22:43:57 +00:00
|
|
|
if ($('#loginPassword').val() == "") {
|
2015-08-27 20:06:14 +00:00
|
|
|
show_modal_error("Login Failed", "Enter your email password.", function() {
|
|
|
|
$('#loginPassword').focus();
|
|
|
|
});
|
2014-08-17 22:43:57 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exchange the email address & password for an API key.
|
2021-08-22 20:40:07 +00:00
|
|
|
api_credentials = { username: $('#loginEmail').val(), session_key: $('#loginPassword').val() }
|
2014-08-17 22:43:57 +00:00
|
|
|
|
|
|
|
api(
|
2021-08-22 20:07:16 +00:00
|
|
|
"/login",
|
|
|
|
"POST",
|
2020-09-02 15:23:32 +00:00
|
|
|
{},
|
|
|
|
function(response) {
|
2014-08-17 22:43:57 +00:00
|
|
|
// This API call always succeeds. It returns a JSON object indicating
|
|
|
|
// whether the request was authenticated or not.
|
2020-09-02 15:23:32 +00:00
|
|
|
if (response.status != 'ok') {
|
2020-09-27 12:31:23 +00:00
|
|
|
if (response.status === 'missing-totp-token' || (response.status === 'invalid' && response.reason == 'invalid-totp-token')) {
|
2020-09-02 18:30:08 +00:00
|
|
|
$('#loginForm').addClass('is-twofactor');
|
2020-09-27 12:31:23 +00:00
|
|
|
if (response.reason === "invalid-totp-token") {
|
|
|
|
show_modal_error("Login Failed", "Incorrect two factor authentication token.");
|
|
|
|
} else {
|
|
|
|
setTimeout(() => {
|
|
|
|
$('#loginOtpInput').focus();
|
|
|
|
});
|
|
|
|
}
|
2020-09-02 15:23:32 +00:00
|
|
|
} else {
|
2020-09-02 18:30:08 +00:00
|
|
|
$('#loginForm').removeClass('is-twofactor');
|
2020-09-27 12:31:23 +00:00
|
|
|
|
2020-09-02 15:23:32 +00:00
|
|
|
// Show why the login failed.
|
|
|
|
show_modal_error("Login Failed", response.reason)
|
|
|
|
|
|
|
|
// Reset any saved credentials.
|
|
|
|
do_logout();
|
|
|
|
}
|
2014-11-30 15:43:07 +00:00
|
|
|
} else if (!("api_key" in response)) {
|
|
|
|
// Login succeeded but user might not be authorized!
|
|
|
|
show_modal_error("Login Failed", "You are not an administrator on this system.")
|
|
|
|
|
|
|
|
// Reset any saved credentials.
|
|
|
|
do_logout();
|
|
|
|
|
2014-08-17 22:43:57 +00:00
|
|
|
} else {
|
|
|
|
// Login succeeded.
|
|
|
|
|
|
|
|
// Save the new credentials.
|
2021-08-22 20:40:07 +00:00
|
|
|
api_credentials = { username: response.email,
|
|
|
|
session_key: response.api_key,
|
|
|
|
privileges: response.privileges };
|
2014-08-17 22:43:57 +00:00
|
|
|
|
|
|
|
// Try to wipe the username/password information.
|
|
|
|
$('#loginEmail').val('');
|
|
|
|
$('#loginPassword').val('');
|
2020-09-02 15:23:32 +00:00
|
|
|
$('#loginOtpInput').val('');
|
2020-09-02 18:30:08 +00:00
|
|
|
$('#loginForm').removeClass('is-twofactor');
|
2014-08-17 22:43:57 +00:00
|
|
|
|
|
|
|
// Remember the credentials.
|
|
|
|
if (typeof localStorage != 'undefined' && typeof sessionStorage != 'undefined') {
|
|
|
|
if ($('#loginRemember').val()) {
|
2021-08-22 20:40:07 +00:00
|
|
|
localStorage.setItem("miab-cp-credentials", JSON.stringify(api_credentials));
|
2014-08-17 22:43:57 +00:00
|
|
|
sessionStorage.removeItem("miab-cp-credentials");
|
|
|
|
} else {
|
|
|
|
localStorage.removeItem("miab-cp-credentials");
|
2021-08-22 20:40:07 +00:00
|
|
|
sessionStorage.setItem("miab-cp-credentials", JSON.stringify(api_credentials));
|
2014-08-17 22:43:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-22 20:40:07 +00:00
|
|
|
// Toggle menus.
|
|
|
|
show_hide_menus();
|
|
|
|
|
2014-10-11 16:41:42 +00:00
|
|
|
// Open the next panel the user wants to go to. Do this after the XHR response
|
|
|
|
// is over so that we don't start a new XHR request while this one is finishing,
|
|
|
|
// which confuses the loading indicator.
|
2023-05-13 10:49:34 +00:00
|
|
|
setTimeout(function() {
|
|
|
|
if (window.location.hash) {
|
|
|
|
var panelid = window.location.hash.substring(1);
|
|
|
|
show_panel(panelid);
|
|
|
|
} else {
|
|
|
|
show_panel(
|
|
|
|
!switch_back_to_panel || switch_back_to_panel == "login"
|
|
|
|
? 'welcome'
|
|
|
|
: switch_back_to_panel)
|
|
|
|
}
|
|
|
|
}, 300);
|
|
|
|
|
2014-08-17 22:43:57 +00:00
|
|
|
}
|
2020-09-02 15:23:32 +00:00
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
{
|
|
|
|
'x-auth-token': $('#loginOtpInput').val()
|
|
|
|
});
|
2014-08-17 22:43:57 +00:00
|
|
|
}
|
|
|
|
|
2015-08-27 20:06:14 +00:00
|
|
|
function show_login() {
|
2020-09-02 18:30:08 +00:00
|
|
|
$('#loginForm').removeClass('is-twofactor');
|
2020-09-02 15:23:32 +00:00
|
|
|
$('#loginOtpInput').val('');
|
2015-08-27 20:06:14 +00:00
|
|
|
$('#loginEmail,#loginPassword').each(function() {
|
|
|
|
var input = $(this);
|
|
|
|
if (!$.trim(input.val())) {
|
|
|
|
input.focus();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2021-08-22 20:40:07 +00:00
|
|
|
|
|
|
|
function show_hide_menus() {
|
|
|
|
var is_logged_in = (api_credentials != null);
|
|
|
|
var privs = api_credentials ? api_credentials.privileges : [];
|
|
|
|
$('.if-logged-in').toggle(is_logged_in);
|
|
|
|
$('.if-logged-in-admin, .if-logged-in-not-admin').toggle(false);
|
|
|
|
if (is_logged_in) {
|
|
|
|
$('.if-logged-in-not-admin').toggle(true);
|
|
|
|
privs.forEach(function(priv) {
|
|
|
|
$('.if-logged-in-' + priv).toggle(true);
|
|
|
|
$('.if-logged-in-not-' + priv).toggle(false);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
$('.if-not-logged-in').toggle(!is_logged_in);
|
|
|
|
}
|
2014-08-17 22:43:57 +00:00
|
|
|
</script>
|