Allow users to manually setup two factor with secret key (#1071)

* Allow users to manually setup two factor with secret key

* Remove empty lines in markup
This commit is contained in:
Josh 2024-09-29 19:11:43 -05:00 committed by GitHub
parent 528ee8dd17
commit baaee86e67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 0 deletions

View file

@ -24,6 +24,10 @@ public static class TwoFactorStrings
public static readonly TranslatableString QrTitle = create("qr_title");
public static readonly TranslatableString QrDescription = create("qr_description");
public static readonly TranslatableString QrAlternativeDescription = create("qr_alternative");
public static readonly TranslatableString QrAlternativeCopy = create("qr_alternative_copy");
public static readonly TranslatableString QrAlternativeCopySuccess = create("qr_alternative_copy_success");
public static readonly TranslatableString QrAlternativeCopyFail = create("qr_alternative_copy_success");
private static TranslatableString create(string key) => new(TranslationAreas.TwoFactor, key);
}

View file

@ -66,4 +66,16 @@
<data name="invalid_backup" xml:space="preserve">
<value>Invalid Backup Code</value>
</data>
<data name="qr_alternative" xml:space="preserve">
<value>Can't use the QR code? You can use this secret key instead:</value>
</data>
<data name="qr_alternative_copy" xml:space="preserve">
<value>Copy secret code</value>
</data>
<data name="qr_alternative_copy_success" xml:space="preserve">
<value>Copied to clipboard</value>
</data>
<data name="qr_alternative_copy_fail" xml:space="preserve">
<value>Failed to copy to clipboard</value>
</data>
</root>

View file

@ -18,6 +18,9 @@
<h2>@Model.Translate(TwoFactorStrings.QrTitle)</h2>
<img src="@Model.QrCode" alt="2 Factor QR Code"/>
<p>@Model.Translate(TwoFactorStrings.QrDescription)</p>
<p>@Model.Translate(TwoFactorStrings.QrAlternativeDescription)</p>
<code class="ui segment">@Model.User?.TwoFactorSecret</code>
<button class="ui button primary" style="padding: 1em 1em" id="copyButton" onclick="copySecret('@Model.User?.TwoFactorSecret')">@Model.Translate(TwoFactorStrings.QrAlternativeCopy)</button>
@await Html.PartialAsync("Partials/TwoFactorPartial", new ViewDataDictionary(ViewData)
{
{
@ -31,6 +34,28 @@
},
})
</div>
<script>
let copyTimeout;
function copySecret(secret) {
function scheduleButtonReset() {
copyTimeout = setTimeout(() => {
document.getElementById("copyButton").textContent = '@Model.Translate(TwoFactorStrings.QrAlternativeCopy)';
}, 2000);
}
if (copyTimeout) {
clearTimeout(copyTimeout);
}
navigator.clipboard.writeText(secret).then(() => {
document.getElementById("copyButton").textContent = '@Model.Translate(TwoFactorStrings.QrAlternativeCopySuccess)';
scheduleButtonReset();
}, () => {
document.getElementById("copyButton").textContent = '@Model.Translate(TwoFactorStrings.QrAlternativeCopyFail)';
scheduleButtonReset();
});
}
</script>
}
else
{