initial commit
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
using Indotalent.ConfigFrontEnd.Extensions;
|
||||
using Indotalent.ConfigFrontEnd.Models;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
|
||||
namespace Indotalent.ConfigFrontEnd.Common;
|
||||
|
||||
|
||||
public abstract class BaseAppPage : ComponentBase
|
||||
{
|
||||
[Inject]
|
||||
protected AuthenticationStateProvider AuthStateProvider { get; set; } = default!;
|
||||
|
||||
[Inject]
|
||||
protected CurrentUserState State { get; set; } = default!;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await SyncUserContext();
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
private async Task SyncUserContext()
|
||||
{
|
||||
var authState = await AuthStateProvider.GetAuthenticationStateAsync();
|
||||
var user = authState.User;
|
||||
|
||||
if (user.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
State.UserId = user.GetUserId();
|
||||
State.UserName = user.GetUserName();
|
||||
State.Email = user.GetEmail();
|
||||
State.FullName = user.GetFullName();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
using Indotalent.ConfigBackEnd.Interfaces;
|
||||
using Indotalent.Features.Account.Login.Cqrs;
|
||||
using Indotalent.Infrastructure.Authentication.Identity;
|
||||
using Indotalent.Shared.Models;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MudBlazor;
|
||||
using RestSharp;
|
||||
using System.Net;
|
||||
|
||||
namespace Indotalent.ConfigFrontEnd.Common;
|
||||
|
||||
public abstract class BaseService
|
||||
{
|
||||
protected readonly IHttpClientFactory ClientFactory;
|
||||
protected readonly NavigationManager Nav;
|
||||
protected readonly ISnackbar Snackbar;
|
||||
protected readonly ICurrentUserService CurrentUserService;
|
||||
protected readonly TokenProvider TokenProvider;
|
||||
|
||||
public BaseService(
|
||||
IHttpClientFactory clientFactory,
|
||||
NavigationManager nav,
|
||||
ISnackbar snackbar,
|
||||
ICurrentUserService currentUserService,
|
||||
TokenProvider tokenProvider)
|
||||
{
|
||||
ClientFactory = clientFactory;
|
||||
Nav = nav;
|
||||
Snackbar = snackbar;
|
||||
CurrentUserService = currentUserService;
|
||||
TokenProvider = tokenProvider;
|
||||
}
|
||||
|
||||
protected HttpClient CreateClient()
|
||||
{
|
||||
var client = ClientFactory.CreateClient();
|
||||
if (client.BaseAddress == null)
|
||||
{
|
||||
client.BaseAddress = new Uri(Nav.BaseUri);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
protected async Task<ApiResponse<T>?> ExecuteWithResponseAsync<T>(RestClient client, RestRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(TokenProvider.Token))
|
||||
request.AddOrUpdateHeader("Authorization", $"Bearer {TokenProvider.Token}");
|
||||
|
||||
if (!string.IsNullOrEmpty(TokenProvider.RefreshToken))
|
||||
request.AddOrUpdateHeader("X-Refresh-Token", TokenProvider.RefreshToken);
|
||||
|
||||
if (!string.IsNullOrEmpty(CurrentUserService.UserId))
|
||||
{
|
||||
request.AddOrUpdateHeader("X-UserId", CurrentUserService.UserId);
|
||||
request.AddOrUpdateHeader("X-UserName", CurrentUserService.UserName ?? string.Empty);
|
||||
request.AddOrUpdateHeader("X-Email", CurrentUserService.Email ?? string.Empty);
|
||||
request.AddOrUpdateHeader("X-FullName", CurrentUserService.FullName ?? string.Empty);
|
||||
}
|
||||
|
||||
var response = await client.ExecuteAsync<ApiResponse<T>>(request);
|
||||
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
var httpClient = CreateClient();
|
||||
|
||||
var refreshRequestMessage = new HttpRequestMessage(HttpMethod.Post, "/api/account/refresh-token");
|
||||
|
||||
if (!string.IsNullOrEmpty(TokenProvider.RefreshToken))
|
||||
{
|
||||
refreshRequestMessage.Headers.Add("X-Refresh-Token", TokenProvider.RefreshToken);
|
||||
}
|
||||
|
||||
var refreshResponse = await httpClient.SendAsync(refreshRequestMessage);
|
||||
|
||||
if (refreshResponse.IsSuccessStatusCode)
|
||||
{
|
||||
var result = await refreshResponse.Content.ReadFromJsonAsync<LoginResponse>();
|
||||
if (result != null && !string.IsNullOrEmpty(result.Token))
|
||||
{
|
||||
TokenProvider.Token = result.Token;
|
||||
|
||||
request.AddOrUpdateHeader("Authorization", $"Bearer {TokenProvider.Token}");
|
||||
response = await client.ExecuteAsync<ApiResponse<T>>(request);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Nav.NavigateTo("/account/login");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Data != null)
|
||||
{
|
||||
if (!response.Data.IsSuccess)
|
||||
{
|
||||
HandleApiError(response.Data);
|
||||
}
|
||||
return response.Data;
|
||||
}
|
||||
|
||||
var fallbackMessage = GetFriendlyInfrastructureErrorMessage(response);
|
||||
Snackbar.Add(fallbackMessage, Severity.Error);
|
||||
|
||||
return new ApiResponse<T>
|
||||
{
|
||||
IsSuccess = false,
|
||||
StatusCode = (int)response.StatusCode,
|
||||
Message = fallbackMessage
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var systemError = $"Client System Error: {ex.Message}";
|
||||
Snackbar.Add(systemError, Severity.Error);
|
||||
return new ApiResponse<T> { IsSuccess = false, Message = systemError };
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleApiError<T>(ApiResponse<T> response)
|
||||
{
|
||||
var mainMessage = response.Message ?? "Operation failed";
|
||||
if (response.Errors != null && response.Errors.Any())
|
||||
{
|
||||
var combinedErrors = string.Join(Environment.NewLine, response.Errors.Select(e => $"• {e}"));
|
||||
Snackbar.Add(combinedErrors, Severity.Error, config =>
|
||||
{
|
||||
config.ShowCloseIcon = true;
|
||||
config.VisibleStateDuration = 3000;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add(mainMessage, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFriendlyInfrastructureErrorMessage(RestResponse response)
|
||||
{
|
||||
return response.StatusCode switch
|
||||
{
|
||||
HttpStatusCode.ServiceUnavailable => "Server is currently under maintenance.",
|
||||
HttpStatusCode.GatewayTimeout => "Server took too long to respond.",
|
||||
HttpStatusCode.Unauthorized => "Session expired. Please login again.",
|
||||
HttpStatusCode.Forbidden => "You do not have permission to access this resource.",
|
||||
HttpStatusCode.InternalServerError => "A critical error occurred on the server.",
|
||||
_ => "Unable to reach the server. Please check your connection."
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user