169 lines
7.8 KiB
C#
169 lines
7.8 KiB
C#
using ModVersionChecker.repository.api.dto;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace ModVersionChecker.repository.api
|
|
{
|
|
public class ApiRepository : IApiRepository, IDisposable
|
|
{
|
|
private readonly HttpClient _httpClient;
|
|
private string baseUrl = "http://192.168.1.115:3115/api";
|
|
private JwtTokenResponse? _accessToken;
|
|
private JwtTokenResponse? _refreshToken;
|
|
private DateTime _accessTokenExpiry = DateTime.MinValue;
|
|
|
|
public ApiRepository()
|
|
{
|
|
_httpClient = new HttpClient();
|
|
_httpClient.Timeout = TimeSpan.FromSeconds(30);
|
|
}
|
|
|
|
public async Task<bool> AuthenticateAsync(string username, string password)
|
|
{
|
|
var url = $"{baseUrl}/auth";
|
|
var payload = new { username, password };
|
|
var jsonPayload = JsonSerializer.Serialize(payload);
|
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
|
try
|
|
{
|
|
var response = await _httpClient.PostAsync(url, content);
|
|
response.EnsureSuccessStatusCode();
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
var authentication = JsonSerializer.Deserialize<AuthenticationResponse>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
_accessToken = DecodeJwt(authentication?.AccessToken);
|
|
_refreshToken = DecodeJwt(authentication?.RefreshToken);
|
|
if (_accessToken == null)
|
|
throw new Exception("Failed to decode access token.");
|
|
_accessTokenExpiry = DateTime.UtcNow.AddSeconds(_accessToken.ExpireAt - 60);
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private JwtTokenResponse? DecodeJwt(string? token)
|
|
{
|
|
if (string.IsNullOrEmpty(token))
|
|
return null;
|
|
var parts = token.Split('.');
|
|
if (parts.Length != 3)
|
|
throw new ArgumentException("Invalid JWT token format.");
|
|
var payload = parts[1];
|
|
var paddedPayload = payload.PadRight(payload.Length + (4 - payload.Length % 4) % 4, '=');
|
|
var jsonBytes = Convert.FromBase64String(paddedPayload);
|
|
var json = Encoding.UTF8.GetString(jsonBytes);
|
|
var doc = JsonSerializer.Deserialize<JwtTokenResponse>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
if (doc != null)
|
|
doc.Token = token;
|
|
return doc;
|
|
}
|
|
|
|
private async Task<bool> EnsureTokenValidAsync()
|
|
{
|
|
if (_accessToken == null || DateTime.UtcNow >= _accessTokenExpiry)
|
|
{
|
|
return await RefreshTokenAsync();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private async Task<bool> RefreshTokenAsync()
|
|
{
|
|
if (_refreshToken == null)
|
|
return false;
|
|
var refreshData = new { refreshToken = _refreshToken };
|
|
var content = new StringContent(JsonSerializer.Serialize(refreshData), Encoding.UTF8, "application/json");
|
|
var response = await _httpClient.PostAsync($"{baseUrl}/auth/refresh", content);
|
|
if (!response.IsSuccessStatusCode)
|
|
return false;
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
var authentication = JsonSerializer.Deserialize<AuthenticationResponse>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
_accessToken = DecodeJwt(authentication?.AccessToken);
|
|
if (_accessToken == null)
|
|
throw new Exception("Failed to decode access token.");
|
|
_accessTokenExpiry = DateTime.UtcNow.AddSeconds(_accessToken.ExpireAt - 60);
|
|
return true;
|
|
}
|
|
|
|
private async Task<HttpRequestMessage> CreateRequestAsync(HttpMethod method, string url)
|
|
{
|
|
await EnsureTokenValidAsync();
|
|
var request = new HttpRequestMessage(method, url);
|
|
if (_accessToken != null)
|
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken.Token);
|
|
return request;
|
|
}
|
|
|
|
public async Task<List<AppVersionsResponse>?> GetAppVersionsAsync(List<App> apps)
|
|
{
|
|
var url = $"{baseUrl}/app/versions?{string.Join("&", apps.Select(a => $"version={Uri.EscapeDataString(a.Id)}"))}";
|
|
var request = await CreateRequestAsync(HttpMethod.Get, url);
|
|
var response = await _httpClient.SendAsync(request);
|
|
response.EnsureSuccessStatusCode();
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
return JsonSerializer.Deserialize<List<AppVersionsResponse>>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
}
|
|
public async Task<AppVersionsResponse?> GetAppLatestVersionAsync(App app)
|
|
{
|
|
var url = $"{baseUrl}/app/latest?version={Uri.EscapeDataString(app.Id)}";
|
|
var request = await CreateRequestAsync(HttpMethod.Get, url);
|
|
var response = await _httpClient.SendAsync(request);
|
|
response.EnsureSuccessStatusCode();
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
return JsonSerializer.Deserialize<AppVersionsResponse>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
}
|
|
|
|
public async Task<List<TypeResponse>> GetTypes()
|
|
{
|
|
var url = $"{baseUrl}/type";
|
|
var request = await CreateRequestAsync(HttpMethod.Get, url);
|
|
var response = await _httpClient.SendAsync(request);
|
|
response.EnsureSuccessStatusCode();
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
return JsonSerializer.Deserialize<List<TypeResponse>>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
}
|
|
|
|
public async Task<List<SourceResponse>> GetSources()
|
|
{
|
|
var url = $"{baseUrl}/source";
|
|
var request = await CreateRequestAsync(HttpMethod.Get, url);
|
|
var response = await _httpClient.SendAsync(request);
|
|
response.EnsureSuccessStatusCode();
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
return JsonSerializer.Deserialize<List<SourceResponse>>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
}
|
|
|
|
public async Task<List<AppResponse>?> SearchApps(string searchText)
|
|
{
|
|
var url = $"{baseUrl}/app/search?q={Uri.EscapeDataString(searchText)}";
|
|
var request = await CreateRequestAsync(HttpMethod.Get, url);
|
|
var response = await _httpClient.SendAsync(request);
|
|
response.EnsureSuccessStatusCode();
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
return JsonSerializer.Deserialize<List<AppResponse>>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
}
|
|
|
|
public async Task<List<AppResponse>> GetAppsByIds(List<App> apps)
|
|
{
|
|
var query = string.Join("&", apps.Select(a => $"id={Uri.EscapeDataString(a.Id)}"));
|
|
var url = $"{baseUrl}/app/search?{query}";
|
|
var request = await CreateRequestAsync(HttpMethod.Get, url);
|
|
var response = await _httpClient.SendAsync(request);
|
|
response.EnsureSuccessStatusCode();
|
|
var json = await response.Content.ReadAsStringAsync();
|
|
return JsonSerializer.Deserialize<List<AppResponse>>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? new List<AppResponse>();
|
|
}
|
|
|
|
|
|
public void Dispose()
|
|
{
|
|
_httpClient?.Dispose();
|
|
}
|
|
}
|
|
} |