<style> .title { margin: 1em; text-align: center; } .subtitle { margin: 2em; text-align: center; } .login { margin: 0 auto; max-width: 32em; } .login #loginOtp { display: none; } #loginForm.is-twofactor #loginOtp { display: block } </style> <h1 class="title">{{hostname}}</h1> {% if no_users_exist or no_admins_exist %} <div class="row"> <div class="col-md-offset-2 col-md-8"> {% 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 sudo tools/mail.py user add me@{{hostname}} sudo tools/mail.py user make-admin me@{{hostname}}</pre> {% else %} <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 sudo tools/mail.py user make-admin me@{{hostname}}</pre> {% endif %} <hr> </div> </div> {% endif %} <p class="subtitle">Log in here for your Mail-in-a-Box control panel.</p> <div class="login"> <form id="loginForm" class="form-horizontal" role="form" onsubmit="do_login(); return false;" method="get"> <div class="form-group"> <label for="inputEmail3" class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input name="email" type="email" class="form-control" id="loginEmail" placeholder="Email"> </div> </div> <div class="form-group"> <label for="inputPassword3" class="col-sm-3 control-label">Password</label> <div class="col-sm-9"> <input name="password" type="password" class="form-control" id="loginPassword" placeholder="Password"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <div class="checkbox"> <label> <input name='remember' type="checkbox" id="loginRemember"> Remember me </label> </div> </div> </div> <div class="form-group" id="loginOtp"> <div class="col-sm-offset-3 col-sm-9"> <label for="loginOtpInput" class="control-label">Two-Factor Code</label> <input type="text" class="form-control" id="loginOtpInput" placeholder="6-digit code"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-default">Sign in</button> </div> </div> </form> </div> <script> function do_login() { if ($('#loginEmail').val() == "") { show_modal_error("Login Failed", "Enter your email address.", function() { $('#loginEmail').focus(); }); return false; } if ($('#loginPassword').val() == "") { show_modal_error("Login Failed", "Enter your email password.", function() { $('#loginPassword').focus(); }); return false; } // Exchange the email address & password for an API key. api_credentials = [$('#loginEmail').val(), $('#loginPassword').val()] api( "/me", "GET", {}, function(response) { // This API call always succeeds. It returns a JSON object indicating // whether the request was authenticated or not. if (response.status != 'ok') { if (response.status === 'missing_token' && !$('#loginForm').hasClass('is-twofactor')) { $('#loginForm').addClass('is-twofactor'); setTimeout(() => { $('#loginOtpInput').focus(); }); } else { $('#loginForm').removeClass('is-twofactor'); // Show why the login failed. show_modal_error("Login Failed", response.reason) // Reset any saved credentials. do_logout(); } } 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(); } else { // Login succeeded. // Save the new credentials. api_credentials = [response.email, response.api_key]; // Try to wipe the username/password information. $('#loginEmail').val(''); $('#loginPassword').val(''); $('#loginOtpInput').val(''); $('#loginForm').removeClass('is-twofactor'); // Remember the credentials. if (typeof localStorage != 'undefined' && typeof sessionStorage != 'undefined') { if ($('#loginRemember').val()) { localStorage.setItem("miab-cp-credentials", api_credentials.join(":")); sessionStorage.removeItem("miab-cp-credentials"); } else { localStorage.removeItem("miab-cp-credentials"); sessionStorage.setItem("miab-cp-credentials", api_credentials.join(":")); } } // 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. setTimeout(function() { show_panel(!switch_back_to_panel || switch_back_to_panel == "login" ? 'system_status' : switch_back_to_panel) }, 300); } }, undefined, { 'x-auth-token': $('#loginOtpInput').val() }); } function show_login() { $('#loginForm').removeClass('is-twofactor'); $('#loginOtpInput').val(''); $('#loginEmail,#loginPassword').each(function() { var input = $(this); if (!$.trim(input.val())) { input.focus(); return false; } }); } </script>