diff --git a/BudgetApp/BudgetApp.csproj b/BudgetApp/BudgetApp.csproj index 8133746..f2e15ab 100644 --- a/BudgetApp/BudgetApp.csproj +++ b/BudgetApp/BudgetApp.csproj @@ -5,6 +5,7 @@ enable enable true + 0.1.0 diff --git a/BudgetApp/Components/Layout/NavMenu.razor b/BudgetApp/Components/Layout/NavMenu.razor index 12ae9b9..7a17eb9 100644 --- a/BudgetApp/Components/Layout/NavMenu.razor +++ b/BudgetApp/Components/Layout/NavMenu.razor @@ -7,7 +7,7 @@ diff --git a/BudgetApp/Components/Pages/About.razor b/BudgetApp/Components/Pages/About.razor index 9d5dacf..2f4bc8e 100644 --- a/BudgetApp/Components/Pages/About.razor +++ b/BudgetApp/Components/Pages/About.razor @@ -2,9 +2,9 @@ @layout AuthLayout @inject IConfiguration Configuration -Budgeteer — About +Budgeteer Beta — About -

💰 Budgeteer

+

💰 Budgeteer beta

A personal finance dashboard built with Blazor Server. diff --git a/BudgetApp/Components/Pages/Help.razor b/BudgetApp/Components/Pages/Help.razor index bfb7d6c..1be8e61 100644 --- a/BudgetApp/Components/Pages/Help.razor +++ b/BudgetApp/Components/Pages/Help.razor @@ -133,6 +133,7 @@

The Settings page provides account management options:

diff --git a/BudgetApp/Components/Pages/Login.razor b/BudgetApp/Components/Pages/Login.razor index d30c84f..6b94e9a 100644 --- a/BudgetApp/Components/Pages/Login.razor +++ b/BudgetApp/Components/Pages/Login.razor @@ -6,9 +6,13 @@ @inject NavigationManager Navigation @inject IAuthenticationSchemeProvider SchemeProvider -Budgeteer — Sign In +Budgeteer Beta — Sign In -

Sign In

+
+ 💰 +

Budgeteer beta

+

Sign in to your account

+
diff --git a/BudgetApp/Components/Pages/Register.razor b/BudgetApp/Components/Pages/Register.razor index a6dc449..77f19a5 100644 --- a/BudgetApp/Components/Pages/Register.razor +++ b/BudgetApp/Components/Pages/Register.razor @@ -5,7 +5,7 @@ @inject SignInManager SignInManager @inject NavigationManager Navigation -Budgeteer — Register +Budgeteer Beta — Register

Create Account

diff --git a/BudgetApp/Components/Pages/Settings.razor b/BudgetApp/Components/Pages/Settings.razor index 9f60069..1e7eee9 100644 --- a/BudgetApp/Components/Pages/Settings.razor +++ b/BudgetApp/Components/Pages/Settings.razor @@ -7,11 +7,15 @@ @inject AuthenticationStateProvider AuthStateProvider @inject ApplicationDbContext DbContext @inject NavigationManager Navigation +@inject AppState AppState @rendermode InteractiveServer Settings -

Settings

+

+ Settings + beta +

@* ── Change Password ── *@
@@ -52,6 +56,49 @@
+@* ── Reset Data ── *@ +
+
+
Reset Data
+
+
+

+ This will permanently delete all your accounts, transactions and categories, giving you a clean slate. Your user account and password will be kept. +

+ + @if (resetSuccess) + { +
All data has been reset successfully.
+ } + + @if (!string.IsNullOrEmpty(resetError)) + { +
@resetError
+ } + + @if (!confirmingReset) + { + + } + else + { +
+ Are you sure? This cannot be undone. Type I UNDERSTAND and enter your password to confirm. +
+
+ + +
+ + +
+
+ } +
+
+ @* ── Delete Account ── *@
@@ -88,6 +135,9 @@
@code { + private static readonly string appVersion = + typeof(Program).Assembly.GetName().Version?.ToString(3) ?? "0.0.0"; + private ChangePasswordForm passwordForm = new(); private bool passwordSuccess; private string? passwordError; @@ -96,6 +146,12 @@ private string deletePassword = string.Empty; private string? deleteError; + private bool confirmingReset; + private string resetConfirmation = string.Empty; + private string resetPassword = string.Empty; + private string? resetError; + private bool resetSuccess; + private async Task ChangePassword() { passwordSuccess = false; @@ -166,6 +222,59 @@ deleteError = null; } + private async Task ResetData() + { + resetError = null; + resetSuccess = false; + + var authState = await AuthStateProvider.GetAuthenticationStateAsync(); + var userIdClaim = authState.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value; + if (userIdClaim is null) return; + + var user = await UserManager.FindByIdAsync(userIdClaim); + if (user is null) return; + + if (!string.Equals(resetConfirmation?.Trim(), "I UNDERSTAND", StringComparison.Ordinal)) + { + resetError = "Please type 'I UNDERSTAND' exactly to confirm."; + return; + } + + var passwordValid = await UserManager.CheckPasswordAsync(user, resetPassword); + if (!passwordValid) + { + resetError = "Incorrect password."; + return; + } + + await DbContext.Transactions + .Where(t => t.Account.UserId == userIdClaim) + .ExecuteDeleteAsync(); + + await DbContext.Accounts + .Where(a => a.UserId == userIdClaim) + .ExecuteDeleteAsync(); + + await DbContext.Categories + .Where(c => c.UserId == userIdClaim) + .ExecuteDeleteAsync(); + + confirmingReset = false; + resetConfirmation = string.Empty; + resetPassword = string.Empty; + resetSuccess = true; + + AppState.NotifyAccountsChanged(); + } + + private void CancelReset() + { + confirmingReset = false; + resetConfirmation = string.Empty; + resetPassword = string.Empty; + resetError = null; + } + private sealed class ChangePasswordForm { [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Current password is required")] diff --git a/BudgetApp/budgetapp.db-shm b/BudgetApp/budgetapp.db-shm index 4b1e3fa..7dd160e 100644 Binary files a/BudgetApp/budgetapp.db-shm and b/BudgetApp/budgetapp.db-shm differ diff --git a/BudgetApp/budgetapp.db-wal b/BudgetApp/budgetapp.db-wal index b92960a..2943f34 100644 Binary files a/BudgetApp/budgetapp.db-wal and b/BudgetApp/budgetapp.db-wal differ