Skip to content

Commit

Permalink
Merge branch 'main' into nmshdb-81-improve-relationships-api
Browse files Browse the repository at this point in the history
  • Loading branch information
tnotheis committed Apr 5, 2024
2 parents 4f22e88 + f150b86 commit 2a302ad
Show file tree
Hide file tree
Showing 159 changed files with 10,350 additions and 3,277 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @tnotheis
* @tnotheis @jkoenig134
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2.14.0
uses: subosito/flutter-action@v2.15.0
- name: Run checks
run: ./.ci/aui/runFlutterChecks.sh

Expand Down
6 changes: 6 additions & 0 deletions AdminApi.Sdk/AdminApi.Sdk.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\BuildingBlocks\src\BuildingBlocks.SDK\BuildingBlocks.SDK.csproj" />
<ProjectReference Include="..\BuildingBlocks\src\Tooling\Tooling.csproj" />
</ItemGroup>
</Project>
37 changes: 37 additions & 0 deletions AdminApi.Sdk/Client.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation;
using Backbone.AdminApi.Sdk.Endpoints.Clients;
using Backbone.AdminApi.Sdk.Endpoints.Common;
using Backbone.AdminApi.Sdk.Endpoints.Identities;
using Backbone.AdminApi.Sdk.Endpoints.Logs;
using Backbone.AdminApi.Sdk.Endpoints.Metrics;
using Backbone.AdminApi.Sdk.Endpoints.Relationships;
using Backbone.AdminApi.Sdk.Endpoints.Tiers;
using Backbone.BuildingBlocks.SDK.Endpoints.Common;

namespace Backbone.AdminApi.Sdk;

public class Client
{
public Client(Configuration config)
{
var httpClient = new HttpClient { BaseAddress = new Uri(config.BaseUrl) };
var authenticator = new XsrfAndApiKeyAuthenticator(config.ApiKey, httpClient);
var endpointClient = new EndpointClient(httpClient, authenticator, config.JsonSerializerOptions);

ApiKeyValidation = new ApiKeyValidationEndpoint(endpointClient);
Clients = new ClientsEndpoint(endpointClient);
Identities = new IdentitiesEndpoint(endpointClient);
Logs = new LogsEndpoint(endpointClient);
Metrics = new MetricsEndpoint(endpointClient);
Relationships = new RelationshipsEndpoint(endpointClient);
Tiers = new TiersEndpoint(endpointClient);
}

public ApiKeyValidationEndpoint ApiKeyValidation { get; }
public ClientsEndpoint Clients { get; }
public IdentitiesEndpoint Identities { get; }
public LogsEndpoint Logs { get; }
public MetricsEndpoint Metrics { get; }
public RelationshipsEndpoint Relationships { get; }
public TiersEndpoint Tiers { get; }
}
16 changes: 16 additions & 0 deletions AdminApi.Sdk/Configuration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json;
using Backbone.Tooling.JsonConverters;

namespace Backbone.AdminApi.Sdk;

