From 3e7120c0416e2f68fdedeb6338d472d9c29f7472 Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Wed, 1 Jul 2026 13:35:13 +0900 Subject: [PATCH] Add remember username on login --- .../CustomAuthenticationStateProvider.cs | 34 +++++++++++++++++-- .../QuantEngine.Web/Client/Pages/Login.razor | 15 +++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/dotnet/QuantEngine.Web/Client/Infrastructure/CustomAuthenticationStateProvider.cs b/src/dotnet/QuantEngine.Web/Client/Infrastructure/CustomAuthenticationStateProvider.cs index 8e9e703..02c04c3 100644 --- a/src/dotnet/QuantEngine.Web/Client/Infrastructure/CustomAuthenticationStateProvider.cs +++ b/src/dotnet/QuantEngine.Web/Client/Infrastructure/CustomAuthenticationStateProvider.cs @@ -12,6 +12,7 @@ namespace QuantEngine.Web.Client.Infrastructure private const string TokenKey = "quant_admin_access_token"; private const string UsernameKey = "quant_admin_username"; private const string RoleKey = "quant_admin_role"; + private const string RememberUsernameKey = "quant_admin_remember_username"; public CustomAuthenticationStateProvider(LocalStorageService localStorage, HttpClient http) { @@ -57,9 +58,23 @@ namespace QuantEngine.Web.Client.Infrastructure } public async Task MarkUserAsAuthenticatedAsync(string username, string accessToken, string role) + { + await MarkUserAsAuthenticatedAsync(username, accessToken, role, rememberUsername: true); + } + + public async Task MarkUserAsAuthenticatedAsync(string username, string accessToken, string role, bool rememberUsername) { await _localStorage.SetAsync(TokenKey, accessToken); - await _localStorage.SetAsync(UsernameKey, username); + if (rememberUsername) + { + await _localStorage.SetAsync(UsernameKey, username); + await _localStorage.SetAsync(RememberUsernameKey, true); + } + else + { + await _localStorage.DeleteAsync(UsernameKey); + await _localStorage.SetAsync(RememberUsernameKey, false); + } await _localStorage.SetAsync(RoleKey, role); var identity = new ClaimsIdentity(new[] @@ -75,8 +90,12 @@ namespace QuantEngine.Web.Client.Infrastructure public async Task MarkUserAsLoggedOutAsync() { await _localStorage.DeleteAsync(TokenKey); - await _localStorage.DeleteAsync(UsernameKey); await _localStorage.DeleteAsync(RoleKey); + var rememberUsername = await _localStorage.GetAsync(RememberUsernameKey); + if (!rememberUsername) + { + await _localStorage.DeleteAsync(UsernameKey); + } NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_anonymous))); } @@ -99,5 +118,16 @@ namespace QuantEngine.Web.Client.Infrastructure await MarkUserAsLoggedOutAsync(); } + + public async Task GetRememberedUsernameAsync() + { + var rememberUsername = await _localStorage.GetAsync(RememberUsernameKey); + if (!rememberUsername) + { + return null; + } + + return await _localStorage.GetAsync(UsernameKey); + } } } diff --git a/src/dotnet/QuantEngine.Web/Client/Pages/Login.razor b/src/dotnet/QuantEngine.Web/Client/Pages/Login.razor index 02d72be..259431a 100644 --- a/src/dotnet/QuantEngine.Web/Client/Pages/Login.razor +++ b/src/dotnet/QuantEngine.Web/Client/Pages/Login.razor @@ -18,6 +18,7 @@ + @if (!string.IsNullOrEmpty(ErrorMessage)) { @@ -57,6 +58,18 @@ private string Password { get; set; } = string.Empty; private string ErrorMessage { get; set; } = string.Empty; private bool IsSubmitting { get; set; } = false; + private bool RememberUsername { get; set; } = true; + + protected override async Task OnInitializedAsync() + { + var customProvider = (CustomAuthenticationStateProvider)AuthStateProvider; + var remembered = await customProvider.GetRememberedUsernameAsync(); + if (!string.IsNullOrWhiteSpace(remembered)) + { + Username = remembered; + RememberUsername = true; + } + } private sealed class LoginResponse { @@ -91,7 +104,7 @@ } var customProvider = (CustomAuthenticationStateProvider)AuthStateProvider; - await customProvider.MarkUserAsAuthenticatedAsync(auth.Username ?? Username, auth.AccessToken, auth.Role ?? "Admin"); + await customProvider.MarkUserAsAuthenticatedAsync(auth.Username ?? Username, auth.AccessToken, auth.Role ?? "Admin", RememberUsername); NavigationManager.NavigateTo("/dashboard"); } else