mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-04-13 11:10:02 -04:00
Update reset vault and refactor into its own page (#1007)
This commit is contained in:
committed by
Leendert de Borst
parent
99e17d0792
commit
f74a09e4bb
@@ -11,12 +11,13 @@
|
||||
@using Microsoft.Extensions.Localization
|
||||
|
||||
<FullScreenLoadingIndicator @ref="_loadingIndicator" />
|
||||
<ServerValidationErrors @ref="_serverValidationErrors" />
|
||||
|
||||
@if (IsLoading) {
|
||||
<ServerValidationErrors @ref="_serverValidationErrors" />
|
||||
<BoldLoadingIndicator />
|
||||
}
|
||||
else if (IsWebAuthnLoading) {
|
||||
<ServerValidationErrors @ref="_serverValidationErrors" />
|
||||
<BoldLoadingIndicator />
|
||||
<p class="mt-6 text-center font-normal text-gray-500 dark:text-gray-400">
|
||||
@Localizer["LoggingInWithWebAuthn"]
|
||||
@@ -35,6 +36,9 @@ else
|
||||
<p class="text-base font-normal text-gray-500 dark:text-gray-400 mb-4">
|
||||
@Localizer["QuickUnlockDescription"]
|
||||
</p>
|
||||
|
||||
<ServerValidationErrors @ref="_serverValidationErrors" />
|
||||
|
||||
<div class="flex space-x-4">
|
||||
<button type="button" @onclick="UnlockWithWebAuthn" class="flex-grow inline-flex items-center justify-center px-5 py-3 text-base font-medium text-center text-white rounded-lg bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">
|
||||
<svg class="w-5 h-5 mr-2 -ml-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z"></path><path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd"></path></svg>
|
||||
@@ -52,7 +56,9 @@ else
|
||||
@Localizer["EnterMasterPasswordDescription"]
|
||||
</p>
|
||||
|
||||
<EditForm Model="_unlockModel" OnValidSubmit="UnlockSubmit" class="mt-8 space-y-6">
|
||||
<ServerValidationErrors @ref="_serverValidationErrors" />
|
||||
|
||||
<EditForm Model="_unlockModel" OnValidSubmit="UnlockSubmit" class="mt-4 space-y-6">
|
||||
<DataAnnotationsValidator/>
|
||||
<div>
|
||||
<label asp-for="Input.Password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["YourPasswordLabel"]</label>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
@inject NavigationManager NavigationManager
|
||||
@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-2 text-lg font-medium text-gray-900 dark:text-white">@Localizer["Title"]</h3>
|
||||
<div class="mb-3 text-sm text-gray-600 dark:text-gray-400">
|
||||
@Localizer["Description"]
|
||||
</div>
|
||||
<Button Color="danger" OnClick="ResetVault">@Localizer["ResetVaultButton"]</Button>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private IStringLocalizer Localizer => LocalizerFactory.Create("Components.Main.Settings.ImportExport.ResetVaultSection", "AliasVault.Client");
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the reset vault page.
|
||||
/// </summary>
|
||||
private void ResetVault()
|
||||
{
|
||||
NavigationManager.NavigateTo("settings/import-export/reset-vault");
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,6 @@
|
||||
@using AliasVault.RazorComponents.Services
|
||||
@using AliasVault.Client.Main.Pages.Settings.ImportExport.Components
|
||||
@using AliasVault.ImportExport
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using AliasVault.Client.Resources
|
||||
|
||||
<LayoutPageTitle>@Localizer["PageTitle"]</LayoutPageTitle>
|
||||
|
||||
@@ -54,90 +52,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 mx-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
<h3 class="mb-4 text-xl font-semibold dark:text-white">@Localizer["ResetVaultSectionTitle"]</h3>
|
||||
<div class="mb-4">
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">
|
||||
@Localizer["ResetVaultSectionDescription"]
|
||||
</p>
|
||||
@if (!_showResetPasswordConfirm)
|
||||
{
|
||||
<div class="mb-6">
|
||||
<MessageWarning Message="@Localizer["ResetVaultWarning"]" />
|
||||
|
||||
<div class="mt-4 mb-6 text-gray-600 dark:text-gray-400">
|
||||
<p class="mb-2">@Localizer["ResetVaultPleaseNote"]</p>
|
||||
<ul class="list-disc list-inside space-y-2">
|
||||
<li>@Localizer["ResetVaultCredentialsDeletedNote"]</li>
|
||||
<li>@Localizer["ResetVaultEmailAliasesKeptNote"]</li>
|
||||
<li>@Localizer["ResetVaultSettingsKeptNote"]</li>
|
||||
<li>@Localizer["ResetVaultIrreversibleNote"]</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<EditForm Model="@_resetUsernameModel" OnSubmit="@ConfirmResetUsername">
|
||||
<div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["ResetVaultConfirmUsernameLabel"]</label>
|
||||
<InputText id="reset-username" @bind-Value="_resetUsernameModel.Username" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" />
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<Button Type="submit" Color="danger">@Localizer["ResetVaultContinueButton"]</Button>
|
||||
<Button Type="button" Color="secondary" OnClick="CancelResetVault">@SharedLocalizer["Cancel"]</Button>
|
||||
</div>
|
||||
</EditForm>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-6">
|
||||
<MessageWarning Message="@Localizer["ResetVaultFinalWarning"]" />
|
||||
|
||||
<div class="mt-4 mb-6 text-gray-600 dark:text-gray-400">
|
||||
<p class="mb-2">@Localizer["ResetVaultPleaseNote"]</p>
|
||||
<ul class="list-disc list-inside space-y-2">
|
||||
<li>@Localizer["ResetVaultDeletionIrreversibleNote"]</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<EditForm Model="@_resetPasswordModel" OnValidSubmit="@ResetVaultConfirmed">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary />
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["ResetVaultEnterPasswordLabel"]</label>
|
||||
<InputText id="reset-password" type="password" @bind-Value="_resetPasswordModel.Password" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" />
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<Button Type="submit" Color="danger">@Localizer["ResetVaultConfirmButton"]</Button>
|
||||
<Button Type="button" Color="secondary" OnClick="CancelResetVault">@SharedLocalizer["Cancel"]</Button>
|
||||
</div>
|
||||
</EditForm>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<ResetVaultSection />
|
||||
|
||||
@code {
|
||||
private IStringLocalizer Localizer => LocalizerFactory.Create("Pages.Main.Settings.ImportExport.ImportExport", "AliasVault.Client");
|
||||
private ExportType _currentExportType;
|
||||
|
||||
/// <summary>
|
||||
/// The model for the reset vault username confirmation step.
|
||||
/// </summary>
|
||||
private readonly ResetVaultUsernameModel _resetUsernameModel = new();
|
||||
|
||||
/// <summary>
|
||||
/// The model for the reset vault password confirmation step.
|
||||
/// </summary>
|
||||
private readonly ResetVaultPasswordModel _resetPasswordModel = new();
|
||||
|
||||
/// <summary>
|
||||
/// Whether to show the password confirmation step for reset vault.
|
||||
/// </summary>
|
||||
private bool _showResetPasswordConfirm;
|
||||
|
||||
private enum ExportType
|
||||
{
|
||||
Csv,
|
||||
@@ -230,105 +150,4 @@
|
||||
var username = await GetUsernameAsync();
|
||||
return $"aliasvault-export-{username}-{dateStr}.{extension}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms the username for vault reset.
|
||||
/// </summary>
|
||||
private async Task ConfirmResetUsername()
|
||||
{
|
||||
GlobalNotificationService.ClearMessages();
|
||||
|
||||
if (string.IsNullOrEmpty(_resetUsernameModel.Username))
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultUsernameRequired"], true);
|
||||
return;
|
||||
}
|
||||
|
||||
var username = await GetUsernameAsync();
|
||||
var usernameMatches = string.Equals(_resetUsernameModel.Username.Trim(), username.Trim(), StringComparison.OrdinalIgnoreCase);
|
||||
if (!usernameMatches)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultUsernameDoesNotMatch"], true);
|
||||
return;
|
||||
}
|
||||
|
||||
_showResetPasswordConfirm = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms the password and performs the vault reset.
|
||||
/// </summary>
|
||||
private async Task ResetVaultConfirmed()
|
||||
{
|
||||
GlobalLoadingSpinner.Show(Localizer["ResetVaultProgressMessage"]);
|
||||
GlobalNotificationService.ClearMessages();
|
||||
|
||||
try
|
||||
{
|
||||
// Verify the password locally using the AuthService
|
||||
var isValidPassword = await AuthService.ValidateEncryptionKeyAsync(_resetPasswordModel.Password);
|
||||
if (!isValidPassword)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultPasswordIncorrect"], true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear local vault data
|
||||
await CredentialService.DeleteAllAsync();
|
||||
await DbService.SaveAsync();
|
||||
|
||||
GlobalNotificationService.AddSuccessMessage(Localizer["ResetVaultSuccessMessage"], true);
|
||||
|
||||
// Reset the form state
|
||||
_showResetPasswordConfirm = false;
|
||||
_resetUsernameModel.Username = string.Empty;
|
||||
_resetPasswordModel.Password = string.Empty;
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error resetting vault");
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultErrorMessage"], true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GlobalLoadingSpinner.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the vault reset process.
|
||||
/// </summary>
|
||||
private void CancelResetVault()
|
||||
{
|
||||
_showResetPasswordConfirm = false;
|
||||
_resetUsernameModel.Username = string.Empty;
|
||||
_resetPasswordModel.Password = string.Empty;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Model for the reset vault username confirmation step.
|
||||
/// </summary>
|
||||
public class ResetVaultUsernameModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = nameof(ValidationMessages.UsernameRequired))]
|
||||
public string Username { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Model for the reset vault password confirmation step.
|
||||
/// </summary>
|
||||
public class ResetVaultPasswordModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the password.
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = nameof(ValidationMessages.PasswordRequired))]
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
@page "/settings/import-export/reset-vault"
|
||||
@inherits MainBase
|
||||
@inject HttpClient Http
|
||||
@inject CredentialService CredentialService
|
||||
@inject ILogger<ResetVault> Logger
|
||||
@using System.Text.Json
|
||||
@using AliasVault.Client.Utilities
|
||||
@using AliasVault.Shared.Models.WebApi.Auth
|
||||
@using AliasVault.Cryptography.Client
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using AliasVault.Client.Resources
|
||||
@using Microsoft.Extensions.Localization
|
||||
|
||||
<LayoutPageTitle>@Localizer["PageTitle"]</LayoutPageTitle>
|
||||
|
||||
<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>@Localizer["PageTitle"]</H1>
|
||||
</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">
|
||||
@if (!_showPasswordConfirm)
|
||||
{
|
||||
<div class="mb-6 text-gray-600 dark:text-gray-400">
|
||||
<p class="mb-2">@Localizer["ResetVaultPleaseNote"]</p>
|
||||
<ul class="list-disc list-inside space-y-2">
|
||||
<li>@Localizer["ResetVaultCredentialsDeletedNote"]</li>
|
||||
<li>@Localizer["ResetVaultEmailAliasesKeptNote"]</li>
|
||||
<li>@Localizer["ResetVaultSettingsKeptNote"]</li>
|
||||
<li>@Localizer["ResetVaultIrreversibleNote"]</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<EditForm Model="@_usernameModel" OnSubmit="@ConfirmUsername">
|
||||
<div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["ResetVaultConfirmUsernameLabel"]</label>
|
||||
<InputText id="username" @bind-Value="_usernameModel.Username" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" />
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<Button Type="submit" Color="danger">@Localizer["ResetVaultContinueButton"]</Button>
|
||||
<Button Type="button" Color="secondary" OnClick="Cancel">@SharedLocalizer["Cancel"]</Button>
|
||||
</div>
|
||||
</EditForm>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MessageWarning Message="@Localizer["ResetVaultFinalWarning"]" />
|
||||
|
||||
<div class="mt-4 mb-6 text-gray-600 dark:text-gray-400">
|
||||
<p class="mb-2">@Localizer["ResetVaultPleaseNote"]</p>
|
||||
<ul class="list-disc list-inside space-y-2">
|
||||
<li>@Localizer["ResetVaultDeletionIrreversibleNote"]</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<EditForm Model="@_passwordModel" OnValidSubmit="@ResetVaultConfirmed">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary />
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">@Localizer["ResetVaultEnterPasswordLabel"]</label>
|
||||
<InputText id="password" type="password" @bind-Value="_passwordModel.Password" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" />
|
||||
</div>
|
||||
|
||||
<div class="flex space-x-3">
|
||||
<Button Type="submit" Color="danger">@Localizer["ResetVaultConfirmButton"]</Button>
|
||||
<Button Type="button" Color="secondary" OnClick="Cancel">@SharedLocalizer["Cancel"]</Button>
|
||||
</div>
|
||||
</EditForm>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
/// <summary>
|
||||
/// The model for the username confirmation step.
|
||||
/// </summary>
|
||||
private readonly ResetVaultUsernameModel _usernameModel = new();
|
||||
|
||||
/// <summary>
|
||||
/// The model for the password confirmation step.
|
||||
/// </summary>
|
||||
private readonly ResetVaultPasswordModel _passwordModel = new();
|
||||
|
||||
private IStringLocalizer Localizer => LocalizerFactory.Create("Components.Main.Pages.Settings.ImportExport.ResetVault", "AliasVault.Client");
|
||||
private IStringLocalizer ApiErrorLocalizer => LocalizerFactory.Create("ApiErrors", "AliasVault.Client");
|
||||
|
||||
/// <summary>
|
||||
/// Whether to show the password confirmation step.
|
||||
/// </summary>
|
||||
private bool _showPasswordConfirm;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["BreadcrumbImportExport"], Url = "/settings/import-export" });
|
||||
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["BreadcrumbResetVault"] });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms the username for vault reset.
|
||||
/// </summary>
|
||||
private async Task ConfirmUsername()
|
||||
{
|
||||
GlobalNotificationService.ClearMessages();
|
||||
|
||||
if (string.IsNullOrEmpty(_usernameModel.Username))
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultUsernameRequired"], true);
|
||||
return;
|
||||
}
|
||||
|
||||
var username = await GetUsernameAsync();
|
||||
var usernameMatches = string.Equals(_usernameModel.Username.Trim(), username.Trim(), StringComparison.OrdinalIgnoreCase);
|
||||
if (!usernameMatches)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultUsernameDoesNotMatch"], true);
|
||||
return;
|
||||
}
|
||||
|
||||
_showPasswordConfirm = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms the password and performs the vault reset.
|
||||
/// </summary>
|
||||
private async Task ResetVaultConfirmed()
|
||||
{
|
||||
GlobalLoadingSpinner.Show(Localizer["ResetVaultProgressMessage"]);
|
||||
GlobalNotificationService.ClearMessages();
|
||||
|
||||
try
|
||||
{
|
||||
// Get current username
|
||||
var username = await GetUsernameAsync();
|
||||
|
||||
// Send request to server to get user salt and encryption parameters
|
||||
var result = await Http.PostAsJsonAsync("v1/Auth/login", new LoginInitiateRequest(username));
|
||||
var responseContent = await result.Content.ReadAsStringAsync();
|
||||
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
var errors = ApiResponseUtility.ParseErrorResponse(responseContent, ApiErrorLocalizer);
|
||||
foreach (var error in errors)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(error, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var loginResponse = JsonSerializer.Deserialize<LoginInitiateResponse>(responseContent);
|
||||
if (loginResponse == null)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultErrorMessage"], true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Derive password hash using server parameters
|
||||
byte[] passwordHash = await Encryption.DeriveKeyFromPasswordAsync(_passwordModel.Password, loginResponse.Salt, loginResponse.EncryptionType, loginResponse.EncryptionSettings);
|
||||
|
||||
// Verify the password locally using the derived password hash
|
||||
var isValidPassword = await AuthService.ValidateEncryptionKeyAsync(passwordHash);
|
||||
if (!isValidPassword)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultPasswordIncorrect"], true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear local vault data by soft-deleting all credentials
|
||||
var credentials = await CredentialService.LoadAllAsync();
|
||||
foreach (var credential in credentials)
|
||||
{
|
||||
await CredentialService.SoftDeleteEntryAsync(credential.Id);
|
||||
}
|
||||
|
||||
// Save the database
|
||||
await DbService.SaveDatabaseAsync();
|
||||
|
||||
GlobalNotificationService.AddSuccessMessage(Localizer["ResetVaultSuccessMessage"]);
|
||||
|
||||
// Redirect to credentials overview page to show the empty vault
|
||||
NavigationManager.NavigateTo("/credentials");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error resetting vault");
|
||||
GlobalNotificationService.AddErrorMessage(Localizer["ResetVaultErrorMessage"], true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GlobalLoadingSpinner.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the vault reset process.
|
||||
/// </summary>
|
||||
private void Cancel()
|
||||
{
|
||||
NavigationManager.NavigateTo("/settings/import-export");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Model for the username confirmation step.
|
||||
/// </summary>
|
||||
public class ResetVaultUsernameModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = nameof(ValidationMessages.UsernameRequired))]
|
||||
public string Username { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Model for the password confirmation step.
|
||||
/// </summary>
|
||||
public class ResetVaultPasswordModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the password.
|
||||
/// </summary>
|
||||
[Required(ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = nameof(ValidationMessages.PasswordRequired))]
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?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>
|
||||
<data name="PageTitle" xml:space="preserve">
|
||||
<value>Reset Vault</value>
|
||||
<comment>Page title</comment>
|
||||
</data>
|
||||
<data name="BreadcrumbImportExport" xml:space="preserve">
|
||||
<value>Import / Export</value>
|
||||
<comment>Breadcrumb for import export</comment>
|
||||
</data>
|
||||
<data name="BreadcrumbResetVault" xml:space="preserve">
|
||||
<value>Reset Vault</value>
|
||||
<comment>Breadcrumb for reset vault</comment>
|
||||
</data>
|
||||
<data name="ResetVaultPleaseNote" xml:space="preserve">
|
||||
<value>Please note:</value>
|
||||
<comment>Reset vault please note prefix</comment>
|
||||
</data>
|
||||
<data name="ResetVaultCredentialsDeletedNote" xml:space="preserve">
|
||||
<value>All encrypted credentials in your vault will be permanently deleted</value>
|
||||
<comment>Reset vault note about credentials being deleted</comment>
|
||||
</data>
|
||||
<data name="ResetVaultEmailAliasesKeptNote" xml:space="preserve">
|
||||
<value>Your email aliases will be preserved and can be re-used after resetting your vault</value>
|
||||
<comment>Reset vault note about email aliases being kept</comment>
|
||||
</data>
|
||||
<data name="ResetVaultSettingsKeptNote" xml:space="preserve">
|
||||
<value>Your account settings and preferences will be preserved</value>
|
||||
<comment>Reset vault note about settings being kept</comment>
|
||||
</data>
|
||||
<data name="ResetVaultIrreversibleNote" xml:space="preserve">
|
||||
<value>This action cannot be undone</value>
|
||||
<comment>Reset vault note about action being irreversible</comment>
|
||||
</data>
|
||||
<data name="ResetVaultConfirmUsernameLabel" xml:space="preserve">
|
||||
<value>To continue, please type your username to confirm</value>
|
||||
<comment>Reset vault username confirmation label</comment>
|
||||
</data>
|
||||
<data name="ResetVaultContinueButton" xml:space="preserve">
|
||||
<value>Continue with vault reset</value>
|
||||
<comment>Reset vault continue button</comment>
|
||||
</data>
|
||||
<data name="ResetVaultFinalWarning" xml:space="preserve">
|
||||
<value>Final warning: You are about to permanently delete all your credentials!</value>
|
||||
<comment>Reset vault final warning message</comment>
|
||||
</data>
|
||||
<data name="ResetVaultDeletionIrreversibleNote" xml:space="preserve">
|
||||
<value>This deletion is irreversible and cannot be undone</value>
|
||||
<comment>Reset vault final step irreversible note</comment>
|
||||
</data>
|
||||
<data name="ResetVaultEnterPasswordLabel" xml:space="preserve">
|
||||
<value>Enter your password to confirm</value>
|
||||
<comment>Reset vault password confirmation label</comment>
|
||||
</data>
|
||||
<data name="ResetVaultConfirmButton" xml:space="preserve">
|
||||
<value>Reset my vault</value>
|
||||
<comment>Reset vault final confirmation button</comment>
|
||||
</data>
|
||||
<data name="ResetVaultUsernameRequired" xml:space="preserve">
|
||||
<value>Username is required.</value>
|
||||
<comment>Reset vault username required error</comment>
|
||||
</data>
|
||||
<data name="ResetVaultUsernameDoesNotMatch" xml:space="preserve">
|
||||
<value>The username you entered does not match your account username.</value>
|
||||
<comment>Reset vault username mismatch error</comment>
|
||||
</data>
|
||||
<data name="ResetVaultPasswordIncorrect" xml:space="preserve">
|
||||
<value>The password you entered is incorrect.</value>
|
||||
<comment>Reset vault password incorrect error</comment>
|
||||
</data>
|
||||
<data name="ResetVaultProgressMessage" xml:space="preserve">
|
||||
<value>Resetting vault...</value>
|
||||
<comment>Reset vault progress message</comment>
|
||||
</data>
|
||||
<data name="ResetVaultSuccessMessage" xml:space="preserve">
|
||||
<value>Your vault has been successfully reset. All credentials have been deleted and you can now start fresh.</value>
|
||||
<comment>Reset vault success message</comment>
|
||||
</data>
|
||||
<data name="ResetVaultErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while resetting your vault. Please try again.</value>
|
||||
<comment>Reset vault error message</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,73 @@
|
||||
<?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>
|
||||
<data name="Title" xml:space="preserve">
|
||||
<value>Reset Vault</value>
|
||||
<comment>Reset vault section title</comment>
|
||||
</data>
|
||||
<data name="Description" xml:space="preserve">
|
||||
<value>This option allows you to completely empty your vault while keeping your account and email aliases. Use this if you want to start fresh after importing data from another password manager or if you want to clear all existing credentials to start over.</value>
|
||||
<comment>Reset vault section description</comment>
|
||||
</data>
|
||||
<data name="ResetVaultButton" xml:space="preserve">
|
||||
<value>Reset vault</value>
|
||||
<comment>Reset vault button</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -112,76 +112,4 @@ Are you sure you want to continue with the export?</value>
|
||||
<value>This option allows you to completely empty your vault while keeping your account and email aliases. Use this if you want to start fresh after importing data from another password manager or if you want to clear all existing credentials to start over.</value>
|
||||
<comment>Reset vault section description</comment>
|
||||
</data>
|
||||
<data name="ResetVaultWarning" xml:space="preserve">
|
||||
<value>Warning: This action is irreversible!</value>
|
||||
<comment>Reset vault warning message</comment>
|
||||
</data>
|
||||
<data name="ResetVaultPleaseNote" xml:space="preserve">
|
||||
<value>Please note:</value>
|
||||
<comment>Reset vault please note prefix</comment>
|
||||
</data>
|
||||
<data name="ResetVaultCredentialsDeletedNote" xml:space="preserve">
|
||||
<value>All encrypted credentials in your vault will be permanently deleted</value>
|
||||
<comment>Reset vault note about credentials being deleted</comment>
|
||||
</data>
|
||||
<data name="ResetVaultEmailAliasesKeptNote" xml:space="preserve">
|
||||
<value>Your email aliases will be preserved and remain claimed by your account</value>
|
||||
<comment>Reset vault note about email aliases being kept</comment>
|
||||
</data>
|
||||
<data name="ResetVaultSettingsKeptNote" xml:space="preserve">
|
||||
<value>Your account settings and preferences will be preserved</value>
|
||||
<comment>Reset vault note about settings being kept</comment>
|
||||
</data>
|
||||
<data name="ResetVaultIrreversibleNote" xml:space="preserve">
|
||||
<value>This action cannot be undone</value>
|
||||
<comment>Reset vault note about action being irreversible</comment>
|
||||
</data>
|
||||
<data name="ResetVaultConfirmUsernameLabel" xml:space="preserve">
|
||||
<value>To continue, please type your username to confirm</value>
|
||||
<comment>Reset vault username confirmation label</comment>
|
||||
</data>
|
||||
<data name="ResetVaultContinueButton" xml:space="preserve">
|
||||
<value>Continue with vault reset</value>
|
||||
<comment>Reset vault continue button</comment>
|
||||
</data>
|
||||
<data name="ResetVaultFinalWarning" xml:space="preserve">
|
||||
<value>Final warning: You are about to permanently delete all your credentials!</value>
|
||||
<comment>Reset vault final warning message</comment>
|
||||
</data>
|
||||
<data name="ResetVaultDeletionIrreversibleNote" xml:space="preserve">
|
||||
<value>This deletion is irreversible and cannot be undone</value>
|
||||
<comment>Reset vault final step irreversible note</comment>
|
||||
</data>
|
||||
<data name="ResetVaultEnterPasswordLabel" xml:space="preserve">
|
||||
<value>Enter your password to confirm</value>
|
||||
<comment>Reset vault password confirmation label</comment>
|
||||
</data>
|
||||
<data name="ResetVaultConfirmButton" xml:space="preserve">
|
||||
<value>Reset my vault</value>
|
||||
<comment>Reset vault final confirmation button</comment>
|
||||
</data>
|
||||
<data name="ResetVaultUsernameRequired" xml:space="preserve">
|
||||
<value>Username is required.</value>
|
||||
<comment>Reset vault username required error</comment>
|
||||
</data>
|
||||
<data name="ResetVaultUsernameDoesNotMatch" xml:space="preserve">
|
||||
<value>The username you entered does not match your account username.</value>
|
||||
<comment>Reset vault username mismatch error</comment>
|
||||
</data>
|
||||
<data name="ResetVaultPasswordIncorrect" xml:space="preserve">
|
||||
<value>The password you entered is incorrect.</value>
|
||||
<comment>Reset vault password incorrect error</comment>
|
||||
</data>
|
||||
<data name="ResetVaultProgressMessage" xml:space="preserve">
|
||||
<value>Resetting vault...</value>
|
||||
<comment>Reset vault progress message</comment>
|
||||
</data>
|
||||
<data name="ResetVaultSuccessMessage" xml:space="preserve">
|
||||
<value>Your vault has been successfully reset. All credentials have been deleted and you can now start fresh.</value>
|
||||
<comment>Reset vault success message</comment>
|
||||
</data>
|
||||
<data name="ResetVaultErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while resetting your vault. Please try again.</value>
|
||||
<comment>Reset vault error message</comment>
|
||||
</data>
|
||||
</root>
|
||||
Reference in New Issue
Block a user