public class Configuration
{
public Configuration()
{
JsonSerializerOptions.Converters.Add(new UrlSafeBase64ToByteArrayJsonConverter());
}

public required string BaseUrl { get; set; }
public required string ApiKey { get; set; }
public JsonSerializerOptions JsonSerializerOptions { get; set; } = new() { PropertyNameCaseInsensitive = true };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation.Types.Requests;
using Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation.Types.Responses;
using Backbone.BuildingBlocks.SDK.Endpoints.Common;
using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types;

namespace Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation;

public class ApiKeyValidationEndpoint(EndpointClient client) : Endpoint(client)
{
public async Task<ApiResponse<ValidateApiKeyResponse>> ValidateApiKeyUnauthenticated(ValidateApiKeyRequest? request)
=> await _client.PostUnauthenticated<ValidateApiKeyResponse>("ValidateApiKey", request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation.Types.Requests;

public class ValidateApiKeyRequest
{
public string? ApiKey { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation.Types.Responses;

public class ValidateApiKeyResponse
{
public required bool IsValid { get; set; }
}
25 changes: 25 additions & 0 deletions AdminApi.Sdk/Endpoints/Clients/ClientsEndpoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Backbone.AdminApi.Sdk.Endpoints.Clients.Types;
using Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Requests;
using Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Responses;
using Backbone.BuildingBlocks.SDK.Endpoints.Common;
using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types;

namespace Backbone.AdminApi.Sdk.Endpoints.Clients;

public class ClientsEndpoint(EndpointClient client) : Endpoint(client)
{
public async Task<ApiResponse<ListClientsResponse>> GetAllClients() => await _client.Get<ListClientsResponse>("Clients");

public async Task<ApiResponse<ClientInfo>> GetClient(string id) => await _client.Get<ClientInfo>($"Clients/{id}");

public async Task<ApiResponse<CreateClientResponse>> CreateClient(CreateClientRequest request)
=> await _client.Post<CreateClientResponse>("Clients", request);

public async Task<ApiResponse<ClientInfo>> ChangeClientSecret(string id, ChangeClientSecretRequest request)
=> await _client.Patch<ClientInfo>($"Clients/{id}/ChangeSecret", request);

public async Task<ApiResponse<ClientInfo>> UpdateClient(string id, UpdateClientRequest request)
=> await _client.Put<ClientInfo>($"Clients/{id}", request);

public async Task<ApiResponse<EmptyResponse>> DeleteClient(string id) => await _client.Delete<EmptyResponse>($"Clients/{id}");
}
10 changes: 10 additions & 0 deletions AdminApi.Sdk/Endpoints/Clients/Types/ClientInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types;

public class ClientInfo
{
public required string ClientId { get; set; }
public required string DisplayName { get; set; }
public required string DefaultTier { get; set; }
public required DateTime CreatedAt { get; set; }
public int? MaxIdentities { get; set; }
}
17 changes: 17 additions & 0 deletions AdminApi.Sdk/Endpoints/Clients/Types/ClientOverwiew.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types;

public class ClientOverwiew
{
public required string ClientId { get; set; }
public required string DisplayName { get; set; }
public required Tier DefaultTier { get; set; }
public required DateTime CreatedAt { get; set; }
public int? MaxIdentities { get; set; }
public required int NumberOfIdentities { get; set; }
}

public class Tier
{
public required string Id { get; set; }
public required string Name { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Requests;

public class ChangeClientSecretRequest
{
public required string NewSecret { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Requests;

public class CreateClientRequest
{
public string? ClientId { get; set; }
public string? DisplayName { get; set; }
public string? ClientSecret { get; set; }
public required string DefaultTier { get; set; }
public int? MaxIdentities { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Requests;

public class UpdateClientRequest
{
public required string DefaultTier { get; set; }
public int? MaxIdentities { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Responses;

public class CreateClientResponse
{
public required string ClientId { get; set; }
public required string DisplayName { get; set; }
public required string ClientSecret { get; set; }
public required string DefaultTier { get; set; }
public required DateTime CreatedAt { get; set; }
public int? MaxIdentities { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types;

namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Responses;

public class ListClientsResponse : EnumerableResponseBase<ClientOverwiew>;
53 changes: 53 additions & 0 deletions AdminApi.Sdk/Endpoints/Common/XsrfAndApiKeyAuthenticator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Diagnostics.CodeAnalysis;
using Backbone.BuildingBlocks.SDK.Endpoints.Common;

namespace Backbone.AdminApi.Sdk.Endpoints.Common;

public class XsrfAndApiKeyAuthenticator : IAuthenticator
{
private readonly string _apiKey;
private string? _xsrfToken = null;
private string? _xsrfCookie = null;
private readonly HttpClient _client;

public XsrfAndApiKeyAuthenticator(string apiKey, HttpClient client)
{
_apiKey = apiKey;
_client = client;
}

public async Task Authenticate(HttpRequestMessage request)
{
request.Headers.Add("X-API-KEY", _apiKey);
request.Headers.Add("X-XSRF-TOKEN", await GetToken());
request.Headers.Add("Cookie", await GetCookie());
}

private async Task<string> GetToken()
{
if (_xsrfToken == null) await RefreshToken();

return _xsrfToken;
}

private async Task<string> GetCookie()
{
if (_xsrfCookie == null) await RefreshToken();

return _xsrfCookie;
}

[MemberNotNull(nameof(_xsrfToken), nameof(_xsrfCookie))]
private async Task RefreshToken()
{
HttpRequestMessage request = new(HttpMethod.Get, "xsrf");
request.Headers.Add("X-API-KEY", _apiKey);

#pragma warning disable CS8774 // This warning ("Member must have a non-null value when exiting") must currently be disabled. (see https://github.com/dotnet/csharplang/discussions/ for details)
var response = await _client.SendAsync(request);

_xsrfToken = await response.Content.ReadAsStringAsync();
_xsrfCookie = response.Headers.GetValues("Set-Cookie").First();
#pragma warning restore CS8774
}
}
27 changes: 27 additions & 0 deletions AdminApi.Sdk/Endpoints/Identities/IdentitiesEndpoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Backbone.AdminApi.Sdk.Endpoints.Identities.Types;
using Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Requests;
using Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Responses;
using Backbone.BuildingBlocks.SDK.Endpoints.Common;
using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types;

namespace Backbone.AdminApi.Sdk.Endpoints.Identities;

public class IdentitiesEndpoint(EndpointClient client) : Endpoint(client)
{
public async Task<ApiResponse<IndividualQuota>> CreateIndividualQuota(string address, CreateQuotaForIdentityRequest request)
=> await _client.Post<IndividualQuota>($"Identities/{address}/Quotas", request);

public async Task<ApiResponse<EmptyResponse>> DeleteIndividualQuota(string address, string quotaId)
=> await _client.Delete<EmptyResponse>($"Identities/{address}/Quotas/{quotaId}");

public async Task<ApiResponse<GetIdentityResponse>> GetIdentity(string address) => await _client.Get<GetIdentityResponse>($"Identities/{address}");

public async Task<ApiResponse<EmptyResponse>> UpdateIdentityTier(string address, UpdateIdentityTierRequest request)
=> await _client.Put<EmptyResponse>($"Identities/{address}", request);

public async Task<ApiResponse<CreateIdentityResponse>> CreateIdentity(CreateIdentityRequest request)
=> await _client.Post<CreateIdentityResponse>("Identities", request);

public async Task<ApiResponse<StartDeletionProcessAsSupportResponse>> StartDeletionProcess(string address)
=> await _client.Post<StartDeletionProcessAsSupportResponse>($"Identities/{address}/DeletionProcesses");
}
9 changes: 9 additions & 0 deletions AdminApi.Sdk/Endpoints/Identities/Types/IndividualQuota.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types;

public class IndividualQuota
{
public required string Id { get; set; }
public required Metric Metric { get; set; }
public required int Max { get; set; }
public required string Period { get; set; }
}
7 changes: 7 additions & 0 deletions AdminApi.Sdk/Endpoints/Identities/Types/Metric.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types;

public class Metric
{
public required string Key { get; set; }
public required string DisplayName { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Requests;

public class CreateIdentityRequest
{
public required string ClientId { get; set; }
public required string ClientSecret { get; set; }
public required byte[] IdentityPublicKey { get; set; }
public required string DevicePassword { get; set; }
public required byte IdentityVersion { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Requests;

public class CreateQuotaForIdentityRequest
{
public required string MetricKey { get; set; }
public required int Max { get; set; }
public required string Period { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Requests;

public class UpdateIdentityTierRequest
{
public required string TierId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Responses;

public class CreateIdentityResponse
{
public required string Address { get; set; }
public required DateTime CreatedAt { get; set; }
public required CreateIdentityResponseDevice Device { get; set; }
}

public class CreateIdentityResponseDevice
{
public required string Id { get; set; }
public required string Username { get; set; }
public required DateTime CreatedAt { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Responses;

public class GetIdentityResponse
{
public required string Address { get; set; }
public string? ClientId { get; set; }
public required byte[] PublicKey { get; set; }
public required string TierId { get; set; }
public required DateTime CreatedAt { get; set; }
public required byte IdentityVersion { get; set; }
public required int NumberOfDevices { get; set; }
public required List<Device> Devices { get; set; }
public required List<Quota> Quotas { get; set; }
}

public class Device
{
public required string Id { get; set; }
public required string Username { get; set; }
public required DateTime CreatedAt { get; set; }
public required string CreatedByDevice { get; set; }
public required LastLoginInformation LastLogin { get; set; }
}

public class LastLoginInformation
{
public DateTime? Time { get; set; }
}

public class Quota
{
public required string Id { get; set; }
public required string Source { get; set; }
public required Metric Metric { get; set; }
public required int Max { get; set; }
public required uint Usage { get; set; }
public required string Period { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Responses;

public class StartDeletionProcessAsSupportResponse
{
public required string Id { get; set; }
public required string Status { get; set; }
public required DateTime CreatedAt { get; set; }
}
Loading

0 comments on commit 2a302ad

Please sign in to comment.