Files
annotations/Azaion.Common/Services/AuthProvider.cs
T
Oleksandr Bezdieniezhnykh fd95d2ba2c add MediaHash. Step1
2025-11-17 07:46:05 +02:00

116 lines
4.0 KiB
C#

using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Azaion.Common.DTO;
using Newtonsoft.Json;
using Serilog;
namespace Azaion.Common.Services;
public interface IAzaionApi
{
ApiCredentials Credentials { get; }
Task<User> GetCurrentUserAsync();
Task UpdateOffsetsAsync(UserQueueOffsets offsets);
}
public class AzaionApi(ILogger logger, HttpClient client, ICache cache, ApiCredentials credentials) : IAzaionApi
{
private readonly SemaphoreSlim _authLock = new(1, 1);
private string? _jwtToken;
const string APP_JSON = "application/json";
public ApiCredentials Credentials => credentials;
public async Task<User> GetCurrentUserAsync()
{
var user = await cache.GetFromCacheAsync(Constants.CURRENT_USER_CACHE_KEY,
async () => await GetAsync<User>("users/current"));
return user ?? throw new Exception("Can't get current user");
}
public async Task UpdateOffsetsAsync(UserQueueOffsets offsets)
{
var user = await GetCurrentUserAsync();
await PutAsync("/users/queue-offsets/set", new { Email = user.Email, Offsets = offsets });
}
private async Task<T?> GetAsync<T>(string url)
{
var response = await SendWithAuthAsync(() => client.GetAsync(url));
return JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync());
}
private async Task PutAsync<T>(string url, T obj)
{
var content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, APP_JSON);
await SendWithAuthAsync(() => client.PutAsync(url, content));
}
private async Task<HttpResponseMessage> SendWithAuthAsync(Func<Task<HttpResponseMessage>> sendAction)
{
if (string.IsNullOrEmpty(_jwtToken))
await AuthorizeAsync();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _jwtToken);
var response = await sendAction();
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
await AuthorizeAsync();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _jwtToken);
response = await sendAction();
}
if (!response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.Conflict)
{
var error = JsonConvert.DeserializeObject<BusinessExceptionDto>(content);
throw new Exception($"Failed: {response.StatusCode}! Error Code: {error?.ErrorCode}. Message: {error?.Message}");
}
throw new Exception($"Failed: {response.StatusCode}! Result: {content}");
}
return response;
}
private async Task AuthorizeAsync()
{
await _authLock.WaitAsync();
try
{
if (string.IsNullOrEmpty(credentials.Email) || credentials.Password.Length == 0)
throw new Exception("Email or password is empty!");
var content = new StringContent(
JsonConvert.SerializeObject(new { email = credentials.Email, password = credentials.Password }),
Encoding.UTF8, APP_JSON);
client.DefaultRequestHeaders.Authorization = null;
var response = await client.PostAsync("login", content);
if (!response.IsSuccessStatusCode)
throw new Exception($"Authorization failed: {response.StatusCode}");
var result = JsonConvert.DeserializeObject<LoginResponse>(await response.Content.ReadAsStringAsync())
?? throw new Exception("JWT Token not found in response");
_jwtToken = result.Token ?? throw new Exception("JWT Token not found in response");
}
catch (Exception e)
{
logger.Error(e, e.Message);
throw;
}
finally
{
_authLock.Release();
}
}
}