using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Cli.Services.Models;
namespace StellaOps.Cli.Services;
///
/// HTTP client for Authority console endpoints (CLI-TEN-47-001, CLI-TEN-49-001).
///
internal sealed class AuthorityConsoleClient : IAuthorityConsoleClient
{
private readonly HttpClient _httpClient;
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
public AuthorityConsoleClient(HttpClient httpClient)
{
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
}
public async Task> ListTenantsAsync(string tenant, CancellationToken cancellationToken)
{
using var request = new HttpRequestMessage(HttpMethod.Get, "console/tenants");
if (!string.IsNullOrWhiteSpace(tenant))
{
request.Headers.Add("X-StellaOps-Tenant", tenant.Trim().ToLowerInvariant());
}
using var response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var result = await response.Content
.ReadFromJsonAsync(cancellationToken: cancellationToken)
.ConfigureAwait(false);
return result?.Tenants ?? Array.Empty();
}
public async Task MintTokenAsync(TokenMintRequest request, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(request);
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, "console/token/mint")
{
Content = JsonContent.Create(request, options: JsonOptions)
};
if (!string.IsNullOrWhiteSpace(request.Tenant))
{
httpRequest.Headers.Add("X-StellaOps-Tenant", request.Tenant.Trim().ToLowerInvariant());
}
using var response = await _httpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var result = await response.Content
.ReadFromJsonAsync(JsonOptions, cancellationToken)
.ConfigureAwait(false);
return result ?? throw new InvalidOperationException("Token mint response was empty.");
}
public async Task DelegateTokenAsync(TokenDelegateRequest request, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(request);
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, "console/token/delegate")
{
Content = JsonContent.Create(request, options: JsonOptions)
};
if (!string.IsNullOrWhiteSpace(request.Tenant))
{
httpRequest.Headers.Add("X-StellaOps-Tenant", request.Tenant.Trim().ToLowerInvariant());
}
using var response = await _httpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var result = await response.Content
.ReadFromJsonAsync(JsonOptions, cancellationToken)
.ConfigureAwait(false);
return result ?? throw new InvalidOperationException("Token delegation response was empty.");
}
public async Task IntrospectTokenAsync(string? tenant, CancellationToken cancellationToken)
{
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, "console/token/introspect");
if (!string.IsNullOrWhiteSpace(tenant))
{
httpRequest.Headers.Add("X-StellaOps-Tenant", tenant.Trim().ToLowerInvariant());
}
using var response = await _httpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
return null;
}
return await response.Content
.ReadFromJsonAsync(JsonOptions, cancellationToken)
.ConfigureAwait(false);
}
}