Files
DiunaBI/DiunaBI.UI.Shared/Services/AuthService.cs

180 lines
6.4 KiB
C#
Raw Normal View History

2025-11-09 19:39:52 +01:00
using System.Net.Http.Json;
2025-11-06 10:20:00 +01:00
using System.Text.Json;
using Microsoft.JSInterop;
namespace DiunaBI.UI.Shared.Services;
public class UserInfo
{
2025-11-09 19:39:52 +01:00
public Guid Id { get; set; }
2025-11-06 10:20:00 +01:00
public string FullName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string AvatarUrl { get; set; } = string.Empty;
}
public class AuthService
{
2025-11-09 19:39:52 +01:00
private readonly HttpClient _httpClient;
2025-11-06 10:20:00 +01:00
private readonly IJSRuntime _jsRuntime;
2025-12-06 00:36:22 +01:00
private readonly TokenProvider _tokenProvider;
2025-11-06 10:20:00 +01:00
private bool? _isAuthenticated;
private UserInfo? _userInfo = null;
2025-11-09 19:39:52 +01:00
private string? _apiToken;
2025-12-01 17:56:17 +01:00
2025-11-06 10:20:00 +01:00
public event Action<bool>? AuthenticationStateChanged;
2025-12-01 17:56:17 +01:00
2025-12-06 00:36:22 +01:00
public AuthService(HttpClient httpClient, IJSRuntime jsRuntime, TokenProvider tokenProvider)
2025-11-06 10:20:00 +01:00
{
2025-11-09 19:39:52 +01:00
_httpClient = httpClient;
2025-11-06 10:20:00 +01:00
_jsRuntime = jsRuntime;
2025-12-06 00:36:22 +01:00
_tokenProvider = tokenProvider;
2025-11-06 10:20:00 +01:00
}
public bool IsAuthenticated => _isAuthenticated ?? false;
public UserInfo? CurrentUser => _userInfo;
2025-11-09 19:39:52 +01:00
public async Task<(bool success, string? errorMessage)> ValidateWithBackendAsync(string googleCredential, string fullName, string email, string avatarUrl)
2025-11-06 10:20:00 +01:00
{
try
{
2025-11-09 19:39:52 +01:00
Console.WriteLine($"=== ValidateWithBackend: Sending Google credential for {email} ===");
2025-11-06 10:20:00 +01:00
2025-11-19 17:21:14 +01:00
var response = await _httpClient.PostAsJsonAsync("Auth/apiToken", googleCredential);
2025-11-09 19:39:52 +01:00
if (response.IsSuccessStatusCode)
2025-11-06 10:20:00 +01:00
{
2025-11-09 19:39:52 +01:00
var result = await response.Content.ReadFromJsonAsync<ApiTokenResponse>();
if (result != null)
{
_apiToken = result.Token;
2025-12-06 00:36:22 +01:00
_tokenProvider.Token = result.Token; // Set token for SignalR
2025-11-09 19:39:52 +01:00
_userInfo = new UserInfo
{
Id = result.Id,
FullName = fullName,
Email = email,
AvatarUrl = avatarUrl
};
2025-12-01 17:56:17 +01:00
2025-11-09 19:39:52 +01:00
await _jsRuntime.InvokeVoidAsync("localStorage.setItem", "api_token", _apiToken);
await _jsRuntime.InvokeVoidAsync("localStorage.setItem", "user_info", JsonSerializer.Serialize(_userInfo));
2025-12-01 17:56:17 +01:00
_httpClient.DefaultRequestHeaders.Authorization =
2025-11-09 19:39:52 +01:00
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiToken);
2025-12-01 17:56:17 +01:00
2025-11-09 19:39:52 +01:00
_isAuthenticated = true;
Console.WriteLine($"✅ Backend validation successful. UserId={result.Id}");
AuthenticationStateChanged?.Invoke(true);
2025-12-01 17:56:17 +01:00
2025-11-09 19:39:52 +01:00
return (true, null);
}
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
Console.WriteLine("❌ User not found in DiunaBI database");
2025-11-20 21:03:19 +01:00
return (false, "User does not exist in DiunaBI database.");
2025-11-09 19:39:52 +01:00
}
else
{
Console.WriteLine($"❌ Backend error: {response.StatusCode}");
2025-11-20 21:03:19 +01:00
return (false, "DiunaBI server error. Please try again.");
2025-11-06 10:20:00 +01:00
}
2025-11-20 21:03:19 +01:00
return (false, "Unexpected error.");
2025-11-09 19:39:52 +01:00
}
catch (HttpRequestException ex)
{
Console.WriteLine($"❌ Network error: {ex.Message}");
2025-11-20 21:03:19 +01:00
return (false, "Cannot connect to DiunaBI server.");
2025-11-06 10:20:00 +01:00
}
catch (Exception ex)
{
2025-11-09 19:39:52 +01:00
Console.WriteLine($"❌ Validation error: {ex.Message}");
2025-11-20 21:03:19 +01:00
return (false, "User verification error.");
2025-11-06 10:20:00 +01:00
}
}
2025-11-09 19:39:52 +01:00
public async Task<bool> CheckAuthenticationAsync()
2025-11-06 10:20:00 +01:00
{
try
{
2025-11-09 19:39:52 +01:00
Console.WriteLine("=== AuthService.CheckAuthenticationAsync START ===");
var token = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", "api_token");
var userInfoJson = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", "user_info");
_isAuthenticated = !string.IsNullOrEmpty(token);
2025-11-06 10:20:00 +01:00
2025-11-09 19:39:52 +01:00
if (_isAuthenticated.Value && !string.IsNullOrEmpty(userInfoJson))
{
_apiToken = token;
2025-12-06 00:36:22 +01:00
_tokenProvider.Token = token; // Set token for SignalR
2025-11-09 19:39:52 +01:00
_userInfo = JsonSerializer.Deserialize<UserInfo>(userInfoJson);
2025-11-20 21:03:19 +01:00
// Restore header
_httpClient.DefaultRequestHeaders.Authorization =
2025-11-09 19:39:52 +01:00
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiToken);
2025-12-01 17:56:17 +01:00
2025-11-09 19:39:52 +01:00
Console.WriteLine($"✅ Session restored: {_userInfo?.Email}");
2025-12-06 00:36:22 +01:00
// Notify that authentication state changed (for SignalR initialization)
AuthenticationStateChanged?.Invoke(true);
2025-11-09 19:39:52 +01:00
}
else
2025-11-06 10:20:00 +01:00
{
2025-11-09 19:39:52 +01:00
Console.WriteLine("❌ No valid session");
2025-11-06 10:20:00 +01:00
}
2025-12-06 00:36:22 +01:00
2025-11-09 19:39:52 +01:00
Console.WriteLine($"=== AuthService.CheckAuthenticationAsync END (authenticated={_isAuthenticated}) ===");
2025-12-06 00:36:22 +01:00
2025-11-09 19:39:52 +01:00
return _isAuthenticated.Value;
2025-11-06 10:20:00 +01:00
}
catch (Exception ex)
{
2025-11-09 19:39:52 +01:00
Console.WriteLine($"❌ CheckAuthentication ERROR: {ex.Message}");
_isAuthenticated = false;
_userInfo = null;
return false;
2025-11-06 10:20:00 +01:00
}
}
public async Task ClearAuthenticationAsync()
{
try
{
2025-11-09 19:39:52 +01:00
Console.WriteLine("=== AuthService.ClearAuthenticationAsync ===");
await _jsRuntime.InvokeVoidAsync("localStorage.removeItem", "api_token");
2025-11-06 10:20:00 +01:00
await _jsRuntime.InvokeVoidAsync("localStorage.removeItem", "user_info");
2025-12-01 17:56:17 +01:00
2025-11-09 19:39:52 +01:00
_apiToken = null;
2025-12-06 00:36:22 +01:00
_tokenProvider.Token = null; // Clear token for SignalR
2025-11-06 10:20:00 +01:00
_isAuthenticated = false;
_userInfo = null;
2025-12-01 17:56:17 +01:00
2025-11-09 19:39:52 +01:00
_httpClient.DefaultRequestHeaders.Authorization = null;
2025-12-06 00:36:22 +01:00
2025-11-09 19:39:52 +01:00
Console.WriteLine("✅ Authentication cleared");
2025-11-06 10:20:00 +01:00
AuthenticationStateChanged?.Invoke(false);
}
catch (Exception ex)
{
2025-11-09 19:39:52 +01:00
Console.WriteLine($"❌ ClearAuthentication ERROR: {ex.Message}");
2025-11-06 10:20:00 +01:00
}
}
public async Task<string?> GetTokenAsync()
{
if (_isAuthenticated != true)
{
await CheckAuthenticationAsync();
}
2025-11-09 19:39:52 +01:00
return _apiToken;
}
private class ApiTokenResponse
{
public string Token { get; set; } = string.Empty;
public Guid Id { get; set; }
public DateTime ExpirationTime { get; set; }
2025-11-06 10:20:00 +01:00
}
}