fix(central-ui): resolve CentralUI-020..025 — auth-ping idle logout, DebugView race, push-handler disposal guard, JS-interop catch narrowing, claim-constant helper, SessionExpiry tests

This commit is contained in:
Joseph Doherty
2026-05-17 03:18:16 -04:00
parent f82bcbed7c
commit d7d74ebe5e
28 changed files with 974 additions and 124 deletions

View File

@@ -0,0 +1,43 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using ScadaLink.Security;
namespace ScadaLink.CentralUI.Auth;
/// <summary>
/// Claim-lookup helpers for the Central UI. CentralUI-024: claim types are owned
/// by <see cref="JwtTokenService"/> (the single source of truth). These helpers
/// resolve them through the <c>JwtTokenService</c> constants so a rename there
/// propagates here instead of silently breaking ten copy-pasted call sites.
/// </summary>
public static class ClaimsPrincipalExtensions
{
/// <summary>Fallback returned when no username claim is present.</summary>
public const string UnknownUser = "unknown";
/// <summary>
/// The audit username for <paramref name="principal"/>, or
/// <see cref="UnknownUser"/> when the claim is absent.
/// </summary>
public static string GetUsername(this ClaimsPrincipal principal)
=> principal.FindFirst(JwtTokenService.UsernameClaimType)?.Value ?? UnknownUser;
/// <summary>
/// The display name for <paramref name="principal"/>, or <c>null</c> when
/// the claim is absent.
/// </summary>
public static string? GetDisplayName(this ClaimsPrincipal principal)
=> principal.FindFirst(JwtTokenService.DisplayNameClaimType)?.Value;
/// <summary>
/// Resolves the current user's audit username from the auth state provider.
/// Replaces the <c>GetCurrentUserAsync</c> helper that was copy-pasted into
/// ten components (CentralUI-024).
/// </summary>
public static async Task<string> GetCurrentUsernameAsync(
this AuthenticationStateProvider authStateProvider)
{
var authState = await authStateProvider.GetAuthenticationStateAsync();
return authState.User.GetUsername();
}
}