Add remember username on login
WBS-9.3 - NULL Policy CI Gate / NULL Policy Validation (push) Failing after 5s
Quant Engine CI/CD Pipeline / validate-core (push) Failing after 10s
Quant Engine CI/CD Pipeline / validate-ui-and-storage (push) Has been skipped
Deploy to Production / Build & Deploy to Production (push) Failing after 1m49s

This commit is contained in:
2026-07-01 13:35:13 +09:00
parent 784f4bdbfb
commit 3e7120c041
2 changed files with 46 additions and 3 deletions
@@ -12,6 +12,7 @@ namespace QuantEngine.Web.Client.Infrastructure
private const string TokenKey = "quant_admin_access_token"; private const string TokenKey = "quant_admin_access_token";
private const string UsernameKey = "quant_admin_username"; private const string UsernameKey = "quant_admin_username";
private const string RoleKey = "quant_admin_role"; private const string RoleKey = "quant_admin_role";
private const string RememberUsernameKey = "quant_admin_remember_username";
public CustomAuthenticationStateProvider(LocalStorageService localStorage, HttpClient http) 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) 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(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); await _localStorage.SetAsync(RoleKey, role);
var identity = new ClaimsIdentity(new[] var identity = new ClaimsIdentity(new[]
@@ -75,8 +90,12 @@ namespace QuantEngine.Web.Client.Infrastructure
public async Task MarkUserAsLoggedOutAsync() public async Task MarkUserAsLoggedOutAsync()
{ {
await _localStorage.DeleteAsync(TokenKey); await _localStorage.DeleteAsync(TokenKey);
await _localStorage.DeleteAsync(UsernameKey);
await _localStorage.DeleteAsync(RoleKey); await _localStorage.DeleteAsync(RoleKey);
var rememberUsername = await _localStorage.GetAsync<bool>(RememberUsernameKey);
if (!rememberUsername)
{
await _localStorage.DeleteAsync(UsernameKey);
}
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_anonymous))); NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_anonymous)));
} }
@@ -99,5 +118,16 @@ namespace QuantEngine.Web.Client.Infrastructure
await MarkUserAsLoggedOutAsync(); await MarkUserAsLoggedOutAsync();
} }
public async Task<string?> GetRememberedUsernameAsync()
{
var rememberUsername = await _localStorage.GetAsync<bool>(RememberUsernameKey);
if (!rememberUsername)
{
return null;
}
return await _localStorage.GetAsync<string>(UsernameKey);
}
} }
} }
@@ -18,6 +18,7 @@
<MudStack Spacing="2"> <MudStack Spacing="2">
<MudTextField Label="관리자 아이디" @bind-Value="Username" Variant="Variant.Outlined" Immediate="true" AutoFocus="true" /> <MudTextField Label="관리자 아이디" @bind-Value="Username" Variant="Variant.Outlined" Immediate="true" AutoFocus="true" />
<MudTextField Label="비밀번호" @bind-Value="Password" Variant="Variant.Outlined" InputType="InputType.Password" Immediate="true" /> <MudTextField Label="비밀번호" @bind-Value="Password" Variant="Variant.Outlined" InputType="InputType.Password" Immediate="true" />
<MudCheckBox T="bool" @bind-Checked="RememberUsername" Color="Color.Primary" Label="아이디 저장" />
@if (!string.IsNullOrEmpty(ErrorMessage)) @if (!string.IsNullOrEmpty(ErrorMessage))
{ {
@@ -57,6 +58,18 @@
private string Password { get; set; } = string.Empty; private string Password { get; set; } = string.Empty;
private string ErrorMessage { get; set; } = string.Empty; private string ErrorMessage { get; set; } = string.Empty;
private bool IsSubmitting { get; set; } = false; 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 private sealed class LoginResponse
{ {
@@ -91,7 +104,7 @@
} }
var customProvider = (CustomAuthenticationStateProvider)AuthStateProvider; 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"); NavigationManager.NavigateTo("/dashboard");
} }
else else