2024-11-15 09:28:21 -07:00

130 lines
5.8 KiB
C#

using System.Net;
using System.Text.Json;
using System.Text;
using MesaFabApproval.Shared.Models;
using Microsoft.Extensions.Caching.Memory;
using System.Net.Http.Headers;
using MesaFabApproval.Client.Services;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using System.Net.Http;
namespace MesaFabApproval.Client.Utilities;
public class ApiHttpClientHandler : DelegatingHandler {
private readonly IMemoryCache _cache;
private readonly IAuthenticationService _authService;
private readonly IHttpClientFactory _httpClientFactory;
private readonly ISnackbar _snackbar;
private readonly MesaFabApprovalAuthStateProvider _authStateProvider;
private readonly NavigationManager _navigationManager;
private readonly string _apiBaseUrl;
public ApiHttpClientHandler(IMemoryCache cache,
IConfiguration config,
IAuthenticationService authService,
IHttpClientFactory httpClientFactory,
ISnackbar snackbar,
MesaFabApprovalAuthStateProvider authStateProvider,
NavigationManager navigationManager) {
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
_apiBaseUrl = config["FabApprovalApiBaseUrl"] ??
throw new NullReferenceException("FabApprovalApiBaseUrl not found in config");
_httpClientFactory = httpClientFactory ??
throw new ArgumentNullException("IHttpClientFactory not injected");
_snackbar = snackbar ?? throw new ArgumentNullException("ISnackbar not injected");
_authService = authService ??
throw new ArgumentNullException("IAuthenticationService not injected");
_authStateProvider = authStateProvider ??
throw new ArgumentNullException("MesaFabApprovalAuthStateProvider not injected");
_navigationManager = navigationManager ??
throw new ArgumentNullException("NavigationManager not injected");
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage,
CancellationToken cancellationToken) {
AuthTokens? authTokens = await _authService.GetAuthTokens();
HttpRequestMessage initialRequestMessage = new() {
Content = requestMessage.Content,
Method = requestMessage.Method,
RequestUri = requestMessage.RequestUri
};
if (authTokens is not null) {
initialRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authTokens.JwtToken);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authTokens.JwtToken);
}
HttpClient initialClient = _httpClientFactory.CreateClient("API_Handler");
HttpResponseMessage responseMessage = await initialClient.SendAsync(initialRequestMessage, cancellationToken);
HttpClient refreshClient = _httpClientFactory.CreateClient("API_Handler");
if (responseMessage.StatusCode.Equals(HttpStatusCode.Unauthorized)) {
string? loginId = await _authService.GetLoginId();
if (!string.IsNullOrWhiteSpace(loginId)) {
AuthAttempt authAttempt = new() {
LoginID = loginId,
AuthTokens = authTokens
};
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "auth/refresh");
request.Content = new StringContent(JsonSerializer.Serialize(authAttempt),
Encoding.UTF8,
"application/json");
if (authTokens is not null) {
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authTokens.JwtToken);
}
HttpResponseMessage httpResponseMessage = await refreshClient.SendAsync(request, cancellationToken);
string responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
if (httpResponseMessage.IsSuccessStatusCode) {
JsonSerializerOptions jsonSerializerOptions = new() {
PropertyNameCaseInsensitive = true
};
LoginResult loginResult = JsonSerializer.Deserialize<LoginResult>(responseContent, jsonSerializerOptions) ??
throw new Exception("unable to parse login result from API response");
if (!loginResult.IsAuthenticated) throw new Exception($"User with Login ID {loginId} not authorized");
if (loginResult.AuthTokens is not null) {
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", loginResult.AuthTokens.JwtToken);
await _authService.SetTokens(loginResult.AuthTokens.JwtToken, loginResult.AuthTokens.RefreshToken);
}
if (loginResult.User is not null)
await _authService.SetCurrentUser(loginResult.User);
} else {
await _authStateProvider.Logout();
string? redirectUrl = _cache.Get<string>("redirectUrl");
if (!string.IsNullOrWhiteSpace(redirectUrl)) {
_navigationManager.NavigateTo($"login/{redirectUrl}");
} else {
_navigationManager.NavigateTo("login");
}
}
}
return await base.SendAsync(requestMessage, cancellationToken);
}
initialClient.Dispose();
refreshClient.Dispose();
return responseMessage;
}
}