Refactor. Add data layer

This commit is contained in:
rossmill76 committed 2026-03-06 11:05:01 +00:00
1 parent 3b7e4e6ec5
commit b6b794f0b4
82 files changed
+2930 -2811

No files matched your search

@@ -0,0 +1,159 @@
using Microsoft.EntityFrameworkCore;
namespace BudgetApp.Components.Pages;
public partial class Settings
{
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;
private bool _confirmingDelete;
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;
_passwordError = null;
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;
var result =
await UserManager.ChangePasswordAsync(user, _passwordForm.CurrentPassword, _passwordForm.NewPassword);
if (result.Succeeded)
{
_passwordSuccess = true;
_passwordForm = new ChangePasswordForm();
}
else
{
_passwordError = string.Join(" ", result.Errors.Select(e => e.Description));
}
}
private async Task DeleteAccount()
{
_deleteError = null;
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;
var passwordValid = await UserManager.CheckPasswordAsync(user, _deletePassword);
if (!passwordValid)
{
_deleteError = "Incorrect password.";
return;
}
// Delete all user data explicitly in correct dependency order
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();
// Delete identity user
await UserManager.DeleteAsync(user);
await SignInManager.SignOutAsync();
Navigation.NavigateTo("/login", forceLoad: true);
}
private void CancelDelete()
{
_confirmingDelete = false;
_deletePassword = string.Empty;
_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")]
public string CurrentPassword { get; set; } = string.Empty;
[System.ComponentModel.DataAnnotations.Required(ErrorMessage = "New password is required")]
[System.ComponentModel.DataAnnotations.MinLength(8, ErrorMessage = "Password must be at least 8 characters")]
public string NewPassword { get; set; } = string.Empty;
[System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Please confirm your new password")]
[System.ComponentModel.DataAnnotations.Compare(nameof(NewPassword), ErrorMessage = "Passwords do not match")]
public string ConfirmNewPassword { get; set; } = string.Empty;
}
}