Skip to content
This repository has been archived by the owner on Jul 12, 2023. It is now read-only.

OTP entry form instead of window alert #556

Merged
merged 9 commits into from
Sep 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 28 additions & 21 deletions cmd/server/assets/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
cursor: pointer;
text-decoration: none;
}

a.disabled {
color: lightgray;
pointer-events: none;
}
</style>
{{end}}

Expand Down Expand Up @@ -229,25 +234,27 @@ <h6 class="dropdown-header">Actions</h6>
{{end}}

{{define "flash"}}
{{range $msg := .flash.Errors}}
<div class="alert alert-danger" role="alert">
{{$msg}}
</div>
{{end}}
{{range $msg := .flash.Warnings}}
<div class="alert alert-warning" role="alert">
{{$msg}}
</div>
{{end}}
{{range $msg := .flash.Alerts}}
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{$msg}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<div id="alerts-container">
{{range $msg := .flash.Errors}}
<div class="alert alert-danger" role="alert">
{{$msg}}
</div>
{{end}}
{{range $msg := .flash.Warnings}}
<div class="alert alert-warning" role="alert">
{{$msg}}
</div>
{{end}}
{{range $msg := .flash.Alerts}}
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{$msg}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{{end}}
</div>
{{end}}
{{end}}

{{define "scripts"}}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
Expand Down Expand Up @@ -359,10 +366,10 @@ <h6 class="dropdown-header">Actions</h6>
});
});

var $main = $('main');
var $alerts = $('#alerts-container');

function clearExistingFlash() {
$main.find('div.alert').remove();
$alerts.empty();
}

function flash(message, errLevel, dismissible = undefined) {
Expand All @@ -380,7 +387,7 @@ <h6 class="dropdown-header">Actions</h6>
}

let $div = $('<div class="alert alert-' + errLevel + '" role="alert">');
$div.text(message);
$div.html(message);

if (dismissible) {
$div.addClass("alert-dismissible fade show");
Expand All @@ -390,7 +397,7 @@ <h6 class="dropdown-header">Actions</h6>
</button>');
}

$main.prepend($div);
$alerts.append($div);
}
</script>
{{end}}
Expand Down
25 changes: 25 additions & 0 deletions cmd/server/assets/login/_loginscripts.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,28 @@
}
</script>
{{end}}

{{define "login/pindiv"}}
<div class="card shadow-sm" style="display:none;" id="sms-code-div">
<div class="card-header">
SMS Confirmation Code
<button type="button" class="close" aria-label="Close" id="sms-code-close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="card-body">
<form id="sms-code-form" class="floating-form" action="/" method="POST">
<div class="form-label-group">
<input type="text" id="sms-code" name="sms-code" class="form-control" placeholder="Code" autocomplete="one-time-code" required autofocus />
<label for="sms-code">Code</label>
<small class="form-text text-muted">
Please enter the numerical code that was sent via SMS.
</small>
</div>

<button type="submit" id="sms-code-submit" class="btn btn-primary btn-block">Confirm code</button>
<a id="sms-code-resend" class="card-link btn-block disabled" disabled>Resend SMS</a>
</form>
</div>
</div>
{{end}}
83 changes: 66 additions & 17 deletions cmd/server/assets/login/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
<div class="d-flex vh-100">
<div class="d-flex w-100 justify-content-center align-self-center">
<div class="col-sm-6">
<div class="card shadow-sm">

<div class="card shadow-sm" id="login-div">
<div class="card-header">COVID-19 test verification</div>
<div class="card-body">
<form id="loginForm" class="floating-form" action="/" method="POST">
<form id="login-form" class="floating-form" action="/" method="POST">
<div class="form-label-group">
<input type="email" id="email" name="email" class="form-control" placeholder="Email address" required
autofocus />
Expand All @@ -32,12 +33,13 @@
</div>

<button type="submit" id="submit" class="btn btn-primary btn-block">Login</button>
<a class="card-link btn-block" href="login/reset-password">Forgot password</a>
</form>
<div class="card-body">
<a class="card-link" href="login/reset-password">Forgot password</a>
</div>
</div>
</div>

{{template "login/pindiv" .}}

</div>
</div>
</div>
Expand All @@ -60,11 +62,21 @@
});

$(function() {
let $form = $('#loginForm');
let $loginDiv = $('#login-div');
let $form = $('#login-form');
let $submit = $('#submit');
let $email = $('#email');
let $password = $('#password');

let $pinDiv = $('#sms-code-div');
let $pinClose = $('#sms-code-close');
let $pinForm = $('#sms-code-form');
let $pin = $('#sms-code');
let $submitPin = $('#sms-code-submit');
let $resendPin = $('#sms-code-resend');

let verId = "";

$form.on('submit', function(event) {
event.preventDefault();

Expand All @@ -80,24 +92,18 @@
resolver = error.resolver;
let selectedIndex = 0 // TODO: show list of factors
if (resolver.hints[selectedIndex].factorId === firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) {

let phoneInfoOptions = {
multiFactorHint: resolver.hints[selectedIndex],
session: resolver.session
};
let phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
.then(function(verificationId) {
let verificationCode = window.prompt('Please enter the verification ' +
'code that was sent to your mobile device.');

// Ask user for the SMS verification code.
let cred = firebase.auth.PhoneAuthProvider.credential(
verificationId, verificationCode);
let multiFactorAssertion =
firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
// Complete sign-in.
return resolver.resolveSignIn(multiFactorAssertion)
verId = verificationId;
setTimeout(function() { $resendPin.removeClass('disabled'); }, 15000);
$submitPin.prop('disabled', false);
$loginDiv.hide();
$pinDiv.show();
}).catch(function(error) {
clearExistingFlash();
flash(error.message, "danger");
Expand All @@ -114,6 +120,49 @@
}
});
});

$pinForm.on('submit', function(event) {
event.preventDefault();

// Disable the submit button so we only attempt once.
$submitPin.prop('disabled', true);

// Ask user for the SMS verification code.
let cred = firebase.auth.PhoneAuthProvider.credential(verId, $pin.val());
let multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
// Complete sign-in.
resolver.resolveSignIn(multiFactorAssertion)
.catch(function(err) {
clearExistingFlash();
flash(err.message, "danger");
$submit.prop('disabled', false);
});
});

$pinClose.on('click', function(event) {
$submit.prop('disabled', false);
$loginDiv.show();
$pinDiv.hide();
});

$resendPin.on('click', function(event) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to prevent default here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a link with no href, not a submit button?

$resendPin.addClass('disabled');
setTimeout(function() { $resendPin.removeClass('disabled'); }, 15000);

let phoneInfoOptions = {
multiFactorHint: resolver.hints[0],
session: resolver.session
};
let phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
.then(function(verificationId) {
verId = verificationId;
}).catch(function(error) {
clearExistingFlash();
flash(error.message, "danger");
$submit.prop('disabled', false);
});
});
});
</script>
</body>
Expand Down
Loading