mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 06:46:30 +00:00
116 lines
4.0 KiB
C#
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();
|
|
}
|
|
}
|
|
} |