diff --git a/AdminApi.Sdk/Client.cs b/AdminApi.Sdk/Client.cs index 3a289ffbbb..c961e3a593 100644 --- a/AdminApi.Sdk/Client.cs +++ b/AdminApi.Sdk/Client.cs @@ -1,10 +1,11 @@ -using System.Text.Json; +using System.Text.Json; using Backbone.AdminApi.Sdk.Authentication; using Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation; using Backbone.AdminApi.Sdk.Endpoints.Challenges; using Backbone.AdminApi.Sdk.Endpoints.Clients; using Backbone.AdminApi.Sdk.Endpoints.Identities; using Backbone.AdminApi.Sdk.Endpoints.Logs; +using Backbone.AdminApi.Sdk.Endpoints.Messages; using Backbone.AdminApi.Sdk.Endpoints.Metrics; using Backbone.AdminApi.Sdk.Endpoints.Relationships; using Backbone.AdminApi.Sdk.Endpoints.Tiers; @@ -32,6 +33,7 @@ private Client(HttpClient httpClient, string apiKey) Relationships = new RelationshipsEndpoint(endpointClient); Tiers = new TiersEndpoint(endpointClient); Challenges = new ChallengesEndpoint(endpointClient); + Messages = new MessagesEndpoint(endpointClient); } public ApiKeyValidationEndpoint ApiKeyValidation { get; } @@ -42,6 +44,7 @@ private Client(HttpClient httpClient, string apiKey) public RelationshipsEndpoint Relationships { get; } public TiersEndpoint Tiers { get; } public ChallengesEndpoint Challenges { get; } + public MessagesEndpoint Messages { get; } public static Client Create(string baseUrl, string apiKey) { diff --git a/AdminApi.Sdk/Endpoints/ApiKeyValidation/ApiKeyValidationEndpoint.cs b/AdminApi.Sdk/Endpoints/ApiKeyValidation/ApiKeyValidationEndpoint.cs index 5cfa64d27b..683c30f8e6 100644 --- a/AdminApi.Sdk/Endpoints/ApiKeyValidation/ApiKeyValidationEndpoint.cs +++ b/AdminApi.Sdk/Endpoints/ApiKeyValidation/ApiKeyValidationEndpoint.cs @@ -8,5 +8,7 @@ namespace Backbone.AdminApi.Sdk.Endpoints.ApiKeyValidation; public class ApiKeyValidationEndpoint(EndpointClient client) : AdminApiEndpoint(client) { public async Task> ValidateApiKeyUnauthenticated(ValidateApiKeyRequest? request) - => await _client.PostUnauthenticated($"api/{API_VERSION}/ValidateApiKey", request); + { + return await _client.PostUnauthenticated($"api/{API_VERSION}/ValidateApiKey", request); + } } diff --git a/AdminApi.Sdk/Endpoints/Challenges/ChallengesEndpoint.cs b/AdminApi.Sdk/Endpoints/Challenges/ChallengesEndpoint.cs index c202119588..c967cc135b 100644 --- a/AdminApi.Sdk/Endpoints/Challenges/ChallengesEndpoint.cs +++ b/AdminApi.Sdk/Endpoints/Challenges/ChallengesEndpoint.cs @@ -4,10 +4,10 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Challenges; -public class ChallengesEndpoint(EndpointClient client) : Endpoint(client) +public class ChallengesEndpoint(EndpointClient client) : AdminApiEndpoint(client) { public async Task> CreateChallenge() { - return await _client.Post("Challenges"); + return await _client.Post($"api/{API_VERSION}/Challenges"); } } diff --git a/AdminApi.Sdk/Endpoints/Challenges/Types/SignedChallenge.cs b/AdminApi.Sdk/Endpoints/Challenges/Types/SignedChallenge.cs index d4e79bd55d..bed7ca513c 100644 --- a/AdminApi.Sdk/Endpoints/Challenges/Types/SignedChallenge.cs +++ b/AdminApi.Sdk/Endpoints/Challenges/Types/SignedChallenge.cs @@ -1,4 +1,4 @@ -using Backbone.BuildingBlocks.SDK.Crypto; +using Backbone.BuildingBlocks.SDK.Crypto; using Backbone.Crypto; using Newtonsoft.Json; diff --git a/AdminApi.Sdk/Endpoints/Clients/ClientsEndpoint.cs b/AdminApi.Sdk/Endpoints/Clients/ClientsEndpoint.cs index 36a2d1e748..bb25eef90e 100644 --- a/AdminApi.Sdk/Endpoints/Clients/ClientsEndpoint.cs +++ b/AdminApi.Sdk/Endpoints/Clients/ClientsEndpoint.cs @@ -8,18 +8,33 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Clients; public class ClientsEndpoint(EndpointClient client) : AdminApiEndpoint(client) { - public async Task> GetAllClients() => await _client.Get($"api/{API_VERSION}/Clients"); + public async Task> GetAllClients() + { + return await _client.Get($"api/{API_VERSION}/Clients"); + } - public async Task> GetClient(string id) => await _client.Get($"api/{API_VERSION}/Clients/{id}"); + public async Task> GetClient(string id) + { + return await _client.Get($"api/{API_VERSION}/Clients/{id}"); + } public async Task> CreateClient(CreateClientRequest request) - => await _client.Post($"api/{API_VERSION}/Clients", request); + { + return await _client.Post($"api/{API_VERSION}/Clients", request); + } public async Task> ChangeClientSecret(string id, ChangeClientSecretRequest request) - => await _client.Patch($"api/{API_VERSION}/Clients/{id}/ChangeSecret", request); + { + return await _client.Patch($"api/{API_VERSION}/Clients/{id}/ChangeSecret", request); + } public async Task> UpdateClient(string id, UpdateClientRequest request) - => await _client.Put($"api/{API_VERSION}/Clients/{id}", request); + { + return await _client.Put($"api/{API_VERSION}/Clients/{id}", request); + } - public async Task> DeleteClient(string id) => await _client.Delete($"api/{API_VERSION}/Clients/{id}"); + public async Task> DeleteClient(string id) + { + return await _client.Delete($"api/{API_VERSION}/Clients/{id}"); + } } diff --git a/AdminApi.Sdk/Endpoints/Clients/Types/ClientOverwiew.cs b/AdminApi.Sdk/Endpoints/Clients/Types/ClientOverview.cs similarity index 94% rename from AdminApi.Sdk/Endpoints/Clients/Types/ClientOverwiew.cs rename to AdminApi.Sdk/Endpoints/Clients/Types/ClientOverview.cs index 1113dd7f74..57bcb94b94 100644 --- a/AdminApi.Sdk/Endpoints/Clients/Types/ClientOverwiew.cs +++ b/AdminApi.Sdk/Endpoints/Clients/Types/ClientOverview.cs @@ -1,6 +1,6 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types; -public class ClientOverwiew +public class ClientOverview { public required string ClientId { get; set; } public required string DisplayName { get; set; } diff --git a/AdminApi.Sdk/Endpoints/Clients/Types/Responses/ListClientsResponse.cs b/AdminApi.Sdk/Endpoints/Clients/Types/Responses/ListClientsResponse.cs index 94b2fc6099..b42f1d77a8 100644 --- a/AdminApi.Sdk/Endpoints/Clients/Types/Responses/ListClientsResponse.cs +++ b/AdminApi.Sdk/Endpoints/Clients/Types/Responses/ListClientsResponse.cs @@ -2,4 +2,4 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Responses; -public class ListClientsResponse : EnumerableResponseBase; +public class ListClientsResponse : EnumerableResponseBase; diff --git a/AdminApi.Sdk/Endpoints/Identities/IdentitiesEndpoint.cs b/AdminApi.Sdk/Endpoints/Identities/IdentitiesEndpoint.cs index 95f646917f..e271d8e4b1 100644 --- a/AdminApi.Sdk/Endpoints/Identities/IdentitiesEndpoint.cs +++ b/AdminApi.Sdk/Endpoints/Identities/IdentitiesEndpoint.cs @@ -9,23 +9,39 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Identities; public class IdentitiesEndpoint(EndpointClient client) : AdminApiEndpoint(client) { public async Task> CreateIndividualQuota(string address, CreateQuotaForIdentityRequest request) - => await _client.Post($"api/{API_VERSION}/Identities/{address}/Quotas", request); + { + return await _client.Post($"api/{API_VERSION}/Identities/{address}/Quotas", request); + } public async Task> DeleteIndividualQuota(string address, string quotaId) - => await _client.Delete($"api/{API_VERSION}/Identities/{address}/Quotas/{quotaId}"); - - public async Task> ListIdentities() => await _client.Request(HttpMethod.Get, "odata/Identities") - .Authenticate() - .ExecuteOData(); - - public async Task> GetIdentity(string address) => await _client.Get($"api/{API_VERSION}/Identities/{address}"); + { + return await _client.Delete($"api/{API_VERSION}/Identities/{address}/Quotas/{quotaId}"); + } + + public async Task> ListIdentities() + { + return await _client.Request(HttpMethod.Get, "odata/Identities") + .Authenticate() + .ExecuteOData(); + } + + public async Task> GetIdentity(string address) + { + return await _client.Get($"api/{API_VERSION}/Identities/{address}"); + } public async Task> UpdateIdentityTier(string address, UpdateIdentityTierRequest request) - => await _client.Put($"api/{API_VERSION}/Identities/{address}", request); + { + return await _client.Put($"api/{API_VERSION}/Identities/{address}", request); + } public async Task> CreateIdentity(CreateIdentityRequest request) - => await _client.Post($"api/{API_VERSION}", request); + { + return await _client.Post($"api/{API_VERSION}/Identities", request); + } public async Task> StartDeletionProcess(string address) - => await _client.Post($"api/{API_VERSION}/Identities/{address}/DeletionProcesses"); + { + return await _client.Post($"api/{API_VERSION}/Identities/{address}/DeletionProcesses"); + } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/MessageOverviewDTO.cs b/AdminApi.Sdk/Endpoints/Identities/Types/MessageOverviewDTO.cs similarity index 100% rename from AdminApi/test/AdminApi.Tests.Integration/Models/MessageOverviewDTO.cs rename to AdminApi.Sdk/Endpoints/Identities/Types/MessageOverviewDTO.cs diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/MessageRecipientDTO.cs b/AdminApi.Sdk/Endpoints/Identities/Types/MessageRecipientDTO.cs similarity index 100% rename from AdminApi/test/AdminApi.Tests.Integration/Models/MessageRecipientDTO.cs rename to AdminApi.Sdk/Endpoints/Identities/Types/MessageRecipientDTO.cs diff --git a/AdminApi.Sdk/Endpoints/Identities/Types/Requests/CreateIdentityRequest.cs b/AdminApi.Sdk/Endpoints/Identities/Types/Requests/CreateIdentityRequest.cs index e8a2ec2c23..dd22c73827 100644 --- a/AdminApi.Sdk/Endpoints/Identities/Types/Requests/CreateIdentityRequest.cs +++ b/AdminApi.Sdk/Endpoints/Identities/Types/Requests/CreateIdentityRequest.cs @@ -5,7 +5,6 @@ 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; } diff --git a/AdminApi.Sdk/Endpoints/Logs/LogsEndpoint.cs b/AdminApi.Sdk/Endpoints/Logs/LogsEndpoint.cs index 72198d150a..734921ec31 100644 --- a/AdminApi.Sdk/Endpoints/Logs/LogsEndpoint.cs +++ b/AdminApi.Sdk/Endpoints/Logs/LogsEndpoint.cs @@ -6,5 +6,8 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Logs; public class LogsEndpoint(EndpointClient client) : AdminApiEndpoint(client) { - public async Task> CreateLog(LogRequest request) => await _client.Post($"api/{API_VERSION}/Logs", request); + public async Task> CreateLog(LogRequest request) + { + return await _client.Post($"api/{API_VERSION}/Logs", request); + } } diff --git a/AdminApi.Sdk/Endpoints/Messages/MessagesEndpoint.cs b/AdminApi.Sdk/Endpoints/Messages/MessagesEndpoint.cs new file mode 100644 index 0000000000..56a9f8888c --- /dev/null +++ b/AdminApi.Sdk/Endpoints/Messages/MessagesEndpoint.cs @@ -0,0 +1,19 @@ +using Backbone.AdminApi.Sdk.Endpoints.Messages.Types; +using Backbone.AdminApi.Sdk.Endpoints.Messages.Types.Responses; +using Backbone.BuildingBlocks.SDK.Endpoints.Common; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; + +namespace Backbone.AdminApi.Sdk.Endpoints.Messages; + +public class MessagesEndpoint(EndpointClient client) : AdminApiEndpoint(client) +{ + public async Task> GetMessagesWithParticipant(string identityAddress, MessageType type) + { + return await _client + .Request(HttpMethod.Get, $"api/{API_VERSION}/Messages") + .Authenticate() + .AddQueryParameter("participant", identityAddress) + .AddQueryParameter("type", type.Value) + .Execute(); + } +} diff --git a/AdminApi.Sdk/Endpoints/Messages/Types/Message.cs b/AdminApi.Sdk/Endpoints/Messages/Types/Message.cs new file mode 100644 index 0000000000..9410e02c5e --- /dev/null +++ b/AdminApi.Sdk/Endpoints/Messages/Types/Message.cs @@ -0,0 +1,11 @@ +namespace Backbone.AdminApi.Sdk.Endpoints.Messages.Types; + +public class Message +{ + public string MessageId { get; set; } = null!; + public string SenderAddress { get; set; } = null!; + public string SenderDevice { get; set; } = null!; + public DateTime SendDate { get; set; } + public int NumberOfAttachments { get; set; } + public List Recipients { get; set; } = null!; +} diff --git a/AdminApi.Sdk/Endpoints/Messages/Types/MessageRecipient.cs b/AdminApi.Sdk/Endpoints/Messages/Types/MessageRecipient.cs new file mode 100644 index 0000000000..2281e4743d --- /dev/null +++ b/AdminApi.Sdk/Endpoints/Messages/Types/MessageRecipient.cs @@ -0,0 +1,8 @@ +namespace Backbone.AdminApi.Sdk.Endpoints.Messages.Types; + +public class MessageRecipient +{ + public int Id { get; set; } + public string Address { get; set; } = null!; + public string MessageId { get; set; } = null!; +} diff --git a/AdminApi.Sdk/Endpoints/Messages/Types/MessageType.cs b/AdminApi.Sdk/Endpoints/Messages/Types/MessageType.cs new file mode 100644 index 0000000000..93dc364a66 --- /dev/null +++ b/AdminApi.Sdk/Endpoints/Messages/Types/MessageType.cs @@ -0,0 +1,14 @@ +namespace Backbone.AdminApi.Sdk.Endpoints.Messages.Types; + +public record MessageType +{ + public static readonly MessageType INCOMING = new("Incoming"); + public static readonly MessageType OUTGOING = new("Outgoing"); + + public MessageType(string value) + { + Value = value; + } + + public string Value { get; } +} diff --git a/AdminApi.Sdk/Endpoints/Messages/Types/Responses/ListMessagesResponse.cs b/AdminApi.Sdk/Endpoints/Messages/Types/Responses/ListMessagesResponse.cs new file mode 100644 index 0000000000..848158f068 --- /dev/null +++ b/AdminApi.Sdk/Endpoints/Messages/Types/Responses/ListMessagesResponse.cs @@ -0,0 +1,5 @@ +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; + +namespace Backbone.AdminApi.Sdk.Endpoints.Messages.Types.Responses; + +public class ListMessagesResponse : EnumerableResponseBase; diff --git a/AdminApi.Sdk/Endpoints/Metrics/MetricsEndpoint.cs b/AdminApi.Sdk/Endpoints/Metrics/MetricsEndpoint.cs index f75ddaee1e..d92570eafd 100644 --- a/AdminApi.Sdk/Endpoints/Metrics/MetricsEndpoint.cs +++ b/AdminApi.Sdk/Endpoints/Metrics/MetricsEndpoint.cs @@ -6,5 +6,8 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Metrics; public class MetricsEndpoint(EndpointClient client) : AdminApiEndpoint(client) { - public async Task> GetAllMetrics() => await _client.Get($"api/{API_VERSION}/Metrics"); + public async Task> GetAllMetrics() + { + return await _client.Get($"api/{API_VERSION}/Metrics"); + } } diff --git a/AdminApi.Sdk/Endpoints/Relationships/RelationshipsEndpoint.cs b/AdminApi.Sdk/Endpoints/Relationships/RelationshipsEndpoint.cs index da16766b21..e8dd4d348c 100644 --- a/AdminApi.Sdk/Endpoints/Relationships/RelationshipsEndpoint.cs +++ b/AdminApi.Sdk/Endpoints/Relationships/RelationshipsEndpoint.cs @@ -7,12 +7,17 @@ namespace Backbone.AdminApi.Sdk.Endpoints.Relationships; public class RelationshipsEndpoint(EndpointClient client) : AdminApiEndpoint(client) { public async Task> GetAllRelationships(PaginationFilter? pagination = null) - => await _client.Get($"api/{API_VERSION}/Relationships", null, pagination); + { + return await _client.Get($"api/{API_VERSION}/Relationships", null, pagination); + } - public async Task> GetAllRelationships(string participant, PaginationFilter? pagination = null) => await _client - .Request(HttpMethod.Get, $"api/{API_VERSION}/Relationships") - .Authenticate() - .WithPagination(pagination) - .AddQueryParameter("participant", participant) - .Execute(); + public async Task> GetAllRelationships(string participant, PaginationFilter? pagination = null) + { + return await _client + .Request(HttpMethod.Get, $"api/{API_VERSION}/Relationships") + .Authenticate() + .WithPagination(pagination) + .AddQueryParameter("participant", participant) + .Execute(); + } } diff --git a/AdminApi.Sdk/Services/IdentityCreationHelper.cs b/AdminApi.Sdk/Services/IdentityCreationHelper.cs new file mode 100644 index 0000000000..ff19f7c73e --- /dev/null +++ b/AdminApi.Sdk/Services/IdentityCreationHelper.cs @@ -0,0 +1,44 @@ +using Backbone.AdminApi.Sdk.Endpoints.Challenges.Types; +using Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Requests; +using Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Responses; +using Backbone.BuildingBlocks.SDK.Crypto; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; +using Backbone.Crypto; +using Newtonsoft.Json; +using SignatureHelper = Backbone.Crypto.Implementations.SignatureHelper; + +namespace Backbone.AdminApi.Sdk.Services; + +public static class IdentityCreationHelper +{ + public const string DEVICE_PASSWORD = "some-device-password"; + public const string TEST_CLIENT_ID = "test"; + + public static async Task> CreateIdentity(Client client) + { + var signatureHelper = SignatureHelper.CreateEd25519WithRawKeyFormat(); + + var identityKeyPair = signatureHelper.CreateKeyPair(); + + var challenge = await client.Challenges.CreateChallenge(); + var serializedChallenge = JsonConvert.SerializeObject(challenge.Result); + + var challengeSignature = signatureHelper.CreateSignature(identityKeyPair.PrivateKey, ConvertibleString.FromUtf8(serializedChallenge)); + var signedChallenge = new SignedChallenge(serializedChallenge, challengeSignature); + + var createIdentityPayload = new CreateIdentityRequest + { + ClientId = TEST_CLIENT_ID, + IdentityVersion = 1, + SignedChallenge = signedChallenge, + IdentityPublicKey = ConvertibleString.FromUtf8(JsonConvert.SerializeObject(new CryptoSignaturePublicKey + { + alg = CryptoExchangeAlgorithm.ECDH_X25519, + pub = identityKeyPair.PublicKey.Base64Representation + })).BytesRepresentation, + DevicePassword = DEVICE_PASSWORD + }; + + return await client.Identities.CreateIdentity(createIdentityPayload); + } +} diff --git a/AdminApi/src/AdminApi/AdminApi.csproj b/AdminApi/src/AdminApi/AdminApi.csproj index 3a6d8ea53f..2c7a24204e 100644 --- a/AdminApi/src/AdminApi/AdminApi.csproj +++ b/AdminApi/src/AdminApi/AdminApi.csproj @@ -19,7 +19,7 @@ - + @@ -32,11 +32,13 @@ - - + + + + diff --git a/AdminApi/src/AdminApi/Authentication/AnonymousUserContext.cs b/AdminApi/src/AdminApi/Authentication/AnonymousUserContext.cs new file mode 100644 index 0000000000..fb44f585b1 --- /dev/null +++ b/AdminApi/src/AdminApi/Authentication/AnonymousUserContext.cs @@ -0,0 +1,57 @@ +using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; +using Backbone.DevelopmentKit.Identity.ValueObjects; + +namespace Backbone.AdminApi.Authentication; + +public class AnonymousUserContext : IUserContext +{ + public IdentityAddress GetAddress() + { + throw new NotSupportedException(); + } + + public IdentityAddress? GetAddressOrNull() + { + return null; + } + + public DeviceId GetDeviceId() + { + throw new NotSupportedException(); + } + + public DeviceId? GetDeviceIdOrNull() + { + return null; + } + + public string GetUserId() + { + throw new NotSupportedException(); + } + + public string? GetUserIdOrNull() + { + throw new NotSupportedException(); + } + + public string GetUsername() + { + throw new NotSupportedException(); + } + + public string? GetUsernameOrNull() + { + throw new NotSupportedException(); + } + + public IEnumerable GetRoles() + { + throw new NotSupportedException(); + } + + public SubscriptionPlan GetSubscriptionPlan() + { + throw new NotSupportedException(); + } +} diff --git a/AdminApi/src/AdminApi/Configuration/AdminConfiguration.cs b/AdminApi/src/AdminApi/Configuration/AdminConfiguration.cs index f25c050c17..2a2d8e5a8a 100644 --- a/AdminApi/src/AdminApi/Configuration/AdminConfiguration.cs +++ b/AdminApi/src/AdminApi/Configuration/AdminConfiguration.cs @@ -40,16 +40,19 @@ public class AdminInfrastructureConfiguration { [Required] public EventBusConfiguration EventBus { get; set; } = new(); + public SqlDatabaseConfiguration SqlDatabase { get; set; } = new(); } public class ModulesConfiguration { - [Required] public DevicesConfiguration Devices { get; set; } = new(); [Required] public QuotasConfiguration Quotas { get; set; } = new(); + + [Required] + public ChallengesConfiguration Challenges { get; set; } = new(); } } diff --git a/AdminApi/src/AdminApi/Configuration/ChallengesConfiguration.cs b/AdminApi/src/AdminApi/Configuration/ChallengesConfiguration.cs new file mode 100644 index 0000000000..6bb08c3d06 --- /dev/null +++ b/AdminApi/src/AdminApi/Configuration/ChallengesConfiguration.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; +using Backbone.Modules.Challenges.Application; + +namespace Backbone.AdminApi.Configuration; + +public class ChallengesConfiguration +{ + [Required] + public ApplicationOptions Application { get; set; } = new(); + + [Required] + public InfrastructureConfiguration Infrastructure { get; set; } = new(); + + public class InfrastructureConfiguration + { + [Required] + public SqlDatabaseConfiguration SqlDatabase { get; set; } = new(); + + public class SqlDatabaseConfiguration + { + [Required] + [MinLength(1)] + [RegularExpression("SqlServer|Postgres")] + public string Provider { get; set; } = string.Empty; + + [Required] + [MinLength(1)] + public string ConnectionString { get; set; } = string.Empty; + } + } +} diff --git a/AdminApi/src/AdminApi/Controllers/ChallengesController.cs b/AdminApi/src/AdminApi/Controllers/ChallengesController.cs new file mode 100644 index 0000000000..7f72513a30 --- /dev/null +++ b/AdminApi/src/AdminApi/Controllers/ChallengesController.cs @@ -0,0 +1,28 @@ +using Backbone.BuildingBlocks.API; +using Backbone.BuildingBlocks.API.Mvc; +using Backbone.BuildingBlocks.API.Mvc.ControllerAttributes; +using Backbone.Modules.Challenges.Application.Challenges.Commands.CreateChallenge; +using Backbone.Modules.Challenges.Application.Challenges.DTOs; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Backbone.AdminApi.Controllers; + +[Route("api/v1/[controller]")] +[Authorize("ApiKey")] +public class ChallengesController : ApiControllerBase +{ + public ChallengesController(IMediator mediator) : base(mediator) + { + } + + [HttpPost] + [ProducesResponseType(typeof(HttpResponseEnvelopeResult), StatusCodes.Status201Created)] + [ProducesError(StatusCodes.Status400BadRequest)] + public async Task Create(CancellationToken cancellationToken) + { + var response = await _mediator.Send(new CreateChallengeCommand(), cancellationToken); + return CreatedAtAction(nameof(Create), new { id = response.Id }, response); + } +} diff --git a/AdminApi/src/AdminApi/Controllers/IdentitiesController.cs b/AdminApi/src/AdminApi/Controllers/IdentitiesController.cs index b15e38e8a4..727a4d2ddb 100644 --- a/AdminApi/src/AdminApi/Controllers/IdentitiesController.cs +++ b/AdminApi/src/AdminApi/Controllers/IdentitiesController.cs @@ -78,7 +78,7 @@ public async Task GetIdentityByAddress([FromRoute] string address [ProducesError(StatusCodes.Status404NotFound)] public async Task UpdateIdentity([FromRoute] string identityAddress, [FromBody] UpdateIdentityRequest request, CancellationToken cancellationToken) { - var command = new UpdateIdentityCommand() { Address = identityAddress, TierId = request.TierId }; + var command = new UpdateIdentityCommand { Address = identityAddress, TierId = request.TierId }; await _mediator.Send(command, cancellationToken); return NoContent(); } @@ -96,10 +96,9 @@ public async Task CreateIdentity(CreateIdentityRequest request, C IdentityVersion = request.IdentityVersion, SignedChallenge = new SignedChallengeDTO { - Challenge = "-", - Signature = [0] - }, - ShouldValidateChallenge = false + Challenge = request.SignedChallenge.Challenge, + Signature = request.SignedChallenge.Signature + } }; var response = await _mediator.Send(command, cancellationToken); @@ -173,8 +172,8 @@ public class GetIdentityResponse 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; } + public required SignedChallengeDTO SignedChallenge { get; set; } } diff --git a/AdminApi/src/AdminApi/Dockerfile b/AdminApi/src/AdminApi/Dockerfile index b7df73fae9..7757496bc3 100644 --- a/AdminApi/src/AdminApi/Dockerfile +++ b/AdminApi/src/AdminApi/Dockerfile @@ -78,6 +78,9 @@ COPY ["Modules/Devices/src/Devices.Application/Devices.Application.csproj", "Mod COPY ["BuildingBlocks/src/BuildingBlocks.Application/BuildingBlocks.Application.csproj", "BuildingBlocks/src/BuildingBlocks.Application/"] COPY ["Common/src/Common.Infrastructure/Common.Infrastructure.csproj", "Common/src/Common.Infrastructure/"] COPY ["BuildingBlocks/src/Crypto/Crypto.csproj", "BuildingBlocks/src/Crypto/"] +COPY ["Modules/Challenges/src/Challenges.Application/Challenges.Application.csproj", "Modules/Challenges/src/Challenges.Application/"] +COPY ["Modules/Challenges/src/Challenges.Domain/Challenges.Domain.csproj", "Modules/Challenges/src/Challenges.Domain/"] +COPY ["Modules/Challenges/src/Challenges.Infrastructure/Challenges.Infrastructure.csproj", "Modules/Challenges/src/Challenges.Infrastructure/"] COPY ["Infrastructure/Infrastructure.csproj", "Infrastructure/"] COPY ["Modules/Quotas/src/Quotas.Application/Quotas.Application.csproj", "Modules/Quotas/src/Quotas.Application/"] COPY ["Modules/Quotas/src/Quotas.Domain/Quotas.Domain.csproj", "Modules/Quotas/src/Quotas.Domain/"] diff --git a/AdminApi/src/AdminApi/Extensions/ChallengesServiceCollectionExtensions.cs b/AdminApi/src/AdminApi/Extensions/ChallengesServiceCollectionExtensions.cs new file mode 100644 index 0000000000..cc1c29a492 --- /dev/null +++ b/AdminApi/src/AdminApi/Extensions/ChallengesServiceCollectionExtensions.cs @@ -0,0 +1,22 @@ +using Backbone.AdminApi.Configuration; +using Backbone.Modules.Challenges.Application.Extensions; +using Backbone.Modules.Challenges.Infrastructure.Persistence; + +namespace Backbone.AdminApi.Extensions; + +public static class ChallengesServiceCollectionExtensions +{ + public static IServiceCollection AddChallenges(this IServiceCollection services, + ChallengesConfiguration configuration) + { + services.AddApplication(); + + services.AddDatabase(options => + { + options.DbConnectionString = configuration.Infrastructure.SqlDatabase.ConnectionString; + options.Provider = configuration.Infrastructure.SqlDatabase.Provider; + }); + + return services; + } +} diff --git a/AdminApi/src/AdminApi/Extensions/IServiceCollectionExtensions.cs b/AdminApi/src/AdminApi/Extensions/IServiceCollectionExtensions.cs index 8786b31b93..2e4278afe9 100644 --- a/AdminApi/src/AdminApi/Extensions/IServiceCollectionExtensions.cs +++ b/AdminApi/src/AdminApi/Extensions/IServiceCollectionExtensions.cs @@ -6,6 +6,7 @@ using Backbone.AdminApi.Infrastructure.DTOs; using Backbone.BuildingBlocks.API; using Backbone.BuildingBlocks.API.Mvc.ExceptionFilters; +using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.UserContext; using Backbone.Modules.Devices.Application.Devices.Commands.RegisterDevice; using Backbone.Modules.Devices.Application.Devices.DTOs; using FluentValidation; @@ -20,10 +21,7 @@ public static class IServiceCollectionExtensions { public static IServiceCollection AddCustomFluentValidation(this IServiceCollection services) { - services.AddFluentValidationAutoValidation(config => - { - config.DisableDataAnnotationsValidation = true; - }); + services.AddFluentValidationAutoValidation(config => { config.DisableDataAnnotationsValidation = true; }); ValidatorOptions.Global.DisplayNameResolver = (_, member, _) => member != null ? char.ToLowerInvariant(member.Name[0]) + member.Name[1..] : null; @@ -136,11 +134,11 @@ public static IServiceCollection AddCustomAspNetCore(this IServiceCollection ser services.AddHealthChecks().AddSqlServer( connectionString, name: moduleName - ); + ); break; case "Postgres": services.AddHealthChecks().AddNpgSql( - connectionString: connectionString, + connectionString, name: moduleName); break; default: @@ -150,6 +148,8 @@ public static IServiceCollection AddCustomAspNetCore(this IServiceCollection ser services.AddHttpContextAccessor(); + services.AddTransient(); + return services; } diff --git a/AdminApi/src/AdminApi/Program.cs b/AdminApi/src/AdminApi/Program.cs index b77bb14770..8183099318 100644 --- a/AdminApi/src/AdminApi/Program.cs +++ b/AdminApi/src/AdminApi/Program.cs @@ -108,6 +108,7 @@ static void ConfigureServices(IServiceCollection services, IConfiguration config .AddDatabase(parsedConfiguration.Infrastructure.SqlDatabase) .AddDevices(parsedConfiguration.Modules.Devices) .AddQuotas(parsedConfiguration.Modules.Quotas) + .AddChallenges(parsedConfiguration.Modules.Challenges) .AddHealthChecks(); if (parsedConfiguration.SwaggerUi.Enabled) diff --git a/AdminApi/src/AdminApi/appsettings.override.json b/AdminApi/src/AdminApi/appsettings.override.json index ce0079fd28..8ab2af112e 100644 --- a/AdminApi/src/AdminApi/appsettings.override.json +++ b/AdminApi/src/AdminApi/appsettings.override.json @@ -30,6 +30,21 @@ } }, "Modules": { + "Challenges": { + "Application": { + "Pagination": { + "DefaultPageSize": 50, + "MaxPageSize": 200 + } + }, + "Infrastructure": { + "SqlDatabase": { + "Provider": "Postgres", + "ConnectionString": "User ID=challenges;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres + //"ConnectionString": "Server=localhost;Database=enmeshed;User Id=challenges;Password=Passw0rd;TrustServerCertificate=True" // sqlserver + } + } + }, "Devices": { "Application": { "Pagination": { diff --git a/AdminApi/test/AdminApi.Tests.Integration/API/BaseApi.cs b/AdminApi/test/AdminApi.Tests.Integration/API/BaseApi.cs deleted file mode 100644 index e48eb4e85b..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/API/BaseApi.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System.Net; -using System.Net.Http.Headers; -using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.AdminApi.Tests.Integration.Models; -using FluentValidation.TestHelper; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using HttpResponse = Backbone.AdminApi.Tests.Integration.Models.HttpResponse; - -namespace Backbone.AdminApi.Tests.Integration.API; - -internal class BaseApi -{ - protected const string ROUTE_PREFIX = "/api/v1"; - protected const string ODATA_ROUTE_PREFIX = "/odata"; - private readonly HttpClient _httpClient; - private const string XSRF_TOKEN_HEADER_NAME = "X-XSRF-TOKEN"; - private const string XSRF_TOKEN_COOKIE_NAME = "X-XSRF-COOKIE"; - private string _xsrfToken = string.Empty; - private string _xsrfCookie = string.Empty; - - protected BaseApi(IOptions httpConfiguration, HttpClientFactory factory) - { - _httpClient = factory.CreateClient(); - _httpClient.DefaultRequestHeaders.Add("X-API-KEY", httpConfiguration.Value.ApiKey); - - LoadAndAddXsrfHeaders(); - - ServicePointManager.ServerCertificateValidationCallback += (_, _, _, _) => true; - } - - private void LoadAndAddXsrfHeaders() - { - Task.Run(LoadXsrfTokensAsync).Wait(); - _httpClient.DefaultRequestHeaders.Add(XSRF_TOKEN_HEADER_NAME, _xsrfToken); - _httpClient.DefaultRequestHeaders.Add("Cookie", $"{XSRF_TOKEN_COOKIE_NAME}={_xsrfCookie}"); - } - - private async Task LoadXsrfTokensAsync() - { - var request = new HttpRequestMessage(HttpMethod.Get, ROUTE_PREFIX + "/xsrf"); - request.Headers.Add("Accept", "text/plain"); - - var httpResponse = await _httpClient.SendAsync(request); - - if (httpResponse.Headers.TryGetValues("Set-Cookie", out var cookies)) - { - _xsrfToken = await httpResponse.Content.ReadAsStringAsync(); - _xsrfCookie = cookies.Select(it => - { - var rawCookieHeader = it.Split('=', 2); - return new Models.Cookie { Name = rawCookieHeader[0], Value = rawCookieHeader[1] }; - }).First(c => c.Name == XSRF_TOKEN_COOKIE_NAME).Value; - } - else - { - throw new ValidationTestException("Could not load XSRF tokens."); - } - } - - protected async Task> GetOData(string endpoint) - { - return await ExecuteODataRequest(HttpMethod.Get, endpoint); - } - - protected async Task> Get(string endpoint, RequestConfiguration requestConfiguration) - { - return await ExecuteRequest(HttpMethod.Get, endpoint, requestConfiguration); - } - - protected async Task> Post(string endpoint, RequestConfiguration requestConfiguration) - { - return await ExecuteRequest(HttpMethod.Post, endpoint, requestConfiguration); - } - - protected async Task Post(string endpoint, RequestConfiguration requestConfiguration) - { - return await ExecuteRequest(HttpMethod.Post, endpoint, requestConfiguration); - } - - protected async Task Delete(string endpoint, RequestConfiguration requestConfiguration) - { - return await ExecuteRequest(HttpMethod.Delete, endpoint, requestConfiguration); - } - - protected async Task> Patch(string endpoint, RequestConfiguration requestConfiguration) - { - return await ExecuteRequest(HttpMethod.Patch, endpoint, requestConfiguration); - } - - protected async Task> Put(string endpoint, RequestConfiguration requestConfiguration) - { - return await ExecuteRequest(HttpMethod.Put, endpoint, requestConfiguration); - } - - private async Task ExecuteRequest(HttpMethod method, string endpoint, RequestConfiguration requestConfiguration) - { - var request = new HttpRequestMessage(method, ROUTE_PREFIX + endpoint); - - if (string.IsNullOrEmpty(requestConfiguration.ContentType)) - throw new ArgumentNullException(nameof(requestConfiguration.ContentType)); - - if (!string.IsNullOrEmpty(requestConfiguration.Content)) - request.Content = new StringContent(requestConfiguration.Content, MediaTypeHeaderValue.Parse(requestConfiguration.ContentType)); - - if (!string.IsNullOrEmpty(requestConfiguration.AcceptHeader)) - request.Headers.Add("Accept", requestConfiguration.AcceptHeader); - - var httpResponse = await _httpClient.SendAsync(request); - - var response = new HttpResponse - { - Content = JsonConvert.DeserializeObject(await httpResponse.Content.ReadAsStringAsync())!, - ContentType = httpResponse.Content.Headers.ContentType?.MediaType, - IsSuccessStatusCode = httpResponse.IsSuccessStatusCode, - StatusCode = httpResponse.StatusCode - }; - - return response; - } - - private async Task> ExecuteODataRequest(HttpMethod method, string endpoint) - { - var request = new HttpRequestMessage(method, ODATA_ROUTE_PREFIX + endpoint); - - var httpResponse = await _httpClient.SendAsync(request); - var responseRawContent = await httpResponse.Content.ReadAsStringAsync(); - - var responseData = JsonConvert.DeserializeObject>(responseRawContent); - - var response = new ODataResponse - { - IsSuccessStatusCode = httpResponse.IsSuccessStatusCode, - StatusCode = httpResponse.StatusCode, - Content = responseData!, - ContentType = httpResponse.Content.Headers.ContentType?.MediaType, - RawContent = responseRawContent - }; - - return response; - } - - private async Task> ExecuteRequest(HttpMethod method, string endpoint, RequestConfiguration requestConfiguration) - { - var request = new HttpRequestMessage(method, ROUTE_PREFIX + endpoint); - - if (string.IsNullOrEmpty(requestConfiguration.ContentType)) - throw new ArgumentNullException(nameof(requestConfiguration.ContentType)); - - if (!string.IsNullOrEmpty(requestConfiguration.Content)) - request.Content = new StringContent(requestConfiguration.Content, MediaTypeHeaderValue.Parse(requestConfiguration.ContentType)); - - if (!string.IsNullOrEmpty(requestConfiguration.AcceptHeader)) - request.Headers.Add("Accept", requestConfiguration.AcceptHeader); - - var httpResponse = await _httpClient.SendAsync(request); - var responseRawContent = await httpResponse.Content.ReadAsStringAsync(); - - var responseData = JsonConvert.DeserializeObject>(responseRawContent); - - var response = new HttpResponse - { - IsSuccessStatusCode = httpResponse.IsSuccessStatusCode, - StatusCode = httpResponse.StatusCode, - Content = responseData!, - ContentType = httpResponse.Content.Headers.ContentType?.MediaType, - RawContent = responseRawContent - }; - - return response; - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/API/ClientsApi.cs b/AdminApi/test/AdminApi.Tests.Integration/API/ClientsApi.cs deleted file mode 100644 index 83adb2bc5c..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/API/ClientsApi.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.AdminApi.Tests.Integration.Models; -using Microsoft.Extensions.Options; - -namespace Backbone.AdminApi.Tests.Integration.API; -internal class ClientsApi : BaseApi -{ - public ClientsApi(IOptions httpConfiguration, HttpClientFactory factory) : base(httpConfiguration, factory) { } - - internal async Task>> GetAllClients(RequestConfiguration requestConfiguration) - { - return await Get>("/Clients", requestConfiguration); - } - - internal async Task> GetClient(string clientId, RequestConfiguration requestConfiguration) - { - return await Get($"/Clients/{clientId}", requestConfiguration); - } - - internal async Task DeleteClient(string clientId, RequestConfiguration requestConfiguration) - { - return await Delete($"/Clients/{clientId}", requestConfiguration); - } - - internal async Task> CreateClient(RequestConfiguration requestConfiguration) - { - return await Post("/Clients", requestConfiguration); - } - - internal async Task> ChangeClientSecret(string clientId, RequestConfiguration requestConfiguration) - { - return await Patch($"/Clients/{clientId}/ChangeSecret", requestConfiguration); - } - - internal async Task> UpdateClient(string clientId, RequestConfiguration requestConfiguration) - { - return await Put($"/Clients/{clientId}", requestConfiguration); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/API/IdentitiesApi.cs b/AdminApi/test/AdminApi.Tests.Integration/API/IdentitiesApi.cs deleted file mode 100644 index 069be9a2e8..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/API/IdentitiesApi.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.AdminApi.Tests.Integration.Models; -using Microsoft.Extensions.Options; - -namespace Backbone.AdminApi.Tests.Integration.API; - -internal class IdentitiesApi : BaseApi -{ - public IdentitiesApi(IOptions httpConfiguration, HttpClientFactory factory) : base(httpConfiguration, factory) { } - - internal async Task> GetIdentityByAddress(RequestConfiguration requestConfiguration, string identityAddress) - { - return await Get($"/Identities/{identityAddress}", requestConfiguration); - } - - internal async Task> CreateIndividualQuota(RequestConfiguration requestConfiguration, string identityAddress) - { - return await Post($"/Identities/{identityAddress}/Quotas", requestConfiguration); - } - - internal async Task DeleteIndividualQuota(string identityAddress, string individualQuotaId, RequestConfiguration requestConfiguration) - { - return await Delete($"/Identities/{identityAddress}/Quotas/{individualQuotaId}", requestConfiguration); - } - - internal async Task>?> GetIdentityOverviews() - { - return await GetOData>("/Identities?$expand=Tier"); - } - - internal async Task> StartDeletionProcess(string identityAddress, RequestConfiguration requestConfiguration) - { - return await Post($"/Identities/{identityAddress}/DeletionProcesses", requestConfiguration); - } - - internal async Task> CreateIdentity(RequestConfiguration requestConfiguration) - { - return await Post("/Identities", requestConfiguration); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/API/LogsApi.cs b/AdminApi/test/AdminApi.Tests.Integration/API/LogsApi.cs deleted file mode 100644 index 1903cc3700..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/API/LogsApi.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.AdminApi.Tests.Integration.Models; -using Microsoft.Extensions.Options; - -namespace Backbone.AdminApi.Tests.Integration.API; -internal class LogsApi : BaseApi -{ - public LogsApi(IOptions httpConfiguration, HttpClientFactory factory) : base(httpConfiguration, factory) { } - - internal async Task CreateLog(RequestConfiguration requestConfiguration) - { - return await Post("/Logs", requestConfiguration); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/API/MessagesApi.cs b/AdminApi/test/AdminApi.Tests.Integration/API/MessagesApi.cs deleted file mode 100644 index e90bc77f3f..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/API/MessagesApi.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.AdminApi.Tests.Integration.Models; -using Microsoft.Extensions.Options; - -namespace Backbone.AdminApi.Tests.Integration.API; -internal class MessagesApi : BaseApi -{ - public MessagesApi(IOptions httpConfiguration, HttpClientFactory factory) : base(httpConfiguration, factory) { } - - internal async Task>> GetMessagesWithParticipant(string participant, string type, RequestConfiguration requestConfiguration) - { - return await Get>($"/Messages?&participant={participant}&type={type}", requestConfiguration); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/API/MetricsApi.cs b/AdminApi/test/AdminApi.Tests.Integration/API/MetricsApi.cs deleted file mode 100644 index ba633c10ff..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/API/MetricsApi.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.AdminApi.Tests.Integration.Models; -using Microsoft.Extensions.Options; - -namespace Backbone.AdminApi.Tests.Integration.API; -internal class MetricsApi : BaseApi -{ - public MetricsApi(IOptions httpConfiguration, HttpClientFactory factory) : base(httpConfiguration, factory) { } - - internal async Task>> GetAllMetrics(RequestConfiguration requestConfiguration) - { - return await Get>("/Metrics", requestConfiguration); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/API/TiersApi.cs b/AdminApi/test/AdminApi.Tests.Integration/API/TiersApi.cs deleted file mode 100644 index c39ff6612e..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/API/TiersApi.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.AdminApi.Tests.Integration.Models; -using Microsoft.Extensions.Options; - -namespace Backbone.AdminApi.Tests.Integration.API; - -internal class TiersApi : BaseApi -{ - public TiersApi(IOptions httpConfiguration, HttpClientFactory factory) : base(httpConfiguration, factory) { } - - internal async Task>> GetTiers(RequestConfiguration requestConfiguration) - { - return await Get>("/Tiers", requestConfiguration); - } - - internal async Task> GetTierById(RequestConfiguration requestConfiguration, string tierId) - { - return await Get($"/Tiers/{tierId}", requestConfiguration); - } - - internal async Task> CreateTierQuota(RequestConfiguration requestConfiguration, string tierId) - { - return await Post($"/Tiers/{tierId}/Quotas", requestConfiguration); - } - - internal async Task DeleteTierQuota(string tierId, string tierQuotaDefinitionId, RequestConfiguration requestConfiguration) - { - return await Delete($"/Tiers/{tierId}/Quotas/{tierQuotaDefinitionId}", requestConfiguration); - } - - internal async Task> CreateTier(RequestConfiguration requestConfiguration) - { - return await Post("/Tiers", requestConfiguration); - } - - internal async Task DeleteTier(RequestConfiguration requestConfiguration, string tierId) - { - return await Delete($"/Tiers/{tierId}", requestConfiguration); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/AdminApi.Tests.Integration.csproj b/AdminApi/test/AdminApi.Tests.Integration/AdminApi.Tests.Integration.csproj index bc45787048..b12def24c8 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/AdminApi.Tests.Integration.csproj +++ b/AdminApi/test/AdminApi.Tests.Integration/AdminApi.Tests.Integration.csproj @@ -27,6 +27,7 @@ + diff --git a/AdminApi/test/AdminApi.Tests.Integration/Assertions/ApiResponseAssertions.cs b/AdminApi/test/AdminApi.Tests.Integration/Assertions/ApiResponseAssertions.cs new file mode 100644 index 0000000000..03ade75aa1 --- /dev/null +++ b/AdminApi/test/AdminApi.Tests.Integration/Assertions/ApiResponseAssertions.cs @@ -0,0 +1,38 @@ +using Backbone.AdminApi.Tests.Integration.Validators; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; +using Newtonsoft.Json; + +namespace Backbone.AdminApi.Tests.Integration.Assertions; + +public class ApiResponseAssertions : ReferenceTypeAssertions, ApiResponseAssertions> +{ + public ApiResponseAssertions(ApiResponse instance) : base(instance) + { + } + + protected override string Identifier => "ApiResponse"; + + public void ComplyWithSchema(string because = "", params object[] becauseArgs) + { + IList errors = []; + Execute.Assertion + .BecauseOf(because, becauseArgs) + .Given(() => Subject.Result!) + .ForCondition(result => result != null) + .FailWith("You can't validate the JSON schema of a NULL object") + .Then + .ForCondition(result => JsonValidators.ValidateJsonSchema(JsonConvert.SerializeObject(result), out errors)) + .FailWith($"Response content does not comply with the {typeof(T).FullName} schema: {string.Join(", ", errors)}"); + } + + public void BeASuccess(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .Given(() => Subject) + .ForCondition(result => result.IsSuccess) + .FailWith($"Expected response to be successful. Failed with error code: '{Subject.Error?.Code}'. Error Message: '{Subject.Error?.Message}'"); + } +} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Configuration/HttpClientOptions.cs b/AdminApi/test/AdminApi.Tests.Integration/Configuration/HttpClientOptions.cs index fe10d38f2c..dd1413c671 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/Configuration/HttpClientOptions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/Configuration/HttpClientOptions.cs @@ -5,8 +5,5 @@ namespace Backbone.AdminApi.Tests.Integration.Configuration; public class HttpClientOptions { [Required] - public string BaseUrl { get; set; } = ""; - - [Required] - public string ApiKey { get; set; } = ""; + public string ApiKey { get; set; } = string.Empty; } diff --git a/AdminApi/test/AdminApi.Tests.Integration/Extensions/ApiResponseExtensions.cs b/AdminApi/test/AdminApi.Tests.Integration/Extensions/ApiResponseExtensions.cs new file mode 100644 index 0000000000..7c2fe040ba --- /dev/null +++ b/AdminApi/test/AdminApi.Tests.Integration/Extensions/ApiResponseExtensions.cs @@ -0,0 +1,12 @@ +using Backbone.AdminApi.Tests.Integration.Assertions; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; + +namespace Backbone.AdminApi.Tests.Integration.Extensions; + +public static class ApiResponseExtensions +{ + public static ApiResponseAssertions Should(this ApiResponse instance) + { + return new ApiResponseAssertions(instance); + } +} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Extensions/HttpResponseExtensions.cs b/AdminApi/test/AdminApi.Tests.Integration/Extensions/HttpResponseExtensions.cs deleted file mode 100644 index 44f4e3380e..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Extensions/HttpResponseExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Models; - -namespace Backbone.AdminApi.Tests.Integration.Extensions; - -public static class HttpResponseExtensions -{ - public static void AssertHasValue(this HttpResponse response) - { - response.Should().NotBeNull(); - } - - public static void AssertStatusCodeIsSuccess(this HttpResponse response) - { - response.IsSuccessStatusCode.Should().BeTrue(); - } - - public static void AssertContentTypeIs(this HttpResponse response, string contentType) - { - response.ContentType.Should().Be(contentType); - } - - public static void AssertContentCompliesWithSchema(this HttpResponse response) - { - // JsonValidators.ValidateJsonSchema>(response.RawContent!, out var errors) - // .Should().BeTrue($"Response content does not comply with the {typeof(T).FullName} schema: {string.Join(", ", errors)}"); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Extensions/ODataResponseExtensions.cs b/AdminApi/test/AdminApi.Tests.Integration/Extensions/ODataResponseExtensions.cs deleted file mode 100644 index ceb3e27e57..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Extensions/ODataResponseExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Backbone.AdminApi.Tests.Integration.Models; - -namespace Backbone.AdminApi.Tests.Integration.Extensions; - -public static class ODataResponseExtensions -{ - public static void AssertHasValue(this ODataResponse response) - { - response.Should().NotBeNull(); - } - - public static void AssertStatusCodeIsSuccess(this ODataResponse response) - { - response.IsSuccessStatusCode.Should().BeTrue(); - } - - public static void AssertContentTypeIs(this ODataResponse response, string contentType) - { - response.ContentType.Should().Be(contentType); - } - - public static void AssertContentCompliesWithSchema(this ODataResponse response) - { - // JsonValidators.ValidateJsonSchema>(response.RawContent!, out var errors) - // .Should().BeTrue($"Response content does not comply with the {typeof(T).FullName} schema: {string.Join(", ", errors)}"); - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/HttpClientFactory.cs b/AdminApi/test/AdminApi.Tests.Integration/HttpClientFactory.cs index 6a14830193..67ea07709f 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/HttpClientFactory.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/HttpClientFactory.cs @@ -14,7 +14,8 @@ internal HttpClientFactory(CustomWebApplicationFactory factory) internal HttpClient CreateClient() { var baseAddress = Environment.GetEnvironmentVariable("ADMIN_API_BASE_ADDRESS"); - return baseAddress.IsNullOrEmpty() ? _factory.CreateClient() : new HttpClient() { BaseAddress = new Uri(baseAddress) }; + return baseAddress.IsNullOrEmpty() + ? _factory.CreateClient() + : new HttpClient { BaseAddress = new Uri(baseAddress) }; } } - diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/ChangeClientSecretRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/ChangeClientSecretRequest.cs deleted file mode 100644 index 91318905b5..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/ChangeClientSecretRequest.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class ChangeClientSecretRequest -{ - public required string NewSecret { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/ChangeClientSecretResponse.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/ChangeClientSecretResponse.cs deleted file mode 100644 index 6ad1825d25..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/ChangeClientSecretResponse.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class ChangeClientSecretResponse -{ - 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; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/ClientDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/ClientDTO.cs deleted file mode 100644 index c9d88fc345..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/ClientDTO.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class ClientDTO -{ - 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; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/ClientOverviewDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/ClientOverviewDTO.cs deleted file mode 100644 index 9b23439c75..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/ClientOverviewDTO.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class ClientOverviewDTO -{ - public required string ClientId { get; set; } - public required string DisplayName { get; set; } - public required TierDTO DefaultTier { get; set; } - public required DateTime CreatedAt { get; set; } - public int? MaxIdentities { get; set; } - public required int NumberOfIdentities { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateClientRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/CreateClientRequest.cs deleted file mode 100644 index 10ab8578dd..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateClientRequest.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class CreateClientRequest -{ - 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 int? MaxIdentities { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateClientResponse.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/CreateClientResponse.cs deleted file mode 100644 index 04f8861c7b..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateClientResponse.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class CreateClientResponse -{ - public required string ClientId { get; set; } - public required string DisplayName { get; set; } - public required string ClientSecret { get; set; } - public required DateTime CreatedAt { get; set; } - public int? MaxIdentities { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIdentityRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIdentityRequest.cs deleted file mode 100644 index 3088d3f958..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIdentityRequest.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class CreateIdentityRequest -{ - public required string ClientId { get; set; } - public required string ClientSecret { get; set; } - public required string IdentityPublicKey { get; set; } - public required string DevicePassword { get; set; } - public required byte IdentityVersion { get; set; } - public required CreateIdentityRequestSignedChallenge SignedChallenge { get; set; } -} - -public class CreateIdentityRequestSignedChallenge -{ - public required string Challenge { get; set; } - public required string Signature { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIdentityResponse.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIdentityResponse.cs deleted file mode 100644 index 84a22bea64..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIdentityResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -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; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIndividualQuotaRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIndividualQuotaRequest.cs deleted file mode 100644 index ce510615e7..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateIndividualQuotaRequest.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class CreateIndividualQuotaRequest -{ - public required string MetricKey { get; set; } - public required int Max { get; set; } - public required string Period { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateTierQuotaRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/CreateTierQuotaRequest.cs deleted file mode 100644 index bc8569a441..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateTierQuotaRequest.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class CreateTierQuotaRequest -{ - public required string MetricKey { get; set; } - public required int Max { get; set; } - public required string Period { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateTierRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/CreateTierRequest.cs deleted file mode 100644 index 3a459537a1..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/CreateTierRequest.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class CreateTierRequest -{ - public required string Name { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/Error.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/Error.cs deleted file mode 100644 index 8b0038a51a..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/Error.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class Error -{ - public required string Id { get; set; } - public required string Code { get; set; } - public required string Message { get; set; } - public required string Docs { get; set; } - public required DateTime Time { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/HttpResponse.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/HttpResponse.cs deleted file mode 100644 index 440f7fd003..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/HttpResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Net; - -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class HttpResponse -{ - public required ResponseContent Content { get; set; } - public required HttpStatusCode StatusCode { get; set; } - public required bool IsSuccessStatusCode { get; set; } - public string? ContentType { get; set; } - public string? RawContent { get; set; } -} - -public class HttpResponse -{ - public required HttpStatusCode StatusCode { get; set; } - public required bool IsSuccessStatusCode { get; set; } - public string? ContentType { get; set; } - public required ErrorResponseContent? Content { get; set; } -} - -public class Cookie -{ - public required string Name { get; init; } - public required string Value { get; init; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/IdentityOverviewDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/IdentityOverviewDTO.cs deleted file mode 100644 index b241009a84..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/IdentityOverviewDTO.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class IdentityOverviewDTO -{ - public required string Address { get; set; } - public required DateTime CreatedAt { get; set; } - public DateTime? LastLoginAt { get; set; } - public string? CreatedWithClient { get; set; } - public int? DatawalletVersion { get; set; } - public required byte IdentityVersion { get; set; } - public required TierDTO Tier { get; set; } - public int? NumberOfDevices { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/IdentitySummaryDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/IdentitySummaryDTO.cs deleted file mode 100644 index 02cae24636..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/IdentitySummaryDTO.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class IdentitySummaryDTO -{ - public required string Address { get; set; } - public required string ClientId { get; set; } - public required string PublicKey { get; set; } - public required DateTime CreatedAt { get; set; } - public required byte IdentityVersion { get; set; } - public required int NumberOfDevices { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/IndividualQuotaDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/IndividualQuotaDTO.cs deleted file mode 100644 index 0f94074c08..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/IndividualQuotaDTO.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class IndividualQuotaDTO -{ - public required string Id { get; set; } - public required MetricDTO Metric { get; set; } - public required int Max { get; set; } - public required string Period { get; set; } -} - diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/LogRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/LogRequest.cs deleted file mode 100644 index 585a5301a6..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/LogRequest.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class LogRequest -{ - public required LogLevel LogLevel { get; set; } - public required string Category { get; set; } - public required string MessageTemplate { get; set; } - public object[]? Arguments { get; set; } -} - -public enum LogLevel -{ - Trace, - Debug, - Information, - Log, - Warning, - Error, - Critical -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/MetricDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/MetricDTO.cs deleted file mode 100644 index c1af6086cd..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/MetricDTO.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class MetricDTO -{ - public required string Key { get; set; } - public required string DisplayName { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/ODataResponse.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/ODataResponse.cs deleted file mode 100644 index 053c919d21..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/ODataResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Net; - -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class ODataResponse -{ - public required ODataResponseContent Content { get; set; } - public required HttpStatusCode StatusCode { get; set; } - public required bool IsSuccessStatusCode { get; set; } - public string? ContentType { get; set; } - public string? RawContent { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/ODataResponseContent.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/ODataResponseContent.cs deleted file mode 100644 index 5502edc05c..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/ODataResponseContent.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class ODataResponseContent -{ - public T? Value { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/RequestConfiguration.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/RequestConfiguration.cs deleted file mode 100644 index d28d4babb5..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/RequestConfiguration.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Newtonsoft.Json; - -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class RequestConfiguration -{ - public bool Authenticate { get; set; } - public string? ContentType { get; set; } - public string? AcceptHeader { get; set; } - public string? Content { get; set; } - - public void SetContent(object obj) - { - Content = JsonConvert.SerializeObject(obj); - } - - public void SupplementWith(RequestConfiguration other) - { - Authenticate = other.Authenticate; - AcceptHeader ??= other.AcceptHeader; - ContentType ??= other.ContentType; - Content ??= other.Content; - } - - public RequestConfiguration Clone() - { - var requestConfiguration = new RequestConfiguration(); - requestConfiguration.SupplementWith(this); - return requestConfiguration; - } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/ResponseContent.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/ResponseContent.cs deleted file mode 100644 index 0a7aaafaff..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/ResponseContent.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Newtonsoft.Json; - -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class ResponseContent -{ - public T? Result { get; set; } - - [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public Error? Error { get; set; } -} - -public class ErrorResponseContent -{ - - [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public required Error Error { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/StartDeletionProcessAsSupportResponse.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/StartDeletionProcessAsSupportResponse.cs deleted file mode 100644 index f69b090430..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/StartDeletionProcessAsSupportResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class StartDeletionProcessAsSupportResponse -{ - public required string Id { get; set; } - public required string Status { get; set; } - public required DateTime CreatedAt { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/TierDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/TierDTO.cs deleted file mode 100644 index a64bfe1fa8..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/TierDTO.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class TierDTO -{ - public required string Id { get; set; } - public required string Name { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/TierDetailsDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/TierDetailsDTO.cs deleted file mode 100644 index c55a1b60ff..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/TierDetailsDTO.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class TierDetailsDTO -{ - public required string Id { get; set; } - public required string Name { get; set; } - public required IEnumerable Quotas { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/TierOverviewDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/TierOverviewDTO.cs deleted file mode 100644 index 987f2632bb..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/TierOverviewDTO.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class TierOverviewDTO -{ - public required string Id { get; set; } - public required string Name { get; set; } - public required int NumberOfIdentities { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/TierQuotaDTO.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/TierQuotaDTO.cs deleted file mode 100644 index b2a3c7cb8e..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/TierQuotaDTO.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; - -public class TierQuotaDTO -{ - public required string Id { get; set; } - public required MetricDTO Metric { get; set; } - public required int Max { get; set; } - public required string Period { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/UpdateClientRequest.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/UpdateClientRequest.cs deleted file mode 100644 index b550ddbe5f..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/UpdateClientRequest.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class UpdateClientRequest -{ - public required string DefaultTier { get; set; } - public int? MaxIdentities { get; set; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Models/UpdateClientResponse.cs b/AdminApi/test/AdminApi.Tests.Integration/Models/UpdateClientResponse.cs deleted file mode 100644 index d2d3a68ba0..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/Models/UpdateClientResponse.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.Models; -public class UpdateClientResponse -{ - 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; } -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/BaseStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/BaseStepDefinitions.cs index 3cb1371659..9f46749f27 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/BaseStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/BaseStepDefinitions.cs @@ -1,32 +1,15 @@ -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.AdminApi.Sdk; +using Backbone.AdminApi.Tests.Integration.Configuration; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; -[Binding] -public class BaseStepDefinitions +internal abstract class BaseStepDefinitions { - protected readonly RequestConfiguration _requestConfiguration; + protected readonly Client _client; - public BaseStepDefinitions() + protected BaseStepDefinitions(HttpClientFactory factory, IOptions options) { - _requestConfiguration = new RequestConfiguration { ContentType = "application/json" }; - } - - [Given("the user is authenticated")] - public void GivenTheUserIsAuthenticated() - { - _requestConfiguration.Authenticate = true; - } - - [Given("the user is unauthenticated")] - public void GivenTheUserIsUnauthenticated() - { - _requestConfiguration.Authenticate = false; - } - - [Given("the Accept header is '([^']*)'")] - public void GivenTheAcceptHeaderIs(string acceptHeader) - { - _requestConfiguration.AcceptHeader = acceptHeader; + _client = Client.Create(factory.CreateClient(), options.Value.ApiKey); } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientDetailsStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientDetailsStepDefinitions.cs index a7cdeca73f..fadaa23bc5 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientDetailsStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientDetailsStepDefinitions.cs @@ -1,22 +1,25 @@ -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Clients.Types; +using Backbone.AdminApi.Sdk.Endpoints.Clients.Types.Requests; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types.Requests; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; using Backbone.UnitTestTools.Data; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; + +[Binding] +[Scope(Feature = "GET Client Details")] internal class ClientDetailsStepDefinitions : BaseStepDefinitions { - private readonly ClientsApi _clientsApi; - private readonly TiersApi _tiersApi; + private ApiResponse? _response; private string _clientId; private string _tierId; private readonly int _maxIdentities; - private HttpResponse? _response; - public ClientDetailsStepDefinitions(ClientsApi clientsApi, TiersApi tiersApi) + public ClientDetailsStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _clientsApi = clientsApi; - _tiersApi = tiersApi; _clientId = string.Empty; _tierId = string.Empty; _maxIdentities = 1; @@ -25,20 +28,13 @@ public ClientDetailsStepDefinitions(ClientsApi clientsApi, TiersApi tiersApi) [Given("a Tier t")] public async Task GivenATierT() { - var createTierRequest = new CreateTierRequest + var response = await _client.Tiers.CreateTier(new CreateTierRequest { Name = "TestTier_" + TestDataGenerator.GenerateString(12) - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - var response = await _tiersApi.CreateTier(requestConfiguration); + }); + response.Should().BeASuccess(); - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); - _tierId = response.Content.Result!.Id; + _tierId = response.Result!.Id; // allow the event queue to trigger the creation of this tier on the Quotas module Thread.Sleep(2000); @@ -47,51 +43,39 @@ public async Task GivenATierT() [Given("a Client c with Tier t")] public async Task GivenAClientWithTierT() { - var createClientRequest = new CreateClientRequest + var response = await _client.Clients.CreateClient(new CreateClientRequest { ClientId = string.Empty, DisplayName = string.Empty, ClientSecret = string.Empty, DefaultTier = _tierId, MaxIdentities = _maxIdentities - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createClientRequest); - - var response = await _clientsApi.CreateClient(requestConfiguration); + }); + response.Should().BeASuccess(); - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); - _clientId = response.Content.Result!.ClientId; + _clientId = response.Result!.ClientId; } [When("a GET request is sent to the /Clients/{c.clientId} endpoint")] public async Task WhenAGETRequestIsSentToTheClientsIdEndpoint() { - _response = await _clientsApi.GetClient(_clientId, _requestConfiguration); - _response.Should().NotBeNull(); - _response.Content.Should().NotBeNull(); + _response = await _client.Clients.GetClient(_clientId); } [Then("the response contains Client c")] public void ThenTheResponseContainsAClient() { - _response!.Content.Result.Should().NotBeNull(); - _response!.Content.Result!.ClientId.Should().NotBeNull(); - _response!.Content.Result!.ClientId.Should().Be(_clientId); - _response!.Content.Result!.DefaultTier.Should().NotBeNull(); - _response!.Content.Result!.DefaultTier.Should().Be(_tierId); - _response!.Content.Result!.MaxIdentities.Should().NotBeNull(); - _response!.Content.Result!.MaxIdentities.Should().Be(_maxIdentities); - _response!.AssertContentCompliesWithSchema(); + _response!.Result!.Should().NotBeNull(); + _response!.Result!.ClientId.Should().Be(_clientId); + _response!.Result!.DefaultTier.Should().Be(_tierId); + _response!.Result!.MaxIdentities.Should().Be(_maxIdentities); + _response!.ContentType.Should().StartWith("application/json"); + _response!.Should().ComplyWithSchema(); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { - var actualStatusCode = (int)_response!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); + ((int)_response!.Status).Should().Be(expectedStatusCode); } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientsStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientsStepDefinitions.cs index 70be0f1085..30d97abb02 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientsStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/ClientsStepDefinitions.cs @@ -1,7 +1,12 @@ -using Backbone.AdminApi.Tests.Integration.API; +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.AdminApi.Sdk.Endpoints.Tiers.Types.Requests; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; using Backbone.UnitTestTools.Data; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -12,23 +17,19 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "PUT Clients")] internal class ClientsStepDefinitions : BaseStepDefinitions { - private readonly ClientsApi _clientsApi; - private readonly TiersApi _tiersApi; private string _clientId; private string _clientSecret; private string _tierId; private string _updatedTierId; private int? _maxIdentities; private int? _updatedMaxIdentities; - private HttpResponse>? _getClientsResponse; - private HttpResponse? _changeClientSecretResponse; - private HttpResponse? _updateClientResponse; - private HttpResponse? _deleteResponse; + private ApiResponse? _getClientsResponse; + private ApiResponse? _changeClientSecretResponse; + private ApiResponse? _updateClientResponse; + private ApiResponse? _deleteResponse; - public ClientsStepDefinitions(ClientsApi clientsApi, TiersApi tiersApi) + public ClientsStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _clientsApi = clientsApi; - _tiersApi = tiersApi; _clientId = string.Empty; _clientSecret = string.Empty; _tierId = string.Empty; @@ -39,39 +40,22 @@ public ClientsStepDefinitions(ClientsApi clientsApi, TiersApi tiersApi) public async Task GetTier() { - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - - var response = await _tiersApi.GetTiers(requestConfiguration); - - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(200); - - var basicTier = response.Content.Result!.SingleOrDefault(t => t.Name == "Basic"); + var response = await _client.Tiers.ListTiers(); + response.Should().BeASuccess(); + var basicTier = response.Result!.SingleOrDefault(t => t.Name == "Basic"); return basicTier != null ? basicTier.Id : await CreateTier(); } public async Task CreateTier() { - var createTierRequest = new CreateTierRequest - { - Name = "TestTier_" + TestDataGenerator.GenerateString(12) - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - var response = await _tiersApi.CreateTier(requestConfiguration); - - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); + var response = await _client.Tiers.CreateTier(new CreateTierRequest { Name = "TestTier_" + TestDataGenerator.GenerateString(12) }); + response.Should().BeASuccess(); // allow the event queue to trigger the creation of this tier on the Quotas module Thread.Sleep(2000); - return response.Content.Result!.Id; + return response.Result!.Id; } [Given("a Client c")] @@ -80,24 +64,17 @@ public async Task GivenAClientC() _tierId = await GetTier(); _maxIdentities = 100; - var createClientRequest = new CreateClientRequest + var response = await _client.Clients.CreateClient(new CreateClientRequest { ClientId = string.Empty, DisplayName = string.Empty, ClientSecret = string.Empty, DefaultTier = _tierId, MaxIdentities = _maxIdentities - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createClientRequest); - - var response = await _clientsApi.CreateClient(requestConfiguration); + }); + response.Should().BeASuccess(); - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); - _clientId = response.Content.Result!.ClientId; + _clientId = response.Result!.ClientId; } [Given("a non-existent Client c")] @@ -109,72 +86,32 @@ public void GivenANonExistentClientC() [When("a DELETE request is sent to the /Clients endpoint")] public async Task WhenADeleteRequestIsSentToTheClientsEndpoint() { - _deleteResponse = await _clientsApi.DeleteClient(_clientId, _requestConfiguration); - _deleteResponse.Should().NotBeNull(); + _deleteResponse = await _client.Clients.DeleteClient(_clientId); } [When("a GET request is sent to the /Clients endpoint")] public async Task WhenAGetRequestIsSentToTheClientsEndpoint() { - _getClientsResponse = await _clientsApi.GetAllClients(_requestConfiguration); - _getClientsResponse.Should().NotBeNull(); - _getClientsResponse.Content.Should().NotBeNull(); + _getClientsResponse = await _client.Clients.GetAllClients(); } [When("a PATCH request is sent to the /Clients/{c.ClientId}/ChangeSecret endpoint with a new secret")] public async Task WhenAPatchRequestIsSentToTheClientsChangeSecretEndpointWithASecret() { _clientSecret = "new-client-secret"; - - var changeClientSecretRequest = new ChangeClientSecretRequest - { - NewSecret = _clientSecret - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(changeClientSecretRequest); - - _changeClientSecretResponse = await _clientsApi.ChangeClientSecret(_clientId, requestConfiguration); - - _changeClientSecretResponse.Should().NotBeNull(); - _changeClientSecretResponse.Content.Should().NotBeNull(); + _changeClientSecretResponse = await _client.Clients.ChangeClientSecret(_clientId, new ChangeClientSecretRequest { NewSecret = _clientSecret }); } [When("a PATCH request is sent to the /Clients/{c.ClientId}/ChangeSecret endpoint without passing a secret")] public async Task WhenAPatchRequestIsSentToTheClientsChangeSecretEndpointWithoutASecret() { - var changeClientSecretRequest = new ChangeClientSecretRequest - { - NewSecret = string.Empty - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(changeClientSecretRequest); - - _changeClientSecretResponse = await _clientsApi.ChangeClientSecret(_clientId, requestConfiguration); - - _changeClientSecretResponse.Should().NotBeNull(); - _changeClientSecretResponse.Content.Should().NotBeNull(); + _changeClientSecretResponse = await _client.Clients.ChangeClientSecret(_clientId, new ChangeClientSecretRequest { NewSecret = string.Empty }); } [When("a PATCH request is sent to the /Clients/{clientId}/ChangeSecret endpoint")] public async Task WhenAPatchRequestIsSentToTheClientsChangeSecretEndpointForAnInexistentClient() { - var changeClientSecretRequest = new ChangeClientSecretRequest - { - NewSecret = "new-client-secret" - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(changeClientSecretRequest); - - _changeClientSecretResponse = await _clientsApi.ChangeClientSecret("inexistentClientId", requestConfiguration); - - _changeClientSecretResponse.Should().NotBeNull(); - _changeClientSecretResponse.Content.Should().NotBeNull(); + _changeClientSecretResponse = await _client.Clients.ChangeClientSecret("inexistentClientId", new ChangeClientSecretRequest { NewSecret = "new-client-secret" }); } [When("a PUT request is sent to the /Clients/{c.ClientId} endpoint")] @@ -183,172 +120,108 @@ public async Task WhenAPatchRequestIsSentToTheClientsEndpoint() _updatedTierId = await CreateTier(); _updatedMaxIdentities = 150; - var updateClientRequest = new UpdateClientRequest() + _updateClientResponse = await _client.Clients.UpdateClient(_clientId, new UpdateClientRequest { DefaultTier = _updatedTierId, MaxIdentities = _updatedMaxIdentities - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(updateClientRequest); - - _updateClientResponse = await _clientsApi.UpdateClient(_clientId, requestConfiguration); - - _updateClientResponse.Should().NotBeNull(); - _updateClientResponse.Content.Should().NotBeNull(); + }); } [When("a PUT request is sent to the /Clients/{c.ClientId} endpoint with a null value for maxIdentities")] public async Task WhenAPatchRequestIsSentToTheClientsEndpointWithANullMaxIdentities() { - var updateClientRequest = new UpdateClientRequest() + _updateClientResponse = await _client.Clients.UpdateClient(_clientId, new UpdateClientRequest { DefaultTier = _tierId, MaxIdentities = null - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(updateClientRequest); - - _updateClientResponse = await _clientsApi.UpdateClient(_clientId, requestConfiguration); - - _updateClientResponse.Should().NotBeNull(); - _updateClientResponse.Content.Should().NotBeNull(); + }); } [When("a PUT request is sent to the /Clients/{c.ClientId} endpoint with a non-existent tier id")] public async Task WhenAPatchRequestIsSentToTheClientsEndpointWithAnInexistentDefaultTier() { - var updateClientRequest = new UpdateClientRequest() + _updateClientResponse = await _client.Clients.UpdateClient(_clientId, new UpdateClientRequest { DefaultTier = "inexistent-tier-id", MaxIdentities = _maxIdentities - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(updateClientRequest); - - _updateClientResponse = await _clientsApi.UpdateClient(_clientId, requestConfiguration); - - _updateClientResponse.Should().NotBeNull(); - _updateClientResponse.Content.Should().NotBeNull(); + }); } [When("a PUT request is sent to the /Clients/{c.clientId} endpoint with a non-existing clientId")] public async Task WhenAPatchRequestIsSentToTheClientsEndpointForAnInexistentClient() { - var updateClientRequest = new UpdateClientRequest() + _updateClientResponse = await _client.Clients.UpdateClient("inexistentClientId", new UpdateClientRequest { DefaultTier = "new-tier-id", MaxIdentities = _maxIdentities - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(updateClientRequest); - - _updateClientResponse = await _clientsApi.UpdateClient("inexistentClientId", requestConfiguration); - - _updateClientResponse.Should().NotBeNull(); - _updateClientResponse.Content.Should().NotBeNull(); + }); } [Then("the response contains a paginated list of Clients")] public void ThenTheResponseContainsAListOfClients() { - _getClientsResponse!.Content.Result.Should().NotBeNullOrEmpty(); - _getClientsResponse.AssertContentCompliesWithSchema(); + _getClientsResponse!.Should().BeASuccess(); + _getClientsResponse!.ContentType.Should().StartWith("application/json"); + _getClientsResponse.Should().ComplyWithSchema(); } [Then("the response contains Client c with the new client secret")] public void ThenTheResponseContainsAClientWithNewSecret() { - _changeClientSecretResponse!.AssertHasValue(); - _changeClientSecretResponse!.AssertStatusCodeIsSuccess(); - _changeClientSecretResponse!.AssertContentTypeIs("application/json"); - _changeClientSecretResponse!.AssertContentCompliesWithSchema(); - _changeClientSecretResponse!.Content.Result!.ClientSecret.Should().Be(_clientSecret); + _changeClientSecretResponse!.Should().BeASuccess(); + _changeClientSecretResponse!.ContentType.Should().StartWith("application/json"); + _changeClientSecretResponse.Should().ComplyWithSchema(); } [Then("the response contains Client c with a random secret generated by the backend")] public void ThenTheResponseContainsAClientWithRandomGeneratedSecret() { - _changeClientSecretResponse!.AssertHasValue(); - _changeClientSecretResponse!.AssertStatusCodeIsSuccess(); - _changeClientSecretResponse!.AssertContentTypeIs("application/json"); - _changeClientSecretResponse!.AssertContentCompliesWithSchema(); - _changeClientSecretResponse!.Content.Result!.ClientSecret.Should().NotBeNullOrEmpty(); + _changeClientSecretResponse!.Should().BeASuccess(); + _changeClientSecretResponse!.ContentType.Should().StartWith("application/json"); + _changeClientSecretResponse.Should().ComplyWithSchema(); } [Then("the response contains Client c")] public void ThenTheResponseContainsAClient() { - _updateClientResponse!.AssertHasValue(); - _updateClientResponse!.AssertStatusCodeIsSuccess(); - _updateClientResponse!.AssertContentTypeIs("application/json"); - _updateClientResponse!.AssertContentCompliesWithSchema(); + _updateClientResponse!.Should().BeASuccess(); + _updateClientResponse!.ContentType.Should().StartWith("application/json"); + _updateClientResponse!.Should().ComplyWithSchema(); } [Then("the Client in the Backend was successfully updated")] public async Task ThenTheClientInTheBackendWasUpdatedAsync() { - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - - var response = await _clientsApi.GetClient(_clientId, requestConfiguration); + var response = await _client.Clients.GetClient(_clientId); - response.AssertHasValue(); - response.AssertStatusCodeIsSuccess(); - response.AssertContentTypeIs("application/json"); - response.AssertContentCompliesWithSchema(); - response.Content.Result!.DefaultTier.Should().Be(_updatedTierId); - response.Content.Result!.MaxIdentities.Should().Be(_updatedMaxIdentities); + response.Should().BeASuccess(); + response.Result!.DefaultTier.Should().Be(_updatedTierId); + response.Result.MaxIdentities.Should().Be(_updatedMaxIdentities); } [Then("the Client in the Backend has a null value for maxIdentities")] public async Task ThenTheClientInTheBackendHasNullIdentitiesLimit() { - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - - var response = await _clientsApi.GetClient(_clientId, requestConfiguration); + var response = await _client.Clients.GetClient(_clientId); - response.AssertHasValue(); - response.AssertStatusCodeIsSuccess(); - response.AssertContentTypeIs("application/json"); - response.AssertContentCompliesWithSchema(); - response.Content.Result!.MaxIdentities.Should().BeNull(); + response.Should().BeASuccess(); + response.Result!.MaxIdentities.Should().BeNull(); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { if (_getClientsResponse != null) - { - var actualStatusCode = (int)_getClientsResponse.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_getClientsResponse!.Status).Should().Be(expectedStatusCode); if (_changeClientSecretResponse != null) - { - var actualStatusCode = (int)_changeClientSecretResponse.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_changeClientSecretResponse!.Status).Should().Be(expectedStatusCode); if (_deleteResponse != null) - { - var actualStatusCode = (int)_deleteResponse.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_deleteResponse!.Status).Should().Be(expectedStatusCode); if (_updateClientResponse != null) - { - var actualStatusCode = (int)_updateClientResponse.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_updateClientResponse!.Status).Should().Be(expectedStatusCode); } [Then(@"the response content includes an error with the error code ""([^""]+)""")] @@ -356,27 +229,26 @@ public void ThenTheResponseContentIncludesAnErrorWithTheErrorCode(string errorCo { if (_getClientsResponse != null) { - _getClientsResponse!.Content.Error.Should().NotBeNull(); - _getClientsResponse.Content.Error!.Code.Should().Be(errorCode); + _getClientsResponse!.Error.Should().NotBeNull(); + _getClientsResponse.Error!.Code.Should().Be(errorCode); } if (_changeClientSecretResponse != null) { - _changeClientSecretResponse!.Content.Error.Should().NotBeNull(); - _changeClientSecretResponse.Content.Error!.Code.Should().Be(errorCode); + _changeClientSecretResponse!.Error.Should().NotBeNull(); + _changeClientSecretResponse.Error!.Code.Should().Be(errorCode); } if (_deleteResponse != null) { - _deleteResponse.Content.Should().NotBeNull(); - _deleteResponse.Content!.Error.Should().NotBeNull(); - _deleteResponse.Content!.Error.Code.Should().Be(errorCode); + _deleteResponse.Error.Should().NotBeNull(); + _deleteResponse.Error!.Code.Should().Be(errorCode); } if (_updateClientResponse != null) { - _updateClientResponse!.Content.Error.Should().NotBeNull(); - _updateClientResponse.Content.Error!.Code.Should().Be(errorCode); + _updateClientResponse.Error.Should().NotBeNull(); + _updateClientResponse.Error!.Code.Should().Be(errorCode); } } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IdentitiesApiStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IdentitiesApiStepDefinitions.cs index 54986d60b6..19e1cccdee 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IdentitiesApiStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IdentitiesApiStepDefinitions.cs @@ -1,9 +1,9 @@ -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Responses; +using Backbone.AdminApi.Sdk.Services; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; -using Backbone.Crypto; -using Backbone.Crypto.Abstractions; -using Newtonsoft.Json; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -12,138 +12,91 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "POST Identities/{id}/DeletionProcess")] internal class IdentitiesApiStepDefinitions : BaseStepDefinitions { - private readonly IdentitiesApi _identitiesApi; - private readonly ISignatureHelper _signatureHelper; - private ODataResponse>? _identityOverviewsResponse; - private HttpResponse? _identityResponse; - private HttpResponse? _createIdentityResponse; - private HttpResponse? _identityDeletionProcessResponse; + private ApiResponse? _identityOverviewsResponse; + private ApiResponse? _identityResponse; + private ApiResponse? _createIdentityResponse; + private ApiResponse? _identityDeletionProcessResponse; private string _existingIdentity; - public IdentitiesApiStepDefinitions(IdentitiesApi identitiesApi, ISignatureHelper signatureHelper) + public IdentitiesApiStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _identitiesApi = identitiesApi; - _signatureHelper = signatureHelper; _existingIdentity = string.Empty; } - - [Given("an active deletion process for Identity i exists")] - public async Task GivenAnActiveDeletionProcessForIdentityAExists() - { - await _identitiesApi.StartDeletionProcess(_createIdentityResponse!.Content.Result!.Address, _requestConfiguration); - } - [Given("an Identity i")] public async Task GivenAnIdentityI() { - var keyPair = _signatureHelper.CreateKeyPair(); + _createIdentityResponse = await IdentityCreationHelper.CreateIdentity(_client); + _createIdentityResponse.Should().BeASuccess(); - dynamic publicKey = new - { - pub = keyPair.PublicKey.Base64Representation, - alg = 3 - }; + _existingIdentity = _createIdentityResponse.Result!.Address; + } - var createIdentityRequest = new CreateIdentityRequest() - { - ClientId = "test", - ClientSecret = "test", - DevicePassword = "test", - IdentityPublicKey = (ConvertibleString.FromUtf8(JsonConvert.SerializeObject(publicKey)) as ConvertibleString)!.Base64Representation, - IdentityVersion = 1, - SignedChallenge = new CreateIdentityRequestSignedChallenge - { - Challenge = "string.Empty", - Signature = "some-dummy-signature" - } - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createIdentityRequest); - - _createIdentityResponse = await _identitiesApi.CreateIdentity(requestConfiguration); - _createIdentityResponse.IsSuccessStatusCode.Should().BeTrue(); - _existingIdentity = _createIdentityResponse.Content.Result!.Address; + [Given("an active deletion process for Identity i exists")] + public async Task GivenAnActiveDeletionProcessForIdentityAExists() + { + await _client.Identities.StartDeletionProcess(_createIdentityResponse!.Result!.Address); } [When("a POST request is sent to the /Identities/{i.id}/DeletionProcesses endpoint")] public async Task WhenAPOSTRequestIsSentToTheIdentitiesIdDeletionProcessesEndpoint() { - _identityDeletionProcessResponse = await _identitiesApi.StartDeletionProcess(_createIdentityResponse!.Content.Result!.Address, _requestConfiguration); + _identityDeletionProcessResponse = await _client.Identities.StartDeletionProcess(_createIdentityResponse!.Result!.Address); } [When("a GET request is sent to the /Identities endpoint")] public async Task WhenAGETRequestIsSentToTheIdentitiesOverviewEndpoint() { - _identityOverviewsResponse = await _identitiesApi.GetIdentityOverviews(); - _identityOverviewsResponse.Should().NotBeNull(); - _identityOverviewsResponse!.Content.Should().NotBeNull(); + _identityOverviewsResponse = await _client.Identities.ListIdentities(); } [When("a GET request is sent to the /Identities/{i.address} endpoint")] public async Task WhenAGETRequestIsSentToTheIdentitiesAddressEndpoint() { - _identityResponse = await _identitiesApi.GetIdentityByAddress(_requestConfiguration, _existingIdentity); - _identityResponse.Should().NotBeNull(); - _identityResponse.Content.Should().NotBeNull(); + _identityResponse = await _client.Identities.GetIdentity(_existingIdentity); } [When("a GET request is sent to the /Identities/{address} endpoint with an inexistent address")] public async Task WhenAGETRequestIsSentToTheIdentitiesAddressEndpointForAnInexistentIdentity() { - _identityResponse = await _identitiesApi.GetIdentityByAddress(_requestConfiguration, "inexistentIdentityAddress"); - _identityResponse.Should().NotBeNull(); - _identityResponse.Content.Should().NotBeNull(); + _identityResponse = await _client.Identities.GetIdentity("inexistentIdentityAddress"); } [Then("the response contains a list of Identities")] public void ThenTheResponseContainsAListOfIdentities() { - _identityOverviewsResponse!.Content.Value.Should().NotBeNull(); - _identityOverviewsResponse!.Content.Value.Should().NotBeNullOrEmpty(); - _identityOverviewsResponse!.AssertContentTypeIs("application/json"); - _identityOverviewsResponse!.AssertContentCompliesWithSchema(); + _identityOverviewsResponse!.Result!.Should().NotBeNull(); + _identityOverviewsResponse!.ContentType.Should().StartWith("application/json"); + _identityOverviewsResponse.Should().ComplyWithSchema(); } [Then("the response contains a Deletion Process")] public void ThenTheResponseContainsADeletionProcess() { - _identityDeletionProcessResponse!.Content.Result.Should().NotBeNull(); - _identityDeletionProcessResponse!.AssertContentTypeIs("application/json"); - _identityDeletionProcessResponse!.AssertContentCompliesWithSchema(); + _identityDeletionProcessResponse!.Result!.Should().NotBeNull(); + _identityDeletionProcessResponse!.ContentType.Should().StartWith("application/json"); + _identityDeletionProcessResponse.Should().ComplyWithSchema(); } [Then("the response contains Identity i")] public void ThenTheResponseContainsAnIdentity() { - _identityResponse!.AssertHasValue(); - _identityResponse!.AssertStatusCodeIsSuccess(); - _identityResponse!.AssertContentTypeIs("application/json"); - _identityResponse!.AssertContentCompliesWithSchema(); + _identityResponse!.Result!.Should().NotBeNull(); + _identityResponse!.ContentType.Should().StartWith("application/json"); + _identityResponse.Should().ComplyWithSchema(); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { if (_identityResponse != null) - { - var actualStatusCode = (int)_identityResponse!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_identityResponse!.Status).Should().Be(expectedStatusCode); if (_identityOverviewsResponse != null) - { - var actualStatusCode = (int)_identityOverviewsResponse!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_identityOverviewsResponse!.Status).Should().Be(expectedStatusCode); if (_identityDeletionProcessResponse != null) - { - var actualStatusCode = (int)_identityDeletionProcessResponse!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_identityDeletionProcessResponse!.Status).Should().Be(expectedStatusCode); } [Then(@"the response content includes an error with the error code ""([^""]+)""")] @@ -151,14 +104,14 @@ public void ThenTheResponseContentIncludesAnErrorWithTheErrorCode(string errorCo { if (_identityResponse != null) { - _identityResponse!.Content.Error.Should().NotBeNull(); - _identityResponse.Content.Error!.Code.Should().Be(errorCode); + _identityResponse!.Result!.Should().NotBeNull(); + _identityResponse.Error!.Code.Should().Be(errorCode); } if (_identityDeletionProcessResponse != null) { - _identityDeletionProcessResponse!.Content.Error.Should().NotBeNull(); - _identityDeletionProcessResponse.Content.Error!.Code.Should().Be(errorCode); + _identityDeletionProcessResponse!.Error.Should().NotBeNull(); + _identityDeletionProcessResponse.Error!.Code.Should().Be(errorCode); } } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IndividualQuotaStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IndividualQuotaStepDefinitions.cs index ec67d25b89..fc5ba1a071 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IndividualQuotaStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/IndividualQuotaStepDefinitions.cs @@ -1,9 +1,10 @@ -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Identities.Types; +using Backbone.AdminApi.Sdk.Endpoints.Identities.Types.Requests; +using Backbone.AdminApi.Sdk.Services; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; -using Backbone.Crypto; -using Backbone.Crypto.Abstractions; -using Newtonsoft.Json; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -12,17 +13,13 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "DELETE IndividualQuota")] internal class IndividualQuotaStepDefinitions : BaseStepDefinitions { - private readonly IdentitiesApi _identitiesApi; private string _identityAddress; private string _quotaId; - private HttpResponse? _response; - private readonly ISignatureHelper _signatureHelper; - private HttpResponse? _deleteResponse; + private ApiResponse? _createQuotaResponse; + private ApiResponse? _deleteResponse; - public IndividualQuotaStepDefinitions(IdentitiesApi identitiesApi, ISignatureHelper signatureHelper) + public IndividualQuotaStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _identitiesApi = identitiesApi; - _signatureHelper = signatureHelper; _identityAddress = string.Empty; _quotaId = string.Empty; } @@ -37,143 +34,92 @@ public async Task GivenAnIdentityI() public async Task GivenAnIdentityIWithAnIndividualQuotaQ() { await CreateIdentity(); - var createIndividualQuotaRequest = new CreateIndividualQuotaRequest() + + var response = await _client.Identities.CreateIndividualQuota(_identityAddress, new CreateQuotaForIdentityRequest { MetricKey = "NumberOfSentMessages", Max = 2, Period = "Week" - }; - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createIndividualQuotaRequest); - - var response = await _identitiesApi.CreateIndividualQuota(requestConfiguration, _identityAddress); - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); - _quotaId = response.Content.Result!.Id; + }); + response.Should().BeASuccess(); + + _quotaId = response.Result!.Id; } [When("a DELETE request is sent to the /Identities/{i.address}/Quotas/{q.id} endpoint")] public async Task WhenADeleteRequestIsSentToTheDeleteIndividualQuotaEndpoint() { - _deleteResponse = await _identitiesApi.DeleteIndividualQuota(_identityAddress, _quotaId, _requestConfiguration); - _deleteResponse.Should().NotBeNull(); + _deleteResponse = await _client.Identities.DeleteIndividualQuota(_identityAddress, _quotaId); } [When("a DELETE request is sent to the /Identities/{i.address}/Quotas/inexistentQuotaId endpoint")] public async Task WhenADeleteRequestIsSentToTheDeleteIndividualQuotaEndpointWithAnInexistentQuotaId() { - _deleteResponse = await _identitiesApi.DeleteIndividualQuota(_identityAddress, "QUOInexistentIdxxxxx", _requestConfiguration); - _deleteResponse.Should().NotBeNull(); + _deleteResponse = await _client.Identities.DeleteIndividualQuota(_identityAddress, "QUOInexistentIdxxxxx"); } [When("a POST request is sent to the /Identity/{i.id}/Quotas endpoint")] public async Task WhenAPOSTRequestIsSentToTheCreateIndividualQuotaEndpoint() { - var createIndividualQuotaRequest = new CreateIndividualQuotaRequest() + _createQuotaResponse = await _client.Identities.CreateIndividualQuota(_identityAddress, new CreateQuotaForIdentityRequest { MetricKey = "NumberOfSentMessages", Max = 2, Period = "Week" - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createIndividualQuotaRequest); - - _response = await _identitiesApi.CreateIndividualQuota(requestConfiguration, _identityAddress); + }); } [When("a POST request is sent to the /Identity/{address}/Quotas endpoint with an inexistent identity address")] public async Task WhenAPOSTRequestIsSentToTheCreateIndividualQuotaEndpointWithAnInexistentIdentityAddress() { - var createIndividualQuotaRequest = new CreateIndividualQuotaRequest() + _createQuotaResponse = await _client.Identities.CreateIndividualQuota("some-inexistent-identity-address", new CreateQuotaForIdentityRequest { MetricKey = "NumberOfSentMessages", Max = 2, Period = "Week" - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createIndividualQuotaRequest); - - _response = await _identitiesApi.CreateIndividualQuota(requestConfiguration, "some-inexistent-identity-address"); + }); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { - if (_response != null) - { - var actualStatusCode = (int)_response.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + if (_createQuotaResponse != null) + ((int)_createQuotaResponse!.Status).Should().Be(expectedStatusCode); if (_deleteResponse != null) - { - var actualStatusCode = (int)_deleteResponse.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_deleteResponse!.Status).Should().Be(expectedStatusCode); } [Then("the response contains an IndividualQuota")] public void ThenTheResponseContainsAnIndividualQuota() { - _response!.AssertHasValue(); - _response!.AssertStatusCodeIsSuccess(); - _response!.AssertContentTypeIs("application/json"); - _response!.AssertContentCompliesWithSchema(); + _createQuotaResponse!.Result!.Should().NotBeNull(); + _createQuotaResponse!.ContentType.Should().StartWith("application/json"); + _createQuotaResponse.Should().ComplyWithSchema(); } [Then(@"the response content includes an error with the error code ""([^""]+)""")] public void ThenTheResponseContentIncludesAnErrorWithTheErrorCode(string errorCode) { - if (_response != null) + if (_createQuotaResponse != null) { - _response!.Content.Error.Should().NotBeNull(); - _response.Content.Error!.Code.Should().Be(errorCode); + _createQuotaResponse!.Error.Should().NotBeNull(); + _createQuotaResponse.Error!.Code.Should().Be(errorCode); } if (_deleteResponse != null) { - _deleteResponse.Content.Should().NotBeNull(); - _deleteResponse.Content!.Error.Should().NotBeNull(); - _deleteResponse.Content!.Error.Code.Should().Be(errorCode); + _deleteResponse.Error.Should().NotBeNull(); + _deleteResponse.Error!.Code.Should().Be(errorCode); } } private async Task CreateIdentity() { - var keyPair = _signatureHelper.CreateKeyPair(); + var createIdentityResponse = await IdentityCreationHelper.CreateIdentity(_client); + createIdentityResponse.Should().BeASuccess(); - dynamic publicKey = new - { - pub = keyPair.PublicKey.Base64Representation, - alg = 3 - }; - - var createIdentityRequest = new CreateIdentityRequest() - { - ClientId = "test", - ClientSecret = "test", - DevicePassword = "test", - IdentityPublicKey = (ConvertibleString.FromUtf8(JsonConvert.SerializeObject(publicKey)) as ConvertibleString)!.Base64Representation, - IdentityVersion = 1, - SignedChallenge = new CreateIdentityRequestSignedChallenge - { - Challenge = "string.Empty", - Signature = "some-dummy-signature" - } - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createIdentityRequest); - - var createIdentityResponse = await _identitiesApi.CreateIdentity(requestConfiguration); - createIdentityResponse.IsSuccessStatusCode.Should().BeTrue(); - _identityAddress = createIdentityResponse.Content.Result!.Address; + _identityAddress = createIdentityResponse.Result!.Address; // allow the event queue to trigger the creation of this Identity on the Quotas module Thread.Sleep(2000); diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/LogsStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/LogsStepDefinitions.cs index 6818ad22cd..b5ff42a98f 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/LogsStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/LogsStepDefinitions.cs @@ -1,5 +1,7 @@ -using Backbone.AdminApi.Tests.Integration.API; -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.AdminApi.Sdk.Endpoints.Logs.Types.Requests; +using Backbone.AdminApi.Tests.Integration.Configuration; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -7,65 +9,47 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "POST Log")] internal class LogsStepDefinitions : BaseStepDefinitions { - private readonly LogsApi _logsApi; - private HttpResponse? _postResponse; + private ApiResponse? _postResponse; - public LogsStepDefinitions(LogsApi logsApi) + public LogsStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _logsApi = logsApi; } [When("a POST request is sent to the /Logs endpoint")] public async Task WhenAPOSTRequestIsSentToTheLogsEndpoint() { - var createTierRequest = new LogRequest + _postResponse = await _client.Logs.CreateLog(new LogRequest { LogLevel = LogLevel.Trace, Category = "Test Category", MessageTemplate = "The log request {0} has the following description: {1}", Arguments = ["Request Name", "Request Description"] - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - _postResponse = await _logsApi.CreateLog(requestConfiguration); + }); } [When("a POST request is sent to the /Logs endpoint with an invalid Log Level")] public async Task WhenAPOSTRequestIsSentToTheLogsEndpointWithAnInvalidLogLevel() { - var createTierRequest = new LogRequest + _postResponse = await _client.Logs.CreateLog(new LogRequest { LogLevel = (LogLevel)16, Category = "Test Category", MessageTemplate = "The log request {0} has the following description: {1}", Arguments = ["Request Name", "Request Description"] - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - _postResponse = await _logsApi.CreateLog(requestConfiguration); + }); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { if (_postResponse != null) - { - var actualStatusCode = (int)_postResponse!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_postResponse!.Status).Should().Be(expectedStatusCode); } [Then(@"the response content includes an error with the error code ""([^""]+)""")] public void ThenTheResponseContentIncludesAnErrorWithTheErrorCode(string errorCode) { - _postResponse!.Content.Should().NotBeNull(); - _postResponse!.Content!.Error.Should().NotBeNull(); - _postResponse.Content.Error.Code.Should().Be(errorCode); + _postResponse!.Error.Should().NotBeNull(); + _postResponse.Error!.Code.Should().Be(errorCode); } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MessagesStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MessagesStepDefinitions.cs index 59c40d5353..feb7dbc9fc 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MessagesStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MessagesStepDefinitions.cs @@ -1,7 +1,10 @@ -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Messages.Types; +using Backbone.AdminApi.Sdk.Endpoints.Messages.Types.Responses; +using Backbone.AdminApi.Sdk.Services; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; -using Backbone.AdminApi.Tests.Integration.TestData; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -9,47 +12,39 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "GET Messages")] internal class MessagesStepDefinitions : BaseStepDefinitions { - private readonly MessagesApi _messagesApi; private string _identityAddress; - private HttpResponse>? _messagesResponse; + private ApiResponse? _messagesResponse; - public MessagesStepDefinitions(MessagesApi messagesApi) + public MessagesStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _messagesApi = messagesApi; _identityAddress = string.Empty; } [Given(@"an Identity i")] - public void GivenAnIdentity() + public async Task GivenAnIdentity() { - _identityAddress = Identities.IDENTITY_A; + await CreateIdentity(); } [When(@"a GET request is sent to the /Messages endpoint with type '(.*)' and participant i.Address")] public async Task WhenAGetRequestIsSentToTheMessagesEndpoint(string type) { - _messagesResponse = await _messagesApi.GetMessagesWithParticipant(_identityAddress, type, _requestConfiguration); - _messagesResponse.Should().NotBeNull(); - _messagesResponse.Content.Should().NotBeNull(); + _messagesResponse = await _client.Messages.GetMessagesWithParticipant(_identityAddress, new MessageType(type)); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { - if (_messagesResponse != null) - { - var actualStatusCode = (int)_messagesResponse.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_messagesResponse!.Status).Should().Be(expectedStatusCode); } [Then(@"the response contains a paginated list of Messages")] public void ThenTheResponseContainsAListOfMessages() { - _messagesResponse!.AssertHasValue(); - _messagesResponse!.AssertStatusCodeIsSuccess(); - _messagesResponse!.AssertContentTypeIs("application/json"); - _messagesResponse!.AssertContentCompliesWithSchema(); + _messagesResponse!.Result.Should().NotBeNull(); + _messagesResponse!.Should().BeASuccess(); + _messagesResponse!.ContentType.Should().StartWith("application/json"); + _messagesResponse.Should().ComplyWithSchema(); } [Then(@"the response content includes an error with the error code ""([^""]+)""")] @@ -57,8 +52,19 @@ public void ThenTheResponseContentIncludesAnErrorWithTheErrorCode(string errorCo { if (_messagesResponse != null) { - _messagesResponse!.Content.Error.Should().NotBeNull(); - _messagesResponse.Content.Error!.Code.Should().Be(errorCode); + _messagesResponse!.Error.Should().NotBeNull(); + _messagesResponse.Error!.Code.Should().Be(errorCode); } } + + private async Task CreateIdentity() + { + var createIdentityResponse = await IdentityCreationHelper.CreateIdentity(_client); + createIdentityResponse.Should().BeASuccess(); + + _identityAddress = createIdentityResponse.Result!.Address; + + // allow the event queue to trigger the creation of this Identity on the Quotas module + Thread.Sleep(2000); + } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MetricsStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MetricsStepDefinitions.cs index e5b75bc82c..b24ab1cd7e 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MetricsStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/MetricsStepDefinitions.cs @@ -1,6 +1,8 @@ -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Metrics.Types.Responses; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -8,33 +10,30 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "GET Metrics")] internal class MetricsStepDefinitions : BaseStepDefinitions { - private readonly MetricsApi _metricsApi; - private HttpResponse>? _response; + private ApiResponse? _metricsResponse; - public MetricsStepDefinitions(MetricsApi metricsApi) + public MetricsStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _metricsApi = metricsApi; } [When("a GET request is sent to the /Metrics endpoint")] public async Task WhenAGETRequestIsSentToTheMetricsEndpoint() { - _response = await _metricsApi.GetAllMetrics(_requestConfiguration); - _response.Should().NotBeNull(); - _response.Content.Should().NotBeNull(); + _metricsResponse = await _client.Metrics.GetAllMetrics(); + _metricsResponse.Should().BeASuccess(); } [Then("the response contains a list of Metrics")] public void ThenTheResponseContainsAListOfMetrics() { - _response!.Content.Result.Should().NotBeNullOrEmpty(); - _response.AssertContentCompliesWithSchema(); + _metricsResponse!.Result!.Should().NotBeNullOrEmpty(); + _metricsResponse!.ContentType.Should().StartWith("application/json"); + _metricsResponse.Should().ComplyWithSchema(); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { - var actualStatusCode = (int)_response!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); + ((int)_metricsResponse!.Status).Should().Be(expectedStatusCode); } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierDetailsStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierDetailsStepDefinitions.cs index 196267d630..afe8dd9420 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierDetailsStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierDetailsStepDefinitions.cs @@ -1,7 +1,10 @@ -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types.Requests; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; using Backbone.UnitTestTools.Data; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -9,33 +12,20 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "GET Tier Details")] internal class TierDetailsStepDefinitions : BaseStepDefinitions { - private readonly TiersApi _tiersApi; private string _tierId; - private HttpResponse? _response; + private ApiResponse? _tierDetailsResponse; - public TierDetailsStepDefinitions(TiersApi tiersApi) + public TierDetailsStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _tiersApi = tiersApi; _tierId = string.Empty; } [Given("a Tier t")] public async Task GivenATier() { - var createTierRequest = new CreateTierRequest - { - Name = "TestTier_" + TestDataGenerator.GenerateString(12) - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - var response = await _tiersApi.CreateTier(requestConfiguration); - - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); - _tierId = response.Content.Result!.Id; + var response = await _client.Tiers.CreateTier(new CreateTierRequest { Name = "TestTier_" + TestDataGenerator.GenerateString(12) }); + response.Should().BeASuccess(); + _tierId = response.Result!.Id; // allow the event queue to trigger the creation of this tier on the Quotas module Thread.Sleep(2000); @@ -44,24 +34,21 @@ public async Task GivenATier() [When("a GET request is sent to the /Tiers/{t.id} endpoint")] public async Task WhenAGETRequestIsSentToTheTiersIdEndpoint() { - _response = await _tiersApi.GetTierById(_requestConfiguration, _tierId); - _response.Should().NotBeNull(); - _response.Content.Should().NotBeNull(); + _tierDetailsResponse = await _client.Tiers.GetTier(_tierId); } [Then("the response contains Tier t")] public void ThenTheResponseContainsATier() { - _response!.Content.Result.Should().NotBeNull(); - _response!.Content.Result!.Id.Should().NotBeNull(); - _response!.Content.Result!.Id.Should().Be(_tierId); - _response!.AssertContentCompliesWithSchema(); + _tierDetailsResponse!.Result!.Should().NotBeNull(); + _tierDetailsResponse!.Result!.Id.Should().Be(_tierId); + _tierDetailsResponse!.ContentType.Should().StartWith("application/json"); + _tierDetailsResponse.Should().ComplyWithSchema(); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { - var actualStatusCode = (int)_response!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); + ((int)_tierDetailsResponse!.Status).Should().Be(expectedStatusCode); } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierQuotaStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierQuotaStepDefinitions.cs index 4a9f6a0c08..9cc6d86272 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierQuotaStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TierQuotaStepDefinitions.cs @@ -1,23 +1,25 @@ -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types.Requests; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; using Backbone.UnitTestTools.Data; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; +[Binding] [Scope(Feature = "POST TierQuota")] [Scope(Feature = "DELETE TierQuota")] internal class TierQuotaStepDefinitions : BaseStepDefinitions { - private readonly TiersApi _tiersApi; + private ApiResponse? _createTierQuotaResponse; + private ApiResponse? _deleteResponse; private string _tierId; private string _tierQuotaDefinitionId; - private HttpResponse? _response; - private HttpResponse? _deleteResponse; - public TierQuotaStepDefinitions(TiersApi tiersApi) + public TierQuotaStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _tiersApi = tiersApi; _tierId = string.Empty; _tierQuotaDefinitionId = string.Empty; } @@ -25,20 +27,10 @@ public TierQuotaStepDefinitions(TiersApi tiersApi) [Given("a Tier t")] public async Task GivenAValidTier() { - var createTierRequest = new CreateTierRequest - { - Name = "TestTier_" + TestDataGenerator.GenerateString(12) - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); + var response = await _client.Tiers.CreateTier(new CreateTierRequest { Name = "TestTier_" + TestDataGenerator.GenerateString(12) }); + response.Should().BeASuccess(); - var response = await _tiersApi.CreateTier(requestConfiguration); - - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); - _tierId = response.Content.Result!.Id; + _tierId = response.Result!.Id; // allow the event queue to trigger the creation of this tier on the Quotas module Thread.Sleep(2000); @@ -49,22 +41,15 @@ public async Task GivenAValidTierWithAQuota() { await GivenAValidTier(); - var createTierQuotaRequest = new CreateTierQuotaRequest + var response = await _client.Tiers.AddTierQuota(_tierId, new CreateQuotaForTierRequest { MetricKey = "NumberOfSentMessages", Max = 2, Period = "Week" - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierQuotaRequest); + }); + response.Should().BeASuccess(); - var response = await _tiersApi.CreateTierQuota(requestConfiguration, _tierId); - - var actualStatusCode = (int)response.StatusCode; - actualStatusCode.Should().Be(201); - _tierQuotaDefinitionId = response.Content.Result!.Id; + _tierQuotaDefinitionId = response.Result!.Id; // allow the event queue to trigger the creation of this tier quota definition on the Quotas module Thread.Sleep(2000); @@ -73,90 +58,69 @@ public async Task GivenAValidTierWithAQuota() [When("a POST request is sent to the /Tiers/{t.id}/Quotas endpoint")] public async Task WhenAPOSTRequestIsSentToTheCreateTierQuotaEndpoint() { - var createTierQuotaRequest = new CreateTierQuotaRequest + _createTierQuotaResponse = await _client.Tiers.AddTierQuota(_tierId, new CreateQuotaForTierRequest { MetricKey = "NumberOfSentMessages", Max = 2, Period = "Week" - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierQuotaRequest); - - _response = await _tiersApi.CreateTierQuota(requestConfiguration, _tierId); + }); } [When("a POST request is sent to the /Tiers/{tierId}/Quotas endpoint with an inexistent tier id")] public async Task WhenAPOSTRequestIsSentToTheCreateTierQuotaEndpointForAnInexistentTier() { - var createTierQuotaRequest = new CreateTierQuotaRequest + _createTierQuotaResponse = await _client.Tiers.AddTierQuota("inexistentTierId", new CreateQuotaForTierRequest { MetricKey = "NumberOfSentMessages", Max = 2, Period = "Week" - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierQuotaRequest); - - _response = await _tiersApi.CreateTierQuota(requestConfiguration, "inexistentTierId"); + }); } [When("a DELETE request is sent to the /Tiers/{t.id}/Quotas/{q.id} endpoint")] - public async Task WhenADELETERequestIsSentToTheDeleteTierQuotaEndpoint() + public async Task WhenADeleteRequestIsSentToTheDeleteTierQuotaEndpoint() { - _deleteResponse = await _tiersApi.DeleteTierQuota(_tierId, _tierQuotaDefinitionId, _requestConfiguration); - _deleteResponse.Should().NotBeNull(); + _deleteResponse = await _client.Tiers.DeleteTierQuota(_tierId, _tierQuotaDefinitionId); } [When("a DELETE request is sent to the /Tiers/{t.id}/Quotas/{quotaId} endpoint with an inexistent quota id")] - public async Task WhenADELETERequestIsSentToTheDeleteTierQuotaEndpointForAnInexistentQuota() + public async Task WhenADeleteRequestIsSentToTheDeleteTierQuotaEndpointForAnInexistentQuota() { - _deleteResponse = await _tiersApi.DeleteTierQuota(_tierId, "inexistentQuotaId", _requestConfiguration); - _deleteResponse.Should().NotBeNull(); + _deleteResponse = await _client.Tiers.DeleteTierQuota(_tierId, "inexistentQuotaId"); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { - if (_response != null) - { - var actualStatusCode = (int)_response.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + if (_createTierQuotaResponse != null) + ((int)_createTierQuotaResponse!.Status).Should().Be(expectedStatusCode); if (_deleteResponse != null) - { - var actualStatusCode = (int)_deleteResponse.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_deleteResponse!.Status).Should().Be(expectedStatusCode); } [Then("the response contains a TierQuota")] public void ThenTheResponseContainsATierQuotaDefinition() { - _response!.AssertHasValue(); - _response!.AssertStatusCodeIsSuccess(); - _response!.AssertContentTypeIs("application/json"); - _response!.AssertContentCompliesWithSchema(); + _createTierQuotaResponse!.Should().BeASuccess(); + _createTierQuotaResponse!.ContentType.Should().StartWith("application/json"); + _createTierQuotaResponse.Should().ComplyWithSchema(); } [Then(@"the response content includes an error with the error code ""([^""]+)""")] public void ThenTheResponseContentIncludesAnErrorWithTheErrorCode(string errorCode) { - if (_response != null) + if (_createTierQuotaResponse != null) { - _response!.Content.Error.Should().NotBeNull(); - _response.Content.Error!.Code.Should().Be(errorCode); + _createTierQuotaResponse!.Error.Should().NotBeNull(); + _createTierQuotaResponse.Error!.Code.Should().Be(errorCode); } if (_deleteResponse != null) { - _deleteResponse.Content.Should().NotBeNull(); - _deleteResponse.Content!.Error.Should().NotBeNull(); - _deleteResponse.Content!.Error.Code.Should().Be(errorCode); + _deleteResponse!.Error.Should().NotBeNull(); + _deleteResponse.Error!.Code.Should().Be(errorCode); + ; } } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TiersStepDefinitions.cs b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TiersStepDefinitions.cs index 5fd0d74c52..f5819fd295 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TiersStepDefinitions.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/StepDefinitions/TiersStepDefinitions.cs @@ -1,8 +1,11 @@ -using System.Net; -using Backbone.AdminApi.Tests.Integration.API; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types.Requests; +using Backbone.AdminApi.Sdk.Endpoints.Tiers.Types.Responses; +using Backbone.AdminApi.Tests.Integration.Configuration; using Backbone.AdminApi.Tests.Integration.Extensions; -using Backbone.AdminApi.Tests.Integration.Models; +using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; using Backbone.UnitTestTools.Data; +using Microsoft.Extensions.Options; namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; @@ -12,16 +15,14 @@ namespace Backbone.AdminApi.Tests.Integration.StepDefinitions; [Scope(Feature = "DELETE Tier")] internal class TiersStepDefinitions : BaseStepDefinitions { - private readonly TiersApi _tiersApi; - private HttpResponse? _tierResponse; - private HttpResponse? _deleteResponse; - private HttpResponse>? _tiersResponse; + private ApiResponse? _tierResponse; + private ApiResponse? _deleteResponse; + private ApiResponse? _tiersResponse; private string _existingTierName; private string _existingTierId; - public TiersStepDefinitions(TiersApi tiersApi) + public TiersStepDefinitions(HttpClientFactory factory, IOptions options) : base(factory, options) { - _tiersApi = tiersApi; _existingTierName = string.Empty; _existingTierId = string.Empty; } @@ -29,20 +30,11 @@ public TiersStepDefinitions(TiersApi tiersApi) [Given("a Tier t")] public async Task GivenATier() { - var createTierRequest = new CreateTierRequest - { - Name = "TestTier_" + TestDataGenerator.GenerateString(12) - }; + var response = await _client.Tiers.CreateTier(new CreateTierRequest { Name = "TestTier_" + TestDataGenerator.GenerateString(12) }); + response.Should().BeASuccess(); - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - var response = await _tiersApi.CreateTier(requestConfiguration); - - response.StatusCode.Should().Be(HttpStatusCode.Created); - _existingTierName = response.Content.Result!.Name; - _existingTierId = response.Content.Result!.Id; + _existingTierName = response.Result!.Name; + _existingTierId = response.Result.Id; } [Given("the Tier T has one associated identity")] @@ -54,13 +46,10 @@ public void GivenTheTierTHasOneAssociatedIdentity() [Given("the Basic Tier as t")] public async Task GivenTheBasicTierAsT() { - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; + var response = await _client.Tiers.ListTiers(); + response.Should().BeASuccess(); - var response = await _tiersApi.GetTiers(requestConfiguration); - - response.StatusCode.Should().Be(HttpStatusCode.OK); - var basicTier = response.Content.Result!.Single(t => t.Name == "Basic"); + var basicTier = response.Result!.Single(t => t.Name == "Basic"); _existingTierName = basicTier.Name; _existingTierId = basicTier.Id; } @@ -68,95 +57,66 @@ public async Task GivenTheBasicTierAsT() [When("a GET request is sent to the /Tiers endpoint")] public async Task WhenAGETRequestIsSentToTheTiersEndpoint() { - _tiersResponse = await _tiersApi.GetTiers(_requestConfiguration); - _tiersResponse.Should().NotBeNull(); - _tiersResponse.Content.Should().NotBeNull(); + _tiersResponse = await _client.Tiers.ListTiers(); } [When("a POST request is sent to the /Tiers endpoint")] public async Task WhenAPOSTRequestIsSentToTheTiersEndpoint() { - var createTierRequest = new CreateTierRequest - { - Name = "TestTier_" + TestDataGenerator.GenerateString(12) - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - _tierResponse = await _tiersApi.CreateTier(requestConfiguration); + _tierResponse = await _client.Tiers.CreateTier(new CreateTierRequest { Name = "TestTier_" + TestDataGenerator.GenerateString(12) }); } [When("a POST request is sent to the /Tiers endpoint with the name t.Name")] public async Task WhenAPOSTRequestIsSentToTheTiersEndpointWithAnAlreadyExistingName() { - var createTierRequest = new CreateTierRequest - { - Name = _existingTierName - }; - - var requestConfiguration = _requestConfiguration.Clone(); - requestConfiguration.ContentType = "application/json"; - requestConfiguration.SetContent(createTierRequest); - - _tierResponse = await _tiersApi.CreateTier(requestConfiguration); + _tierResponse = await _client.Tiers.CreateTier(new CreateTierRequest { Name = _existingTierName }); } [When(@"a DELETE request is sent to the /Tiers/\{t\.Id} endpoint")] - public async Task WhenADELETERequestIsSentToTheTiersTierIdEndpoint() + public async Task WhenADeleteRequestIsSentToTheTiersTierIdEndpoint() { - _deleteResponse = await _tiersApi.DeleteTier(_requestConfiguration, _existingTierId); + _deleteResponse = await _client.Tiers.DeleteTier(_existingTierId); } [When(@"a DELETE request is sent to the /Tiers/\{t\.Id} endpoint with an inexistent id")] - public async Task WhenADELETERequestIsSentToTheTiersT_IdEndpointWithAnInexistentId() + public async Task WhenADeleteRequestIsSentToTheTiersT_IdEndpointWithAnInexistentId() { - _deleteResponse = await _tiersApi.DeleteTier(_requestConfiguration, "TIR00000000000000000"); + _deleteResponse = await _client.Tiers.DeleteTier("TIR00000000000000000"); } [Then("the response contains a paginated list of Tiers")] - public void ThenTheResponseContainsAList() + public void ThenTheResponseContainsAListOfTiers() { - _tiersResponse!.Content.Result.Should().NotBeNull(); - _tiersResponse!.Content.Result.Should().NotBeEmpty(); + _tiersResponse!.Should().BeASuccess(); + _tiersResponse!.ContentType.Should().StartWith("application/json"); + _tiersResponse.Should().ComplyWithSchema(); } [Then("the response contains a Tier")] public void ThenTheResponseContainsATier() { - _tierResponse!.AssertHasValue(); - _tierResponse!.AssertStatusCodeIsSuccess(); - _tierResponse!.AssertContentTypeIs("application/json"); - _tierResponse!.AssertContentCompliesWithSchema(); + _tierResponse!.Should().BeASuccess(); + _tierResponse!.ContentType.Should().StartWith("application/json"); + _tierResponse.Should().ComplyWithSchema(); } [Then(@"the response status code is (\d+) \(.+\)")] public void ThenTheResponseStatusCodeIs(int expectedStatusCode) { if (_tierResponse != null) - { - var actualStatusCode = (int)_tierResponse!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_tierResponse!.Status).Should().Be(expectedStatusCode); if (_tiersResponse != null) - { - var actualStatusCode = (int)_tiersResponse!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_tiersResponse!.Status).Should().Be(expectedStatusCode); if (_deleteResponse != null) - { - var actualStatusCode = (int)_deleteResponse!.StatusCode; - actualStatusCode.Should().Be(expectedStatusCode); - } + ((int)_deleteResponse!.Status).Should().Be(expectedStatusCode); } [Then(@"the response content includes an error with the error code ""([^""]+)""")] public void ThenTheResponseContentIncludesAnErrorWithTheErrorCode(string errorCode) { - _tierResponse!.Content.Error.Should().NotBeNull(); - _tierResponse.Content.Error!.Code.Should().Be(errorCode); + _tierResponse!.Error.Should().NotBeNull(); + _tierResponse.Error!.Code.Should().Be(errorCode); } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/Support/Dependencies.cs b/AdminApi/test/AdminApi.Tests.Integration/Support/Dependencies.cs index 8ce4b38d57..a2293b6b38 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/Support/Dependencies.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/Support/Dependencies.cs @@ -1,7 +1,4 @@ -using Backbone.AdminApi.Tests.Integration.API; using Backbone.AdminApi.Tests.Integration.Configuration; -using Backbone.Crypto.Abstractions; -using Backbone.Crypto.Implementations; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using SolidToken.SpecFlow.DependencyInjection; @@ -18,7 +15,7 @@ public static IServiceCollection CreateServices() var services = new ServiceCollection(); var config = new ConfigurationBuilder() - .AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), APP_SETTINGS_FILE), optional: false, reloadOnChange: false) + .AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), APP_SETTINGS_FILE), false, false) .Build(); services.ConfigureAndValidate(options => @@ -26,14 +23,6 @@ public static IServiceCollection CreateServices() ); services.AddSingleton(new HttpClientFactory(new CustomWebApplicationFactory())); - services.AddSingleton(SignatureHelper.CreateEd25519WithRawKeyFormat()); - - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); return services; } diff --git a/AdminApi/test/AdminApi.Tests.Integration/TestData/Identities.cs b/AdminApi/test/AdminApi.Tests.Integration/TestData/Identities.cs deleted file mode 100644 index 5f00df4830..0000000000 --- a/AdminApi/test/AdminApi.Tests.Integration/TestData/Identities.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Backbone.AdminApi.Tests.Integration.TestData; - -public static class Identities -{ - public const string IDENTITY_A = "id12Pbi7CgBHaFxge6uy1h6qUkedjQr8XHfm"; -} diff --git a/AdminApi/test/AdminApi.Tests.Integration/Support/JsonValidators.cs b/AdminApi/test/AdminApi.Tests.Integration/Validators/JsonValidators.cs similarity index 55% rename from AdminApi/test/AdminApi.Tests.Integration/Support/JsonValidators.cs rename to AdminApi/test/AdminApi.Tests.Integration/Validators/JsonValidators.cs index 996ea8a26c..c240345caf 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/Support/JsonValidators.cs +++ b/AdminApi/test/AdminApi.Tests.Integration/Validators/JsonValidators.cs @@ -1,11 +1,10 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; -using Newtonsoft.Json.Serialization; using NJsonSchema.NewtonsoftJson.Generation; using JsonSchemaGenerator = NJsonSchema.Generation.JsonSchemaGenerator; -namespace Backbone.AdminApi.Tests.Integration.Support; +namespace Backbone.AdminApi.Tests.Integration.Validators; public class JsonValidators { @@ -15,17 +14,19 @@ public static bool ValidateJsonSchema(string json, out IList errors) { if (CACHED_SCHEMAS.TryGetValue(typeof(T), out var schema)) { - var parsedJson = JObject.Parse(json); - return parsedJson.IsValid(schema, out errors); - } - - var settings = new NewtonsoftJsonSchemaGeneratorSettings - { - SerializerSettings = new JsonSerializerSettings + try { - ContractResolver = new CamelCasePropertyNamesContractResolver() + var parsedJson = JObject.Parse(json); + return parsedJson.IsValid(schema, out errors); } - }; + catch (JsonReaderException) + { + var parsedJson = JArray.Parse(json); + return parsedJson.IsValid(schema, out errors); + } + } + + var settings = new NewtonsoftJsonSchemaGeneratorSettings(); var generator = new JsonSchemaGenerator(settings); @@ -39,8 +40,15 @@ public static bool ValidateJsonSchema(string json, out IList errors) CACHED_SCHEMAS.Add(typeof(T), schema); - var responseJson = JObject.Parse(json); - - return responseJson.IsValid(schema, out errors); + try + { + var responseJson = JObject.Parse(json); + return responseJson.IsValid(schema, out errors); + } + catch (JsonReaderException) + { + var responseJson = JArray.Parse(json); + return responseJson.IsValid(schema, out errors); + } } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/api.appsettings.local.override.json b/AdminApi/test/AdminApi.Tests.Integration/api.appsettings.local.override.json index 0c5f646a9c..e2ed0cc0d6 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/api.appsettings.local.override.json +++ b/AdminApi/test/AdminApi.Tests.Integration/api.appsettings.local.override.json @@ -12,16 +12,20 @@ "Modules": { "Quotas": { "Infrastructure": { - "SqlDatabase": { - "ConnectionString": "Server=localhost;Database=enmeshed;User Id=quotas;Password=Passw0rd;TrustServerCertificate=True" - } + "SqlDatabase": { + "Provider": "Postgres", + "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres + //"ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" + } } }, "Devices": { "Infrastructure": { - "SqlDatabase": { - "ConnectionString": "Server=localhost;Database=enmeshed;User Id=devices;Password=Passw0rd;TrustServerCertificate=True" - } + "SqlDatabase": { + "Provider": "Postgres", + "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres + //"ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" + } } } } diff --git a/AdminApi/test/AdminApi.Tests.Integration/appsettings.json b/AdminApi/test/AdminApi.Tests.Integration/appsettings.json index 340e0c4932..c0a360aea2 100644 --- a/AdminApi/test/AdminApi.Tests.Integration/appsettings.json +++ b/AdminApi/test/AdminApi.Tests.Integration/appsettings.json @@ -1,7 +1,6 @@ { "AdminApi": { "Http": { - "BaseUrl": "http://localhost:5173", "ApiKey": "test" } } diff --git a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs index 1a026960e8..f0132e713e 100644 --- a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs +++ b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/EndpointClient.cs @@ -5,7 +5,6 @@ using System.Text.Json; using System.Web; using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; -using Newtonsoft.Json; using JsonSerializer = System.Text.Json.JsonSerializer; namespace Backbone.BuildingBlocks.SDK.Endpoints.Common; @@ -111,7 +110,8 @@ private async Task> Execute(HttpRequestMessage request) var deserializedResponseContent = JsonSerializer.Deserialize>(responseContent, _jsonSerializerOptions); deserializedResponseContent!.Status = statusCode; - deserializedResponseContent.RawContent = JsonConvert.SerializeObject(deserializedResponseContent.Result); + deserializedResponseContent.RawContent = await response.Content.ReadAsStringAsync(); + deserializedResponseContent.ContentType = response.Content.Headers.ContentType?.MediaType; return deserializedResponseContent; } @@ -129,7 +129,10 @@ private async Task> ExecuteOData(HttpRequestMessage request) } var deserializedResponseContent = JsonSerializer.Deserialize>(responseContent, _jsonSerializerOptions)!; - return deserializedResponseContent.ToApiResponse(statusCode); + var rawContent = await response.Content.ReadAsStringAsync(); + deserializedResponseContent.ContentType = response.Content.Headers.ContentType?.MediaType; + + return deserializedResponseContent.ToApiResponse(statusCode, rawContent); } private async Task ExecuteRaw(HttpRequestMessage request) diff --git a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ApiResponse.cs b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ApiResponse.cs index c8e741e40d..9baff27049 100644 --- a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ApiResponse.cs +++ b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ApiResponse.cs @@ -20,5 +20,6 @@ public class ApiResponse public ApiError? Error { get; set; } public PaginationData? Pagination { get; set; } public HttpStatusCode Status { get; set; } + public string? ContentType { get; set; } public string? RawContent { get; set; } } diff --git a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ODataResponse.cs b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ODataResponse.cs index cd64fbab17..de1f8fe776 100644 --- a/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ODataResponse.cs +++ b/BuildingBlocks/src/BuildingBlocks.SDK/Endpoints/Common/Types/ODataResponse.cs @@ -5,6 +5,13 @@ namespace Backbone.BuildingBlocks.SDK.Endpoints.Common.Types; public class ODataResponse { public TResult? Value { get; set; } + public string? ContentType { get; set; } - public ApiResponse ToApiResponse(HttpStatusCode status) => new() { Result = Value, Status = status }; + public ApiResponse ToApiResponse(HttpStatusCode status, string? rawContent) => new() + { + Result = Value, + ContentType = ContentType, + Status = status, + RawContent = rawContent + }; } diff --git a/ConsumerApi.Tests.Integration/Configuration/Settings.cs b/ConsumerApi.Tests.Integration/Configuration/Settings.cs index a6c13d2925..c8e4c782ec 100644 --- a/ConsumerApi.Tests.Integration/Configuration/Settings.cs +++ b/ConsumerApi.Tests.Integration/Configuration/Settings.cs @@ -6,6 +6,7 @@ public class HttpConfiguration { [Required] public string BaseUrl { get; set; } = string.Empty; + [Required] public ClientCredentialsConfiguration ClientCredentials { get; set; } = new(); } @@ -14,6 +15,7 @@ public class ClientCredentialsConfiguration { [Required] public string ClientId { get; set; } = string.Empty; + [Required] public string ClientSecret { get; set; } = string.Empty; } diff --git a/Modules/Challenges/src/Challenges.Application/Challenges/DTOs/ChallengeDTO.cs b/Modules/Challenges/src/Challenges.Application/Challenges/DTOs/ChallengeDTO.cs index 664f91961b..5531a639ad 100644 --- a/Modules/Challenges/src/Challenges.Application/Challenges/DTOs/ChallengeDTO.cs +++ b/Modules/Challenges/src/Challenges.Application/Challenges/DTOs/ChallengeDTO.cs @@ -1,14 +1,19 @@ +using AutoMapper; using Backbone.BuildingBlocks.Application.Abstractions.Infrastructure.Mapping; -using Backbone.DevelopmentKit.Identity.ValueObjects; using Backbone.Modules.Challenges.Domain.Entities; -using Backbone.Modules.Challenges.Domain.Ids; namespace Backbone.Modules.Challenges.Application.Challenges.DTOs; -public class ChallengeDTO : IMapTo +public class ChallengeDTO : IHaveCustomMapping { - public required ChallengeId Id { get; set; } + public required string Id { get; set; } public required DateTime ExpiresAt { get; set; } - public IdentityAddress? CreatedBy { get; set; } - public DeviceId? CreatedByDevice { get; set; } + public string? CreatedBy { get; set; } + public string? CreatedByDevice { get; set; } + + public void CreateMappings(Profile configuration) + { + configuration.CreateMap() + .ForMember(dto => dto.Id, expression => expression.MapFrom(m => m.Id.Value)); + } } diff --git a/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/CreateIdentityCommand.cs b/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/CreateIdentityCommand.cs index 2e817fe753..92b0bf6fb2 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/CreateIdentityCommand.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/CreateIdentityCommand.cs @@ -10,5 +10,4 @@ public class CreateIdentityCommand : IRequest public required string DevicePassword { get; set; } public required byte IdentityVersion { get; set; } public required SignedChallengeDTO SignedChallenge { get; set; } - public bool ShouldValidateChallenge { get; set; } = true; // Used to avoid challenge validation when creating Identities through the AdminApi for Integration testing purposes. } diff --git a/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/Handler.cs b/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/Handler.cs index cc9e3a0966..50ad6426bd 100644 --- a/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/Handler.cs +++ b/Modules/Devices/src/Devices.Application/Identities/Commands/CreateIdentity/Handler.cs @@ -35,8 +35,8 @@ public Handler(ChallengeValidator challengeValidator, ILogger logger, I public async Task Handle(CreateIdentityCommand command, CancellationToken cancellationToken) { var publicKey = PublicKey.FromBytes(command.IdentityPublicKey); - if (command.ShouldValidateChallenge) - await _challengeValidator.Validate(command.SignedChallenge, publicKey); + + await _challengeValidator.Validate(command.SignedChallenge, publicKey); _logger.LogTrace("Challenge successfully validated."); diff --git a/docker-compose/adminui.appsettings.override.json b/docker-compose/adminui.appsettings.override.json index 239ff696f5..d0b63bd8d6 100644 --- a/docker-compose/adminui.appsettings.override.json +++ b/docker-compose/adminui.appsettings.override.json @@ -29,6 +29,21 @@ } }, "Modules": { + "Challenges": { + "Application": { + "Pagination": { + "DefaultPageSize": 50, + "MaxPageSize": 200 + } + }, + "Infrastructure": { + "SqlDatabase": { + "Provider": "Postgres", + "ConnectionString": "User ID=challenges;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres + //"ConnectionString": "Server=localhost;Database=enmeshed;User Id=challenges;Password=Passw0rd;TrustServerCertificate=True" // sqlserver + } + } + }, "Devices": { "Application": { "Pagination": {