using System.Security.Claims; using MesaFabApproval.Shared.Models; using Microsoft.AspNetCore.Components.Authorization; using MudBlazor; namespace MesaFabApproval.Client.Services; public class MesaFabApprovalAuthStateProvider : AuthenticationStateProvider, IDisposable { private readonly IAuthenticationService _authService; private readonly IUserService _userService; private readonly ISnackbar _snackbar; public User? CurrentUser { get; private set; } public MesaFabApprovalAuthStateProvider(IAuthenticationService authService, ISnackbar snackbar, IUserService userService) { _authService = authService ?? throw new ArgumentNullException("IAuthenticationService not injected"); _snackbar = snackbar ?? throw new ArgumentNullException("ISnackbar not injected"); _userService = userService ?? throw new ArgumentNullException("IUserService not injected"); AuthenticationStateChanged += OnAuthenticationStateChangedAsync; } public override async Task GetAuthenticationStateAsync() { ClaimsPrincipal principal = new(); try { principal = await _authService.FetchAuthState(); CurrentUser = await _authService.GetCurrentUser(); return new(principal); } catch (Exception ex) { return new(new ClaimsPrincipal()); } } public async Task StateHasChanged(ClaimsPrincipal principal) { if (principal is null) throw new ArgumentNullException("ClaimsPrincipal cannot be null"); CurrentUser = await _authService.GetCurrentUser(); NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(principal))); } public async Task LoginAsync(string loginId, string password) { try { if (string.IsNullOrWhiteSpace(loginId)) throw new ArgumentException("LoginId cannot be null or empty"); if (string.IsNullOrWhiteSpace(password)) throw new ArgumentException("Password cannot be null or empty"); ClaimsPrincipal principal = await _authService.SendAuthenticationRequest(loginId, password); CurrentUser = await _authService.GetCurrentUser(); NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(principal))); } catch (Exception ex) { _snackbar.Add(ex.Message, Severity.Error); NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(new()))); } } public async Task Logout() { CurrentUser = null; await _authService.ClearTokens(); await _authService.ClearCurrentUser(); NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(new()))); } public void Dispose() => AuthenticationStateChanged -= OnAuthenticationStateChangedAsync; private async void OnAuthenticationStateChangedAsync(Task task) { try { AuthenticationState authenticationState = await task; if (authenticationState is not null) { ClaimsPrincipal principal = await _authService.FetchAuthState(); CurrentUser = await _authService.GetCurrentUser(); } } catch (Exception ex) { Console.WriteLine($"Unable to get authentication state, because {ex.Message}"); } } }