mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-05-24 16:32:20 -04:00
Tweak enable/disable 2FA flow in web app including translations (#1029)
This commit is contained in:
committed by
Leendert de Borst
parent
3fce102471
commit
1e50b7b6bc
@@ -1,27 +1,29 @@
|
||||
@inject IStringLocalizerFactory LocalizerFactory
|
||||
@using Microsoft.Extensions.Localization
|
||||
|
||||
<div class="p-4 mb-4 mx-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<h3 class="mb-4 text-lg font-medium text-gray-900 dark:text-white">@Localizer["Title"]</h3>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
@Localizer["Description"]
|
||||
</div>
|
||||
<div class="bg-primary-100 border-l-4 border-primary-500 text-primary-700 p-4 mb-4 dark:bg-gray-700 dark:border-primary-500 dark:text-gray-200">
|
||||
<p class="font-semibold">
|
||||
@Localizer["WarningTitle"]
|
||||
</p>
|
||||
<p>
|
||||
@Localizer["WarningDescription"]
|
||||
</p>
|
||||
</div>
|
||||
<div class="max-w-2xl mx-auto px-4 lg:mt-8">
|
||||
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<h3 class="mb-4 text-lg font-medium text-gray-900 dark:text-white">@Localizer["Title"]</h3>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||
@Localizer["Description"]
|
||||
</div>
|
||||
<div class="bg-primary-100 border-l-4 border-primary-500 text-primary-700 p-4 mb-4 dark:bg-gray-700 dark:border-primary-500 dark:text-gray-200">
|
||||
<p class="font-semibold">
|
||||
@Localizer["WarningTitle"]
|
||||
</p>
|
||||
<p>
|
||||
@Localizer["WarningDescription"]
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1" id="recovery-codes">
|
||||
@foreach (var recoveryCode in RecoveryCodes)
|
||||
{
|
||||
<div>
|
||||
<code class="block p-2 bg-gray-100 dark:bg-gray-700 dark:text-gray-200">@recoveryCode</code>
|
||||
</div>
|
||||
}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-2" id="recovery-codes">
|
||||
@foreach (var recoveryCode in RecoveryCodes)
|
||||
{
|
||||
<div>
|
||||
<code class="block p-3 bg-gray-100 dark:bg-gray-700 dark:text-gray-200 rounded border font-mono text-center">@recoveryCode</code>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
@page "/settings/security/disable-2fa"
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inherits MainBase
|
||||
@inject HttpClient Http
|
||||
|
||||
<LayoutPageTitle>Disable two-factor authentication</LayoutPageTitle>
|
||||
<LayoutPageTitle>@Localizer["PageTitle"]</LayoutPageTitle>
|
||||
|
||||
@if (IsLoading)
|
||||
{
|
||||
@@ -13,17 +14,17 @@ else
|
||||
<div class="grid grid-cols-1 px-4 pt-6 xl:grid-cols-3 xl:gap-4 dark:bg-gray-900">
|
||||
<div class="mb-4 col-span-full xl:mb-2">
|
||||
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
|
||||
<H1>Disable two-factor authentication</H1>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">Disabling two-factor authentication means you will be able to login with only your password.</p>
|
||||
<H1>@Localizer["PageTitle"]</H1>
|
||||
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">@Localizer["PageDescription"]</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 mb-4 mx-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<AlertMessageError Message="Please note: after disabling two-factor authentication any configured authenticator app(s) will stop working. When you want to re-enable two-factor authentication you will have to configure the authenticator app(s) again." />
|
||||
<div class="mb-3 text-sm text-gray-600 dark:text-gray-400">Two factor authentication is currently enabled. Disable it in order to be able to access your vault with your password only.</div>
|
||||
<div class="p-4 mb-4 mx-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<AlertMessageError HasTopMargin="false" Message="@Localizer["WarningMessage"]" />
|
||||
<div class="mb-3 mt-4 text-sm text-gray-600 dark:text-gray-400">@Localizer["StatusMessage"]</div>
|
||||
<button @onclick="DisableTwoFactor"
|
||||
class="bg-red-500 text-white py-2 px-4 rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 transition duration-150 ease-in-out">
|
||||
Confirm Disable Two-Factor Authentication
|
||||
@Localizer["ConfirmDisableButton"]
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@@ -31,13 +32,15 @@ else
|
||||
@code {
|
||||
private bool IsLoading { get; set; } = true;
|
||||
|
||||
private IStringLocalizer Localizer => LocalizerFactory.Create("Components.Main.Pages.Settings.Security.Disable2Fa", "AliasVault.Client");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = "Security settings", Url = "/settings/security" });
|
||||
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = "Disable two-factor authentication" });
|
||||
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["BreadcrumbSecuritySettings"], Url = "/settings/security" });
|
||||
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["BreadcrumbDisable2Fa"] });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -51,7 +54,7 @@ else
|
||||
var response = await Http.GetFromJsonAsync<TwoFactorEnabledResult>("v1/TwoFactorAuth/status");
|
||||
if (response is not null && !response.TwoFactorEnabled)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage("Two-factor authentication is not enabled.");
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["TwoFactorNotEnabled"]);
|
||||
NavigationManager.NavigateTo("/settings/security");
|
||||
return;
|
||||
}
|
||||
@@ -66,13 +69,13 @@ else
|
||||
var response = await Http.PostAsync("v1/TwoFactorAuth/disable", null);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
GlobalNotificationService.AddSuccessMessage("Two-factor authentication is now successfully disabled.");
|
||||
GlobalNotificationService.AddSuccessMessage(Localizer["TwoFactorDisabledSuccess"]);
|
||||
NavigationManager.NavigateTo("/settings/security");
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle error
|
||||
GlobalNotificationService.AddErrorMessage("Failed to disable two-factor authentication.", true);
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["FailedToDisable2Fa"], true);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,28 +24,30 @@ else if (RecoveryCodes is not null)
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="p-4 mb-4 mx-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<div class="space-y-6">
|
||||
<div id="authenticator-uri" data-url="@QrCodeUrl" class="flex justify-center">
|
||||
<!-- QR code will be rendered here -->
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-600 text-center">
|
||||
@Localizer["QrCodeInstructions"]
|
||||
</p>
|
||||
<div class="text-lg font-mono text-center bg-gray-100 p-2 rounded" id="authenticator-secret">@Secret</div>
|
||||
|
||||
<EditForm Model="@VerifyModel" OnValidSubmit="@VerifySetup" class="space-y-4">
|
||||
<div>
|
||||
<InputText id="verificationCode" @bind-Value="VerifyModel.Code"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="@Localizer["VerificationCodePlaceholder"]"/>
|
||||
<div class="max-w-2xl mx-auto px-4 lg:mt-8">
|
||||
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<div class="space-y-6">
|
||||
<div id="authenticator-uri" data-url="@QrCodeUrl" class="flex justify-center">
|
||||
<!-- QR code will be rendered here -->
|
||||
</div>
|
||||
<button type="submit"
|
||||
class="w-full bg-primary-500 text-white py-2 px-4 rounded-md hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 transition duration-150 ease-in-out">
|
||||
@Localizer["VerifyAndEnableButton"]
|
||||
</button>
|
||||
</EditForm>
|
||||
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 text-center">
|
||||
@Localizer["QrCodeInstructions"]
|
||||
</p>
|
||||
<div class="text-lg font-mono text-center bg-gray-100 dark:bg-gray-700 p-3 rounded border dark:text-gray-200" id="authenticator-secret">@Secret</div>
|
||||
|
||||
<EditForm Model="@VerifyModel" OnValidSubmit="@VerifySetup" class="space-y-4">
|
||||
<div>
|
||||
<InputText id="verificationCode" @bind-Value="VerifyModel.Code"
|
||||
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400"
|
||||
placeholder="@Localizer["VerificationCodePlaceholder"]"/>
|
||||
</div>
|
||||
<button type="submit"
|
||||
class="w-full bg-primary-500 text-white py-2 px-4 rounded-md hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 transition duration-150 ease-in-out">
|
||||
@Localizer["VerifyAndEnableButton"]
|
||||
</button>
|
||||
</EditForm>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
|
||||
<!-- Page title and breadcrumbs -->
|
||||
<data name="PageTitle" xml:space="preserve">
|
||||
<value>Disable two-factor authentication</value>
|
||||
<comment>Page title for the disable 2FA page</comment>
|
||||
</data>
|
||||
<data name="BreadcrumbSecuritySettings" xml:space="preserve">
|
||||
<value>Security settings</value>
|
||||
<comment>Breadcrumb text for security settings</comment>
|
||||
</data>
|
||||
<data name="BreadcrumbDisable2Fa" xml:space="preserve">
|
||||
<value>Disable two-factor authentication</value>
|
||||
<comment>Breadcrumb text for disable 2FA</comment>
|
||||
</data>
|
||||
|
||||
<!-- Page description -->
|
||||
<data name="PageDescription" xml:space="preserve">
|
||||
<value>Disabling two-factor authentication means you will be able to login with only your password.</value>
|
||||
<comment>Description text explaining what disabling 2FA means</comment>
|
||||
</data>
|
||||
|
||||
<!-- Warning message -->
|
||||
<data name="WarningMessage" xml:space="preserve">
|
||||
<value>Please note: after disabling two-factor authentication any configured authenticator app(s) will stop working. When you want to re-enable two-factor authentication you will have to configure the authenticator app(s) again.</value>
|
||||
<comment>Warning message about the consequences of disabling 2FA</comment>
|
||||
</data>
|
||||
|
||||
<!-- Status message -->
|
||||
<data name="StatusMessage" xml:space="preserve">
|
||||
<value>Two factor authentication is currently enabled. Disable it in order to be able to access your vault with your password only.</value>
|
||||
<comment>Status message explaining current 2FA state</comment>
|
||||
</data>
|
||||
|
||||
<!-- Button text -->
|
||||
<data name="ConfirmDisableButton" xml:space="preserve">
|
||||
<value>Confirm Disable Two-Factor Authentication</value>
|
||||
<comment>Button text to confirm disabling 2FA</comment>
|
||||
</data>
|
||||
|
||||
<!-- Success and error messages -->
|
||||
<data name="TwoFactorDisabledSuccess" xml:space="preserve">
|
||||
<value>Two-factor authentication is now successfully disabled.</value>
|
||||
<comment>Success message when 2FA is disabled</comment>
|
||||
</data>
|
||||
<data name="FailedToDisable2Fa" xml:space="preserve">
|
||||
<value>Failed to disable two-factor authentication.</value>
|
||||
<comment>Error message when 2FA disable fails</comment>
|
||||
</data>
|
||||
<data name="TwoFactorNotEnabled" xml:space="preserve">
|
||||
<value>Two-factor authentication is not enabled.</value>
|
||||
<comment>Error message when 2FA is not enabled</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1122,6 +1122,10 @@ video {
|
||||
max-width: 36rem;
|
||||
}
|
||||
|
||||
.max-w-2xl {
|
||||
max-width: 42rem;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
@@ -3207,6 +3211,11 @@ video {
|
||||
--tw-ring-color: rgb(127 29 29 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.dark\:focus\:ring-blue-400:focus:is(.dark *) {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(96 165 250 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.dark\:focus\:ring-offset-gray-800:focus:is(.dark *) {
|
||||
--tw-ring-offset-color: #1f2937;
|
||||
}
|
||||
@@ -3406,6 +3415,10 @@ video {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
.lg\:mt-8 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.lg\:block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
@if (!string.IsNullOrEmpty(Message))
|
||||
{
|
||||
<div class="p-4 mt-4 text-sm text-red-800 rounded-lg bg-red-50 border-2 dark:bg-red-800 dark:text-white dark:border-red-500 dark:border" role="alert">
|
||||
<div class="p-4 @(HasTopMargin ? "mt-4" : "") text-sm text-red-800 rounded-lg bg-red-50 border-2 dark:bg-red-800 dark:text-white dark:border-red-500 dark:border" role="alert">
|
||||
@Message
|
||||
</div>
|
||||
}
|
||||
@@ -13,4 +13,10 @@
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to include top margin.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool HasTopMargin { get; set; } = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user