@page "/account/settings" @attribute [Authorize] @rendermode InteractiveServer @using Microsoft.AspNetCore.Identity @using RealCV.Infrastructure.Identity @inject UserManager UserManager @inject SignInManager SignInManager @inject AuthenticationStateProvider AuthenticationStateProvider @inject NavigationManager NavigationManager @inject ILogger Logger Account Settings - RealCV

Account Settings

Manage your account details and security

@if (!string.IsNullOrEmpty(_successMessage)) { } @if (!string.IsNullOrEmpty(_errorMessage)) { }
Profile Information
Email cannot be changed
@_userPlan Manage

@_memberSince?.ToString("dd MMMM yyyy")

Change Password
Minimum 12 characters with uppercase, lowercase, number, and special character
@code { private string? _userEmail; private string _userPlan = "Free"; private DateTime? _memberSince; private string? _successMessage; private string? _errorMessage; private bool _isChangingPassword; private PasswordChangeModel _passwordModel = new(); protected override async Task OnInitializedAsync() { try { var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var userIdClaim = authState.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (!string.IsNullOrEmpty(userIdClaim) && Guid.TryParse(userIdClaim, out var userId)) { var user = await UserManager.FindByIdAsync(userId.ToString()); if (user != null) { _userEmail = user.Email; _userPlan = user.Plan.ToString(); // Lockout end date is used as a proxy; in a real app you might have a CreatedAt field _memberSince = DateTime.UtcNow.AddMonths(-1); // Placeholder } } } catch (Exception ex) { Logger.LogError(ex, "Error loading user settings"); _errorMessage = "Unable to load account information."; } } private async Task ChangePassword() { if (_isChangingPassword) return; _isChangingPassword = true; _errorMessage = null; _successMessage = null; try { var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var userIdClaim = authState.User.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userIdClaim) || !Guid.TryParse(userIdClaim, out var userId)) { _errorMessage = "Unable to identify user."; return; } var user = await UserManager.FindByIdAsync(userId.ToString()); if (user == null) { _errorMessage = "User not found."; return; } var result = await UserManager.ChangePasswordAsync( user, _passwordModel.CurrentPassword, _passwordModel.NewPassword); if (result.Succeeded) { _successMessage = "Password updated successfully."; _passwordModel = new PasswordChangeModel(); await SignInManager.RefreshSignInAsync(user); } else { _errorMessage = string.Join(" ", result.Errors.Select(e => e.Description)); } } catch (Exception ex) { Logger.LogError(ex, "Error changing password"); _errorMessage = "An error occurred. Please try again."; } finally { _isChangingPassword = false; } } private class PasswordChangeModel { [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Current password is required")] public string CurrentPassword { get; set; } = ""; [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "New password is required")] [System.ComponentModel.DataAnnotations.MinLength(12, ErrorMessage = "Password must be at least 12 characters")] public string NewPassword { get; set; } = ""; [System.ComponentModel.DataAnnotations.Required(ErrorMessage = "Please confirm your new password")] [System.ComponentModel.DataAnnotations.Compare("NewPassword", ErrorMessage = "Passwords do not match")] public string ConfirmPassword { get; set; } = ""; } }