From b2635193dca106cf553bb0dbcf2edfc51f316a8c Mon Sep 17 00:00:00 2001 From: Sergio Matias Urquin Date: Tue, 29 Apr 2025 18:44:41 -0600 Subject: [PATCH] Add project files. --- .dockerignore | 30 +++ .../Core.Blueprint.Application.csproj | 23 ++ .../BlobStorage/Adapter/StoragePort.cs | 25 +++ .../BlobStorage/Input/DeleteBlobRequest.cs | 14 ++ .../BlobStorage/Input/DownloadBlobRequest.cs | 13 ++ .../BlobStorage/Input/GetBlobListRequest.cs | 13 ++ .../BlobStorage/Input/UploadBlobRequest.cs | 16 ++ .../BlobStorage/Ports/IStoragePort.cs | 16 ++ .../UsesCases/BlobStorage/Storage.cs | 160 ++++++++++++++ .../UsesCases/BlobStorage/StorageHandler.cs | 151 ++++++++++++++ .../Validator/DeleteBlobValidator.cs | 13 ++ .../Validator/DownloadBlobValidator.cs | 13 ++ .../Validator/UploadBlobValidator.cs | 14 ++ .../KeyVault/Adapter/KeyVaultPort.cs | 20 ++ .../KeyVault/Input/CreateSecretRequest.cs | 16 ++ .../KeyVault/Input/DeleteSecretRequest.cs | 14 ++ .../KeyVault/Input/GetSecretRequest.cs | 14 ++ .../KeyVault/Input/UpdateSecretRequest.cs | 14 ++ .../UsesCases/KeyVault/KeyVaultHandler.cs | 160 ++++++++++++++ .../UsesCases/KeyVault/Ports/IKeyVaultPort.cs | 15 ++ .../Validator/CreateSecretValidator.cs | 14 ++ .../Validator/DeleteSecretValidator.cs | 13 ++ .../KeyVault/Validator/GetSecretValidator.cs | 13 ++ .../Validator/UpdateSecretValidator.cs | 14 ++ .../UsesCases/Mongo/Adapter/MongoPort.cs | 19 ++ .../Mongo/Input/CreateBlueprintRequest.cs | 16 ++ .../Mongo/Input/DeleteBlueprintRequest.cs | 14 ++ .../Mongo/Input/GetAllBlueprintsRequest.cs | 12 ++ .../Mongo/Input/GetBlueprintRequest.cs | 14 ++ .../Mongo/Input/UpdateBlueprintRequest.cs | 22 ++ .../UsesCases/Mongo/MongoHandler.cs | 197 ++++++++++++++++++ .../UsesCases/Mongo/Ports/IMongoPort.cs | 14 ++ .../Validator/CreateBlueprintValidator.cs | 13 ++ .../Validator/DeleteBlueprintValidator.cs | 13 ++ .../Mongo/Validator/GetBlueprintValidator.cs | 13 ++ .../Validator/UpdateBlueprintValidator.cs | 17 ++ .../UsesCases/SQL/Adapter/SQLPort.cs | 19 ++ .../SQL/Input/CreateUserProjectRequest.cs | 16 ++ .../SQL/Input/DeleteUserProjectRequest.cs | 14 ++ .../SQL/Input/GetAllUserProjectsRequest.cs | 12 ++ .../SQL/Input/GetUserProjectRequest.cs | 14 ++ .../SQL/Input/UpdateUserProjectRequest.cs | 23 ++ .../UsesCases/SQL/Ports/ISQLPort.cs | 14 ++ .../UsesCases/SQL/SQLHandler.cs | 193 +++++++++++++++++ .../Validator/CreateUserProjectValidator.cs | 15 ++ .../Validator/DeleteUserProjectValidator.cs | 13 ++ .../SQL/Validator/GetUserProjectValidator.cs | 13 ++ .../Validator/UpdateUserProjectValidator.cs | 19 ++ .../Controllers/BlobStorageController.cs | 119 +++++++++++ .../Controllers/KeyVaultController.cs | 124 +++++++++++ .../Controllers/MongoBluePrintController.cs | 142 +++++++++++++ .../Controllers/SQLUserProjectController.cs | 142 +++++++++++++ .../Core.Blueprint.Service.API.csproj | 25 +++ .../Core.Blueprint.Service.API.http | 6 + Core.Blueprint.Service.API/Dockerfile | 25 +++ .../Extensions/ServiceCollectionExtension.cs | 111 ++++++++++ .../Extensions/SwaggerExtensions.cs | 71 +++++++ Core.Blueprint.Service.API/Program.cs | 98 +++++++++ .../Properties/launchSettings.json | 52 +++++ .../appsettings.Development.json | 8 + .../appsettings.Local.json | 12 ++ Core.Blueprint.Service.API/appsettings.json | 12 ++ .../Core.Blueprint.Service.Domain.csproj | 9 + .../Dtos/SampleImageUrlDto.cs | 13 ++ .../Entities/BlobSampleImageEntity.cs | 14 ++ .../Entities/SecretEntity.cs | 13 ++ .../Entities/SqlSampleItemEntity.cs | 17 ++ .../RegisterClientConfiguration.cs | 58 ++++++ .../Clients/Adapters/BlueprintAdapter.cs | 15 ++ .../Clients/Adapters/KeyVaultAdapter.cs | 10 + .../Clients/Adapters/StatusEnum.cs | 15 ++ .../Clients/Adapters/UserProjectAdapter.cs | 16 ++ .../Clients/IBlueprintServiceClient.cs | 67 ++++++ .../Clients/Requests/BlueprintRequest.cs | 8 + .../Clients/Requests/UserProjectRequest.cs | 9 + .../Core.Blueprint.Service.External.csproj | 25 +++ .../GatewayConfiguration.cs | 24 +++ .../GatewaySettingsConfiguration.cs | 43 ++++ .../Token/AuthenticatedHttpClientHandler.cs | 32 +++ .../Helpers/Token/HttpContextTokenProvider.cs | 31 +++ .../Helpers/Token/ITokenProvider.cs | 19 ++ .../Core.Blueprint.Service.Testing.csproj | 25 +++ .../GlobalUsings.cs | 1 + Core.Blueprint.Service.Testing/UnitTest1.cs | 11 + .../BluePrint/BlueprintService.cs | 90 ++++++++ .../Configuration/UseCasesConfiguration.cs | 74 +++++++ .../Core.Blueprint.Service.UseCases.csproj | 18 ++ .../Adapter/CreateSampleImagePort.cs | 15 ++ .../CreateSampleItemHandler.cs | 44 ++++ .../Input/CreateSampleImageRequest.cs | 14 ++ .../Ports/ICreateSampleImagePort.cs | 9 + .../Validator/CreateSampleImageValidator.cs | 15 ++ .../Adapter/CreateSampleItemPort.cs | 15 ++ .../CreateSampleItemHandler.cs | 44 ++++ .../Input/CreateSampleItemRequest.cs | 14 ++ .../Ports/ICreateSampleItemPort.cs | 9 + .../Validator/CreateSampleItemValidator.cs | 16 ++ .../Adapter/DeleteSampleItemPort.cs | 15 ++ .../DeleteSampleItemHandler.cs | 42 ++++ .../Input/DeleteSampleItemRequest.cs | 13 ++ .../Ports/IDeleteSampleItemPort.cs | 9 + .../Validator/DeleteSampleItemValidator.cs | 15 ++ .../Adapter/GetOneSampleItemPort.cs | 15 ++ .../GetOneSampleItemHandler.cs | 42 ++++ .../Input/GetOneSampleItemRequest.cs | 17 ++ .../Ports/IGetOneSampleItemPort.cs | 9 + .../Validator/GetOneSampleItemValidator.cs | 15 ++ .../Adapter/GetSampleImagePort.cs | 15 ++ .../GetSampleImage/GetSampleImageHandler.cs | 43 ++++ .../Input/GetSampleImageRequest.cs | 12 ++ .../Ports/IGetSampleImagePort.cs | 10 + .../Validator/GetSampleImageValidator.cs | 15 ++ .../Adapter/GetSampleItemsPort.cs | 15 ++ .../GetSampleItems/GetSampleItemsHandler.cs | 42 ++++ .../Input/GetSampleItemsRequest.cs | 15 ++ .../Ports/IGetSampleItemsPort.cs | 9 + .../Validator/GetSampleItemValidator.cs | 16 ++ .../GetSecret/Adapter/GetSecretPort.cs | 22 ++ .../GetSecret/GetSecretHandler.cs | 50 +++++ .../GetSecret/Input/GetSecretRequest.cs | 19 ++ .../GetSecret/Ports/IGetSecretPort.cs | 15 ++ .../GetSecret/Validator/GetSecretValidator.cs | 21 ++ .../Adapter/GetUploadUrlPort.cs | 16 ++ .../GetUploadImageUrl/GetUploadUrlHandler.cs | 42 ++++ .../Input/GetUploadUrlRequest.cs | 12 ++ .../Ports/IGetUploadUrlPort.cs | 10 + .../Validator/GetUploadUrlValidator.cs | 16 ++ .../Adapter/UpdateSampleItemPort.cs | 15 ++ .../Input/UpdateSampleItemRequest.cs | 17 ++ .../Ports/IUpdateSampleItemPort.cs | 9 + .../UpdateSampleItemHandler.cs | 45 ++++ .../Validator/UpdateSampleItemValidator.cs | 16 ++ Core.Blueprint.Service.sln | 55 +++++ 133 files changed, 4100 insertions(+) create mode 100644 .dockerignore create mode 100644 Core.Blueprint.Application/Core.Blueprint.Application.csproj create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Adapter/StoragePort.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Input/DeleteBlobRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Input/DownloadBlobRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Input/GetBlobListRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Input/UploadBlobRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Ports/IStoragePort.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Storage.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/StorageHandler.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DeleteBlobValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DownloadBlobValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/BlobStorage/Validator/UploadBlobValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Adapter/KeyVaultPort.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Input/CreateSecretRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Input/DeleteSecretRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Input/GetSecretRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Input/UpdateSecretRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/KeyVaultHandler.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Ports/IKeyVaultPort.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Validator/CreateSecretValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Validator/DeleteSecretValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Validator/GetSecretValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/KeyVault/Validator/UpdateSecretValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Adapter/MongoPort.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Input/CreateBlueprintRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Input/DeleteBlueprintRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Input/GetAllBlueprintsRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Input/GetBlueprintRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Input/UpdateBlueprintRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/MongoHandler.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Ports/IMongoPort.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Validator/CreateBlueprintValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Validator/DeleteBlueprintValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Validator/GetBlueprintValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/Mongo/Validator/UpdateBlueprintValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Adapter/SQLPort.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Input/CreateUserProjectRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Input/DeleteUserProjectRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Input/GetAllUserProjectsRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Input/GetUserProjectRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Input/UpdateUserProjectRequest.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Ports/ISQLPort.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/SQLHandler.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Validator/CreateUserProjectValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Validator/DeleteUserProjectValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Validator/GetUserProjectValidator.cs create mode 100644 Core.Blueprint.Application/UsesCases/SQL/Validator/UpdateUserProjectValidator.cs create mode 100644 Core.Blueprint.Service.API/Controllers/BlobStorageController.cs create mode 100644 Core.Blueprint.Service.API/Controllers/KeyVaultController.cs create mode 100644 Core.Blueprint.Service.API/Controllers/MongoBluePrintController.cs create mode 100644 Core.Blueprint.Service.API/Controllers/SQLUserProjectController.cs create mode 100644 Core.Blueprint.Service.API/Core.Blueprint.Service.API.csproj create mode 100644 Core.Blueprint.Service.API/Core.Blueprint.Service.API.http create mode 100644 Core.Blueprint.Service.API/Dockerfile create mode 100644 Core.Blueprint.Service.API/Extensions/ServiceCollectionExtension.cs create mode 100644 Core.Blueprint.Service.API/Extensions/SwaggerExtensions.cs create mode 100644 Core.Blueprint.Service.API/Program.cs create mode 100644 Core.Blueprint.Service.API/Properties/launchSettings.json create mode 100644 Core.Blueprint.Service.API/appsettings.Development.json create mode 100644 Core.Blueprint.Service.API/appsettings.Local.json create mode 100644 Core.Blueprint.Service.API/appsettings.json create mode 100644 Core.Blueprint.Service.Domain/Core.Blueprint.Service.Domain.csproj create mode 100644 Core.Blueprint.Service.Domain/Dtos/SampleImageUrlDto.cs create mode 100644 Core.Blueprint.Service.Domain/Entities/BlobSampleImageEntity.cs create mode 100644 Core.Blueprint.Service.Domain/Entities/SecretEntity.cs create mode 100644 Core.Blueprint.Service.Domain/Entities/SqlSampleItemEntity.cs create mode 100644 Core.Blueprint.Service.External/ClientConfiguration/RegisterClientConfiguration.cs create mode 100644 Core.Blueprint.Service.External/Clients/Adapters/BlueprintAdapter.cs create mode 100644 Core.Blueprint.Service.External/Clients/Adapters/KeyVaultAdapter.cs create mode 100644 Core.Blueprint.Service.External/Clients/Adapters/StatusEnum.cs create mode 100644 Core.Blueprint.Service.External/Clients/Adapters/UserProjectAdapter.cs create mode 100644 Core.Blueprint.Service.External/Clients/IBlueprintServiceClient.cs create mode 100644 Core.Blueprint.Service.External/Clients/Requests/BlueprintRequest.cs create mode 100644 Core.Blueprint.Service.External/Clients/Requests/UserProjectRequest.cs create mode 100644 Core.Blueprint.Service.External/Core.Blueprint.Service.External.csproj create mode 100644 Core.Blueprint.Service.External/GatewayConfigurations/GatewayConfiguration.cs create mode 100644 Core.Blueprint.Service.External/GatewayConfigurations/GatewaySettingsConfiguration.cs create mode 100644 Core.Blueprint.Service.External/Helpers/Token/AuthenticatedHttpClientHandler.cs create mode 100644 Core.Blueprint.Service.External/Helpers/Token/HttpContextTokenProvider.cs create mode 100644 Core.Blueprint.Service.External/Helpers/Token/ITokenProvider.cs create mode 100644 Core.Blueprint.Service.Testing/Core.Blueprint.Service.Testing.csproj create mode 100644 Core.Blueprint.Service.Testing/GlobalUsings.cs create mode 100644 Core.Blueprint.Service.Testing/UnitTest1.cs create mode 100644 Core.Blueprint.Service.UseCases/BluePrint/BlueprintService.cs create mode 100644 Core.Blueprint.Service.UseCases/Configuration/UseCasesConfiguration.cs create mode 100644 Core.Blueprint.Service.UseCases/Core.Blueprint.Service.UseCases.csproj create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleImage/Adapter/CreateSampleImagePort.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleImage/CreateSampleItemHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleImage/Input/CreateSampleImageRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleImage/Ports/ICreateSampleImagePort.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleImage/Validator/CreateSampleImageValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleItem/Adapter/CreateSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleItem/CreateSampleItemHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleItem/Input/CreateSampleItemRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleItem/Ports/ICreateSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/CreateSampleItem/Validator/CreateSampleItemValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/DeleteSampleItem/Adapter/DeleteSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/DeleteSampleItem/DeleteSampleItemHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/DeleteSampleItem/Input/DeleteSampleItemRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/DeleteSampleItem/Ports/IDeleteSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/DeleteSampleItem/Validator/DeleteSampleItemValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/GetOneSampleItem/Adapter/GetOneSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetOneSampleItem/GetOneSampleItemHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/GetOneSampleItem/Input/GetOneSampleItemRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/GetOneSampleItem/Ports/IGetOneSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetOneSampleItem/Validator/GetOneSampleItemValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleImage/Adapter/GetSampleImagePort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleImage/GetSampleImageHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleImage/Input/GetSampleImageRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleImage/Ports/IGetSampleImagePort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleImage/Validator/GetSampleImageValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleItems/Adapter/GetSampleItemsPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleItems/GetSampleItemsHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleItems/Input/GetSampleItemsRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleItems/Ports/IGetSampleItemsPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSampleItems/Validator/GetSampleItemValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSecret/Adapter/GetSecretPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSecret/GetSecretHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSecret/Input/GetSecretRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSecret/Ports/IGetSecretPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetSecret/Validator/GetSecretValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/GetUploadImageUrl/Adapter/GetUploadUrlPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetUploadImageUrl/GetUploadUrlHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/GetUploadImageUrl/Input/GetUploadUrlRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/GetUploadImageUrl/Ports/IGetUploadUrlPort.cs create mode 100644 Core.Blueprint.Service.UseCases/GetUploadImageUrl/Validator/GetUploadUrlValidator.cs create mode 100644 Core.Blueprint.Service.UseCases/UpdateSampleItem/Adapter/UpdateSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/UpdateSampleItem/Input/UpdateSampleItemRequest.cs create mode 100644 Core.Blueprint.Service.UseCases/UpdateSampleItem/Ports/IUpdateSampleItemPort.cs create mode 100644 Core.Blueprint.Service.UseCases/UpdateSampleItem/UpdateSampleItemHandler.cs create mode 100644 Core.Blueprint.Service.UseCases/UpdateSampleItem/Validator/UpdateSampleItemValidator.cs create mode 100644 Core.Blueprint.Service.sln diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/Core.Blueprint.Application/Core.Blueprint.Application.csproj b/Core.Blueprint.Application/Core.Blueprint.Application.csproj new file mode 100644 index 0000000..7adede3 --- /dev/null +++ b/Core.Blueprint.Application/Core.Blueprint.Application.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Adapter/StoragePort.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Adapter/StoragePort.cs new file mode 100644 index 0000000..649e77e --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Adapter/StoragePort.cs @@ -0,0 +1,25 @@ +using Core.Blueprint.Application.UsesCases.BlobStorage.Ports; +using Core.Blueprint.Storage; +using Core.Blueprint.Storage.Adapters; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Application.UsesCases.BlobStorage.Adapter +{ + public class StoragePort : BasePresenter, IStoragePort + { + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(BlobFileAdapter output) + { + ViewModel = new OkObjectResult(output); + } + + public void Success(BlobDownloadUriAdapter output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Input/DeleteBlobRequest.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/DeleteBlobRequest.cs new file mode 100644 index 0000000..9fb7cc3 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/DeleteBlobRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class DeleteBlobRequest : Notificator, ICommand + { + public string BlobName { get; set; } + + public bool Validate() + { + return !string.IsNullOrEmpty(BlobName); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Input/DownloadBlobRequest.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/DownloadBlobRequest.cs new file mode 100644 index 0000000..c9f1400 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/DownloadBlobRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class DownloadBlobRequest : Notificator, ICommand + { + public string BlobName { get; set; } = null!; + public bool Validate() + { + return !string.IsNullOrEmpty(BlobName); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Input/GetBlobListRequest.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/GetBlobListRequest.cs new file mode 100644 index 0000000..c9acd9e --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/GetBlobListRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class GetBlobListRequest : Notificator, ICommand + { + public string? Prefix { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Input/UploadBlobRequest.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/UploadBlobRequest.cs new file mode 100644 index 0000000..6e47c85 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Input/UploadBlobRequest.cs @@ -0,0 +1,16 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class UploadBlobRequest : Notificator, ICommand + { + public string BlobName { get; set; } = null!; + + public byte[] File { get; set; } = null!; + + public bool Validate() + { + return !string.IsNullOrEmpty(BlobName); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Ports/IStoragePort.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Ports/IStoragePort.cs new file mode 100644 index 0000000..5085539 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Ports/IStoragePort.cs @@ -0,0 +1,16 @@ +using Core.Blueprint.Storage; +using Core.Blueprint.Storage.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.BlobStorage.Ports +{ + public interface IStoragePort : IBasePort, + ICommandSuccessPort>, + ICommandSuccessPort, + ICommandSuccessPort, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort, + IBadRequestPort + { + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Storage.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Storage.cs new file mode 100644 index 0000000..a6620a8 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Storage.cs @@ -0,0 +1,160 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using Core.Blueprint.Application.UsesCases.KeyVault.Ports; +using Core.Blueprint.KeyVault; +using Core.Blueprint.Service.External.Clients; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.KeyVault +{ + public class Storage : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly IKeyVaultPort _port; + private readonly IValidator _createKeyVaultValidator; + private readonly IValidator _getKeyVaultValidator; + private readonly IValidator _updateKeyVaultValidator; + private readonly IValidator _deleteKeyVaultValidator; + private readonly IBlueprintServiceClient _keyVaultDALService; + + public Storage( + IKeyVaultPort port, + IValidator createKeyVaultValidator, + IValidator getKeyVaultValidator, + IValidator updateKeyVaultValidator, + IValidator deleteKeyVaultValidator, + IBlueprintServiceClient keyVaultDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _createKeyVaultValidator = createKeyVaultValidator ?? throw new ArgumentNullException(nameof(createKeyVaultValidator)); + _getKeyVaultValidator = getKeyVaultValidator ?? throw new ArgumentNullException(nameof(getKeyVaultValidator)); + _updateKeyVaultValidator = updateKeyVaultValidator ?? throw new ArgumentNullException(nameof(updateKeyVaultValidator)); + _deleteKeyVaultValidator = deleteKeyVaultValidator ?? throw new ArgumentNullException(nameof(deleteKeyVaultValidator)); + _keyVaultDALService = keyVaultDALService ?? throw new ArgumentNullException(nameof(keyVaultDALService)); + } + + public async ValueTask ExecuteAsync(CreateBlobRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_createKeyVaultValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new KeyVaultRequest + { + Name = command.Name, + Value = command.Value, + }; + + var result = await _keyVaultDALService.CreateSecretAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetBlobListRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _keyVaultDALService.GetSecretByNameAsync("", cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(UpdateBlobRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updateKeyVaultValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new KeyVaultRequest + { + Name = command.Name, + Value = command.Value, + }; + + var result = await _keyVaultDALService.UpdateSecretAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(DeleteBlobRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_deleteKeyVaultValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _keyVaultDALService.DeleteSecretAsync(command.Name, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/StorageHandler.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/StorageHandler.cs new file mode 100644 index 0000000..7a33c02 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/StorageHandler.cs @@ -0,0 +1,151 @@ +using Core.Blueprint.Application.UsesCases.BlobStorage.Ports; +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using Core.Blueprint.Service.External.Clients; +using Core.Blueprint.Storage; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.KeyVault +{ + public class StorageHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly IStoragePort _port; + private readonly IValidator _uploadBlobValidator; + private readonly IValidator _downloadBlobValidator; + private readonly IValidator _deleteBlobValidator; + private readonly IBlueprintServiceClient _storageDALService; + + public StorageHandler( + IStoragePort port, + IValidator uploadBlobValidator, + IValidator downloadBlobValidator, + IValidator deleteBlobValidator, + IBlueprintServiceClient storageDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _uploadBlobValidator = uploadBlobValidator ?? throw new ArgumentNullException(nameof(uploadBlobValidator)); + _downloadBlobValidator = downloadBlobValidator ?? throw new ArgumentNullException(nameof(downloadBlobValidator)); + _deleteBlobValidator = deleteBlobValidator ?? throw new ArgumentNullException(nameof(deleteBlobValidator)); + _storageDALService = storageDALService ?? throw new ArgumentNullException(nameof(storageDALService)); + } + + public async ValueTask ExecuteAsync(UploadBlobRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_uploadBlobValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new BlobAddDto + { + FileName = command.BlobName, + FileContent = command.File + }; + + var result = await _storageDALService.UploadBlobAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetBlobListRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _storageDALService.GetBlobListAsync(command.Prefix, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(DownloadBlobRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_downloadBlobValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _storageDALService.DownloadBlobAsync(command.BlobName, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(DeleteBlobRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_deleteBlobValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _storageDALService.DeleteBlobAsync(command.BlobName, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DeleteBlobValidator.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DeleteBlobValidator.cs new file mode 100644 index 0000000..ebf6b2d --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DeleteBlobValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.KeyVault.Validator +{ + public class DeleteBlobValidator : AbstractValidator + { + public DeleteBlobValidator() + { + RuleFor(i => i.BlobName).NotEmpty().NotNull().OverridePropertyName(x => x.BlobName).WithName("Blob Name").WithMessage("Blob Name is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DownloadBlobValidator.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DownloadBlobValidator.cs new file mode 100644 index 0000000..720f98e --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/DownloadBlobValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.KeyVault.Validator +{ + public class DownloadBlobValidator : AbstractValidator + { + public DownloadBlobValidator() + { + RuleFor(i => i.BlobName).NotEmpty().NotNull().OverridePropertyName(x => x.BlobName).WithName("Blob Name").WithMessage("Blob Name is Obligatory."); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/UploadBlobValidator.cs b/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/UploadBlobValidator.cs new file mode 100644 index 0000000..ba32231 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/BlobStorage/Validator/UploadBlobValidator.cs @@ -0,0 +1,14 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.KeyVault.Validator +{ + public class UploadBlobValidator : AbstractValidator + { + public UploadBlobValidator() + { + RuleFor(i => i.BlobName).NotEmpty().NotNull().OverridePropertyName(x => x.BlobName).WithName("Blob Name").WithMessage("Blob Name is Obligatory."); + RuleFor(i => i.File).NotNull().OverridePropertyName(x => x.File).WithName("Blob File").WithMessage("Blob File is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Adapter/KeyVaultPort.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Adapter/KeyVaultPort.cs new file mode 100644 index 0000000..921e8db --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Adapter/KeyVaultPort.cs @@ -0,0 +1,20 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Ports; +using Core.Blueprint.KeyVault; +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Application.UsesCases.MongoStorage.Adapter +{ + public class KeyVaultPort : BasePresenter, IKeyVaultPort + { + public void Success(KeyVaultResponse output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(KeyVaultAdapter output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Input/CreateSecretRequest.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Input/CreateSecretRequest.cs new file mode 100644 index 0000000..1259295 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Input/CreateSecretRequest.cs @@ -0,0 +1,16 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class CreateSecretRequest : Notificator, ICommand + { + public string Name { get; set; } = null!; + + public string Value { get; set; } = null!; + + public bool Validate() + { + return !string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Value); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Input/DeleteSecretRequest.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Input/DeleteSecretRequest.cs new file mode 100644 index 0000000..67d419c --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Input/DeleteSecretRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class DeleteSecretRequest : Notificator, ICommand + { + public string Name { get; set; } + + public bool Validate() + { + return !string.IsNullOrEmpty(Name); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Input/GetSecretRequest.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Input/GetSecretRequest.cs new file mode 100644 index 0000000..21160a3 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Input/GetSecretRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class GetSecretRequest : Notificator, ICommand + { + public string Name { get; set; } + + public bool Validate() + { + return string.IsNullOrEmpty(Name); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Input/UpdateSecretRequest.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Input/UpdateSecretRequest.cs new file mode 100644 index 0000000..fff832a --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Input/UpdateSecretRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Input +{ + public class UpdateSecretRequest : Notificator, ICommand + { + public string Name { get; set; } = null!; + public string Value { get; set; } = null!; + public bool Validate() + { + return !string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Value); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/KeyVaultHandler.cs b/Core.Blueprint.Application/UsesCases/KeyVault/KeyVaultHandler.cs new file mode 100644 index 0000000..abddd5e --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/KeyVaultHandler.cs @@ -0,0 +1,160 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using Core.Blueprint.Application.UsesCases.KeyVault.Ports; +using Core.Blueprint.KeyVault; +using Core.Blueprint.Service.External.Clients; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.KeyVault +{ + public class KeyVaultHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly IKeyVaultPort _port; + private readonly IValidator _createSecretValidator; + private readonly IValidator _getSecretValidator; + private readonly IValidator _updateSecretValidator; + private readonly IValidator _deleteSecretValidator; + private readonly IBlueprintServiceClient _keyVaultDALService; + + public KeyVaultHandler( + IKeyVaultPort port, + IValidator createSecretValidator, + IValidator getSecretValidator, + IValidator updateSecretValidator, + IValidator deleteSecretValidator, + IBlueprintServiceClient keyVaultDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _createSecretValidator = createSecretValidator ?? throw new ArgumentNullException(nameof(createSecretValidator)); + _getSecretValidator = getSecretValidator ?? throw new ArgumentNullException(nameof(getSecretValidator)); + _updateSecretValidator = updateSecretValidator ?? throw new ArgumentNullException(nameof(updateSecretValidator)); + _deleteSecretValidator = deleteSecretValidator ?? throw new ArgumentNullException(nameof(deleteSecretValidator)); + _keyVaultDALService = keyVaultDALService ?? throw new ArgumentNullException(nameof(keyVaultDALService)); + } + + public async ValueTask ExecuteAsync(CreateSecretRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_createSecretValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new KeyVaultRequest + { + Name = command.Name, + Value = command.Value, + }; + + var result = await _keyVaultDALService.CreateSecretAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetSecretRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _keyVaultDALService.GetSecretByNameAsync(command.Name, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(UpdateSecretRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updateSecretValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new KeyVaultRequest + { + Name = command.Name, + Value = command.Value, + }; + + var result = await _keyVaultDALService.UpdateSecretAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(DeleteSecretRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_deleteSecretValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _keyVaultDALService.DeleteSecretAsync(command.Name, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Ports/IKeyVaultPort.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Ports/IKeyVaultPort.cs new file mode 100644 index 0000000..4487e7d --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Ports/IKeyVaultPort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.KeyVault; +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.KeyVault.Ports +{ + public interface IKeyVaultPort : IBasePort, + ICommandSuccessPort, + ICommandSuccessPort, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort, + IBadRequestPort + { + } +} diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Validator/CreateSecretValidator.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/CreateSecretValidator.cs new file mode 100644 index 0000000..8c10d5c --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/CreateSecretValidator.cs @@ -0,0 +1,14 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.KeyVault.Validator +{ + public class CreateSecretValidator : AbstractValidator + { + public CreateSecretValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Secret Name").WithMessage("Secret Name is Obligatory."); + RuleFor(i => i.Value).NotEmpty().NotNull().OverridePropertyName(x => x.Value).WithName("Secret Name").WithMessage("Secret Value is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Validator/DeleteSecretValidator.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/DeleteSecretValidator.cs new file mode 100644 index 0000000..c9320d6 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/DeleteSecretValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.KeyVault.Validator +{ + public class DeleteSecretValidator : AbstractValidator + { + public DeleteSecretValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Secret Name").WithMessage("Secret Name is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Validator/GetSecretValidator.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/GetSecretValidator.cs new file mode 100644 index 0000000..1078ffa --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/GetSecretValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.KeyVault.Validator +{ + public class GetSecretValidator : AbstractValidator + { + public GetSecretValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Secret Name").WithMessage("Secret Name is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/KeyVault/Validator/UpdateSecretValidator.cs b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/UpdateSecretValidator.cs new file mode 100644 index 0000000..0007648 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/KeyVault/Validator/UpdateSecretValidator.cs @@ -0,0 +1,14 @@ +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.KeyVault.Validator +{ + public class UpdateSecretValidator : AbstractValidator + { + public UpdateSecretValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Secret Name").WithMessage("Secret Name is Obligatory."); + RuleFor(i => i.Value).NotEmpty().NotNull().OverridePropertyName(x => x.Value).WithName("Secret Value").WithMessage("Secret Value is Obligatory."); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Adapter/MongoPort.cs b/Core.Blueprint.Application/UsesCases/Mongo/Adapter/MongoPort.cs new file mode 100644 index 0000000..f0c481c --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Adapter/MongoPort.cs @@ -0,0 +1,19 @@ +using Core.Blueprint.Application.UsesCases.Mongo.Ports; +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Application.UsesCases.MongoStorage.Adapter +{ + public class MongoPort : BasePresenter, IMongoPort + { + public void Success(BlueprintAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Input/CreateBlueprintRequest.cs b/Core.Blueprint.Application/UsesCases/Mongo/Input/CreateBlueprintRequest.cs new file mode 100644 index 0000000..da1e801 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Input/CreateBlueprintRequest.cs @@ -0,0 +1,16 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.Mongo.Input +{ + public class CreateBlueprintRequest : Notificator, ICommand + { + public string Name { get; set; } = null!; + + public string? Description { get; set; } + + public bool Validate() + { + return Name != null && Name != string.Empty; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Input/DeleteBlueprintRequest.cs b/Core.Blueprint.Application/UsesCases/Mongo/Input/DeleteBlueprintRequest.cs new file mode 100644 index 0000000..e9966e9 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Input/DeleteBlueprintRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.Mongo.Input +{ + public class DeleteBlueprintRequest : Notificator, ICommand + { + public string _Id { get; set; } + + public bool Validate() + { + return _Id != null && _Id != string.Empty; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Input/GetAllBlueprintsRequest.cs b/Core.Blueprint.Application/UsesCases/Mongo/Input/GetAllBlueprintsRequest.cs new file mode 100644 index 0000000..fcdcee0 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Input/GetAllBlueprintsRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.Mongo.Input +{ + public class GetAllBlueprintsRequest : Notificator, ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Input/GetBlueprintRequest.cs b/Core.Blueprint.Application/UsesCases/Mongo/Input/GetBlueprintRequest.cs new file mode 100644 index 0000000..10b3f04 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Input/GetBlueprintRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.Mongo.Input +{ + public class GetBlueprintRequest : Notificator, ICommand + { + public string _Id { get; set; } + + public bool Validate() + { + return _Id != null && _Id != string.Empty; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Input/UpdateBlueprintRequest.cs b/Core.Blueprint.Application/UsesCases/Mongo/Input/UpdateBlueprintRequest.cs new file mode 100644 index 0000000..4c9b02c --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Input/UpdateBlueprintRequest.cs @@ -0,0 +1,22 @@ +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.Mongo.Input +{ + public class UpdateBlueprintRequest : Notificator, ICommand + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string _Id { get; set; } = null!; + public string Id { get; init; } = null!; + public DateTime CreatedAt { get; set; } + public string? CreatedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public string? UpdatedBy { get; set; } + public StatusEnum Status { get; set; } + public bool Validate() + { + return _Id != null && _Id != string.Empty; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/MongoHandler.cs b/Core.Blueprint.Application/UsesCases/Mongo/MongoHandler.cs new file mode 100644 index 0000000..ca751aa --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/MongoHandler.cs @@ -0,0 +1,197 @@ +using Core.Blueprint.Application.UsesCases.Mongo.Input; +using Core.Blueprint.Application.UsesCases.Mongo.Ports; +using Core.Blueprint.Service.External.Clients; +using Core.Blueprint.Service.External.Clients.Adapters; +using Core.Blueprint.Service.External.Clients.Requests; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.Blueprints +{ + public class MongoHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly IMongoPort _port; + private readonly IValidator _createBlueprintValidator; + private readonly IValidator _getBlueprintValidator; + private readonly IValidator _updateBlueprintValidator; + private readonly IValidator _deleteBlueprintValidator; + private readonly IBlueprintServiceClient _mongoDALService; + + public MongoHandler( + IMongoPort port, + IValidator createBlueprintValidator, + IValidator getBlueprintValidator, + IValidator updateBlueprintValidator, + IValidator deleteBlueprintValidator, + IBlueprintServiceClient mongoDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _createBlueprintValidator = createBlueprintValidator ?? throw new ArgumentNullException(nameof(createBlueprintValidator)); + _getBlueprintValidator = getBlueprintValidator ?? throw new ArgumentNullException(nameof(getBlueprintValidator)); + _updateBlueprintValidator = updateBlueprintValidator ?? throw new ArgumentNullException(nameof(updateBlueprintValidator)); + _deleteBlueprintValidator = deleteBlueprintValidator ?? throw new ArgumentNullException(nameof(deleteBlueprintValidator)); + _mongoDALService = mongoDALService ?? throw new ArgumentNullException(nameof(mongoDALService)); + } + + public async ValueTask ExecuteAsync(CreateBlueprintRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_createBlueprintValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new BlueprintRequest + { + Name = command.Name, + Description = command.Description, + }; + + var result = await _mongoDALService.CreateBlueprintAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllBlueprintsRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _mongoDALService.GetAllBlueprintsAsync().ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetBlueprintRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_getBlueprintValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _mongoDALService.GetBlueprintByIdAsync(command._Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(UpdateBlueprintRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updateBlueprintValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new BlueprintAdapter + { + Id = command.Id, + _Id = command._Id, + Name = command.Name, + Description = command.Description, + CreatedAt = command.CreatedAt, + CreatedBy = command.CreatedBy, + UpdatedAt = command.UpdatedAt, + UpdatedBy = command.UpdatedBy, + Status = command.Status + }; + + string _id = command._Id; + + var result = await _mongoDALService.UpdateBlueprintAsync(_id, request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(DeleteBlueprintRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_deleteBlueprintValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _mongoDALService.DeleteBlueprintAsync(command._Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Ports/IMongoPort.cs b/Core.Blueprint.Application/UsesCases/Mongo/Ports/IMongoPort.cs new file mode 100644 index 0000000..f2c314e --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Ports/IMongoPort.cs @@ -0,0 +1,14 @@ +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.Mongo.Ports +{ + public interface IMongoPort : IBasePort, + ICommandSuccessPort, + ICommandSuccessPort>, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort, + IBadRequestPort + { + } +} diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Validator/CreateBlueprintValidator.cs b/Core.Blueprint.Application/UsesCases/Mongo/Validator/CreateBlueprintValidator.cs new file mode 100644 index 0000000..10f5d1d --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Validator/CreateBlueprintValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.Mongo.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Blueprints.Validator +{ + public class CreateBlueprintValidator : AbstractValidator + { + public CreateBlueprintValidator() + { + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Blueprint Name").WithMessage("Blueprint Name is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Validator/DeleteBlueprintValidator.cs b/Core.Blueprint.Application/UsesCases/Mongo/Validator/DeleteBlueprintValidator.cs new file mode 100644 index 0000000..6a8d225 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Validator/DeleteBlueprintValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.Mongo.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Blueprints.Validator +{ + public class DeleteBlueprintValidator : AbstractValidator + { + public DeleteBlueprintValidator() + { + RuleFor(i => i._Id).NotEmpty().NotNull().OverridePropertyName(x => x._Id).WithName("Blueprint Mongo Identifier").WithMessage("Blueprint Mongo Identifier is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Validator/GetBlueprintValidator.cs b/Core.Blueprint.Application/UsesCases/Mongo/Validator/GetBlueprintValidator.cs new file mode 100644 index 0000000..d6f2113 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Validator/GetBlueprintValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.Mongo.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Blueprints.Validator +{ + public class GetBlueprintValidator : AbstractValidator + { + public GetBlueprintValidator() + { + RuleFor(i => i._Id).NotEmpty().NotNull().OverridePropertyName(x => x._Id).WithName("Blueprint Mongo Identifier").WithMessage("Blueprint Mongo Identifier is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/Mongo/Validator/UpdateBlueprintValidator.cs b/Core.Blueprint.Application/UsesCases/Mongo/Validator/UpdateBlueprintValidator.cs new file mode 100644 index 0000000..73fd5b7 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/Mongo/Validator/UpdateBlueprintValidator.cs @@ -0,0 +1,17 @@ +using Core.Blueprint.Application.UsesCases.Mongo.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.Blueprints.Validator +{ + public class UpdateBlueprintValidator : AbstractValidator + { + public UpdateBlueprintValidator() + { + RuleFor(i => i._Id).NotEmpty().NotNull().OverridePropertyName(x => x._Id).WithName("Blueprint Mongo Identifier").WithMessage("Blueprint Mongo Identifier is Obligatory."); + RuleFor(i => i._Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("Blueprint GUID").WithMessage("Blueprint GUID is Obligatory."); + RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Blueprint Name").WithMessage("Blueprint Name is Obligatory."); + RuleFor(i => i.Status).NotNull().OverridePropertyName(x => x.Status).WithName("Blueprint Status").WithMessage("Blueprint Status is Obligatory."); + RuleFor(i => i.CreatedAt).NotNull().OverridePropertyName(x => x.CreatedAt).WithName("Blueprint CreatedAt").WithMessage("Blueprint CreatedAt is Obligatory."); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Adapter/SQLPort.cs b/Core.Blueprint.Application/UsesCases/SQL/Adapter/SQLPort.cs new file mode 100644 index 0000000..1750f75 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Adapter/SQLPort.cs @@ -0,0 +1,19 @@ +using Core.Blueprint.Application.UsesCases.SQL.Ports; +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Application.UsesCases.SQL.Adapter +{ + public class SQLPort : BasePresenter, ISQLPort + { + public void Success(UserProjectAdapter output) + { + ViewModel = new OkObjectResult(output); + } + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Input/CreateUserProjectRequest.cs b/Core.Blueprint.Application/UsesCases/SQL/Input/CreateUserProjectRequest.cs new file mode 100644 index 0000000..04ad592 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Input/CreateUserProjectRequest.cs @@ -0,0 +1,16 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.SQL.Input +{ + public class CreateUserProjectRequest : Notificator, ICommand + { + public string ProjectCode { get; set; } = null!; + public string ProjectDescription { get; set; } = null!; + public string UserId { get; set; } = null!; + + public bool Validate() + { + return ProjectCode != null && ProjectCode != string.Empty; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Input/DeleteUserProjectRequest.cs b/Core.Blueprint.Application/UsesCases/SQL/Input/DeleteUserProjectRequest.cs new file mode 100644 index 0000000..3f11d9c --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Input/DeleteUserProjectRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.SQL.Input +{ + public class DeleteUserProjectRequest : Notificator, ICommand + { + public int Id { get; set; } + + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Input/GetAllUserProjectsRequest.cs b/Core.Blueprint.Application/UsesCases/SQL/Input/GetAllUserProjectsRequest.cs new file mode 100644 index 0000000..40f17c6 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Input/GetAllUserProjectsRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.SQL.Input +{ + public class GetAllUserProjectsRequest : Notificator, ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Input/GetUserProjectRequest.cs b/Core.Blueprint.Application/UsesCases/SQL/Input/GetUserProjectRequest.cs new file mode 100644 index 0000000..d87d3d7 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Input/GetUserProjectRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.SQL.Input +{ + public class GetUserProjectRequest : Notificator, ICommand + { + public int Id { get; set; } + + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Input/UpdateUserProjectRequest.cs b/Core.Blueprint.Application/UsesCases/SQL/Input/UpdateUserProjectRequest.cs new file mode 100644 index 0000000..e544673 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Input/UpdateUserProjectRequest.cs @@ -0,0 +1,23 @@ +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.SQL.Input +{ + public class UpdateUserProjectRequest : Notificator, ICommand + { + public string ProjectCode { get; set; } = null!; + public string ProjectDescription { get; set; } = null!; + public string UserId { get; set; } = null!; + public int Id { get; set; } + public string Guid { get; set; } = null!; + public DateTime CreatedAt { get; set; } + public string? CreatedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public string? UpdatedBy { get; set; } + public StatusEnum Status { get; set; } + public bool Validate() + { + return Guid != null && Guid != string.Empty; + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Ports/ISQLPort.cs b/Core.Blueprint.Application/UsesCases/SQL/Ports/ISQLPort.cs new file mode 100644 index 0000000..51a906e --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Ports/ISQLPort.cs @@ -0,0 +1,14 @@ +using Core.Blueprint.Service.External.Clients.Adapters; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Application.UsesCases.SQL.Ports +{ + public interface ISQLPort : IBasePort, + ICommandSuccessPort, + ICommandSuccessPort>, + INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort, + INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort, + IBadRequestPort + { + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/SQLHandler.cs b/Core.Blueprint.Application/UsesCases/SQL/SQLHandler.cs new file mode 100644 index 0000000..45efd6f --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/SQLHandler.cs @@ -0,0 +1,193 @@ +using Core.Blueprint.Application.UsesCases.SQL.Input; +using Core.Blueprint.Application.UsesCases.SQL.Ports; +using Core.Blueprint.Service.External.Clients; +using Core.Blueprint.Service.External.Clients.Adapters; +using Core.Blueprint.Service.External.Clients.Requests; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Lib.Architecture.BuildingBlocks.Helpers; + +namespace Core.Cerberos.Application.UseCases.UserProjects +{ + public class SQLHandler : + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler, + IComponentHandler + { + private readonly ISQLPort _port; + private readonly IValidator _createUserProjectValidator; + private readonly IValidator _getUserProjectValidator; + private readonly IValidator _updateUserProjectValidator; + private readonly IValidator _deleteUserProjectValidator; + private readonly IBlueprintServiceClient _SQLDALService; + + public SQLHandler( + ISQLPort port, + IValidator createUserProjectValidator, + IValidator getUserProjectValidator, + IValidator updateUserProjectValidator, + IValidator deleteUserProjectValidator, + IBlueprintServiceClient SQLDALService) + { + _port = port ?? throw new ArgumentNullException(nameof(port)); + _createUserProjectValidator = createUserProjectValidator ?? throw new ArgumentNullException(nameof(createUserProjectValidator)); + _getUserProjectValidator = getUserProjectValidator ?? throw new ArgumentNullException(nameof(getUserProjectValidator)); + _updateUserProjectValidator = updateUserProjectValidator ?? throw new ArgumentNullException(nameof(updateUserProjectValidator)); + _deleteUserProjectValidator = deleteUserProjectValidator ?? throw new ArgumentNullException(nameof(deleteUserProjectValidator)); + _SQLDALService = SQLDALService ?? throw new ArgumentNullException(nameof(SQLDALService)); + } + + public async ValueTask ExecuteAsync(CreateUserProjectRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_createUserProjectValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new UserProjectRequest + { + ProjectCode = command.ProjectCode, + ProjectDescription = command.ProjectDescription, + UserId = command.UserId, + }; + + var result = await _SQLDALService.CreateUserProjectAsync(request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetAllUserProjectsRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var _result = await _SQLDALService.GetAllUserProjectsAsync().ConfigureAwait(false); + if (!_result.Any()) + { + _port.NoContentSuccess(); + return; + } + _port.Success(_result.ToList()); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + public async ValueTask ExecuteAsync(GetUserProjectRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + var result = await _SQLDALService.GetUserProjectByIdAsync(command.Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(UpdateUserProjectRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_updateUserProjectValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var request = new UserProjectAdapter + { + Id = command.Id, + Guid = command.Guid, + UserId = command.UserId, + ProjectCode = command.ProjectCode, + ProjectDescription = command.ProjectDescription, + CreatedAt = command.CreatedAt, + CreatedBy = command.CreatedBy, + UpdatedAt = command.UpdatedAt, + UpdatedBy = command.UpdatedBy, + Status = command.Status + }; + + int id = command.Id; + + var result = await _SQLDALService.UpdateUserProjectAsync(id, request, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + + + public async ValueTask ExecuteAsync(DeleteUserProjectRequest command, CancellationToken cancellationToken = default) + { + try + { + ArgumentNullException.ThrowIfNull(command); + + if (!command.IsValid(_deleteUserProjectValidator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _SQLDALService.DeleteUserProjectAsync(command.Id, cancellationToken).ConfigureAwait(false); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + ApiResponseHelper.EvaluatePort(ex, _port); + } + } + } +} diff --git a/Core.Blueprint.Application/UsesCases/SQL/Validator/CreateUserProjectValidator.cs b/Core.Blueprint.Application/UsesCases/SQL/Validator/CreateUserProjectValidator.cs new file mode 100644 index 0000000..66384d4 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Validator/CreateUserProjectValidator.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Application.UsesCases.SQL.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.SQL.Validator +{ + public class CreateUserProjectValidator : AbstractValidator + { + public CreateUserProjectValidator() + { + RuleFor(i => i.ProjectCode).NotEmpty().NotNull().OverridePropertyName(x => x.ProjectCode).WithName("Project Code").WithMessage("Project Code is Obligatory."); + RuleFor(i => i.ProjectDescription).NotEmpty().NotNull().OverridePropertyName(x => x.ProjectDescription).WithName("Project Description").WithMessage("Project Description is Obligatory."); + RuleFor(i => i.UserId).NotEmpty().NotNull().OverridePropertyName(x => x.UserId).WithName("User Identifier").WithMessage("User Identifier is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/SQL/Validator/DeleteUserProjectValidator.cs b/Core.Blueprint.Application/UsesCases/SQL/Validator/DeleteUserProjectValidator.cs new file mode 100644 index 0000000..9ef57ff --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Validator/DeleteUserProjectValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.SQL.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.SQL.Validator +{ + public class DeleteUserProjectValidator : AbstractValidator + { + public DeleteUserProjectValidator() + { + RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("User Project Identifier").WithMessage("User Project Identifier is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/SQL/Validator/GetUserProjectValidator.cs b/Core.Blueprint.Application/UsesCases/SQL/Validator/GetUserProjectValidator.cs new file mode 100644 index 0000000..de465a6 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Validator/GetUserProjectValidator.cs @@ -0,0 +1,13 @@ +using Core.Blueprint.Application.UsesCases.SQL.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.SQL.Validator +{ + public class GetUserProjectValidator : AbstractValidator + { + public GetUserProjectValidator() + { + RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("User Project Identifier").WithMessage("User Project Identifier is Obligatory."); + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Application/UsesCases/SQL/Validator/UpdateUserProjectValidator.cs b/Core.Blueprint.Application/UsesCases/SQL/Validator/UpdateUserProjectValidator.cs new file mode 100644 index 0000000..9a88e06 --- /dev/null +++ b/Core.Blueprint.Application/UsesCases/SQL/Validator/UpdateUserProjectValidator.cs @@ -0,0 +1,19 @@ +using Core.Blueprint.Application.UsesCases.SQL.Input; +using FluentValidation; + +namespace Core.Cerberos.Application.UseCases.SQL.Validator +{ + public class UpdateUserProjectValidator : AbstractValidator + { + public UpdateUserProjectValidator() + { + RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("UserProject Identifier").WithMessage("UserPoject Identifier is Obligatory."); + RuleFor(i => i.Guid).NotEmpty().NotNull().OverridePropertyName(x => x.Guid).WithName("UserProject GUID").WithMessage("UserProject GUID is Obligatory."); + RuleFor(i => i.ProjectCode).NotEmpty().NotNull().OverridePropertyName(x => x.ProjectCode).WithName("Project Code").WithMessage("Project Code is Obligatory."); + RuleFor(i => i.ProjectDescription).NotEmpty().NotNull().OverridePropertyName(x => x.ProjectDescription).WithName("Project Description").WithMessage("Project Description is Obligatory."); + RuleFor(i => i.UserId).NotEmpty().NotNull().OverridePropertyName(x => x.UserId).WithName("User Identifier").WithMessage("User Identifier is Obligatory."); + RuleFor(i => i.Status).NotNull().OverridePropertyName(x => x.Status).WithName("UserProject Status").WithMessage("UserProject Status is Obligatory."); + RuleFor(i => i.CreatedAt).NotNull().OverridePropertyName(x => x.CreatedAt).WithName("UserProject CreatedAt").WithMessage("UserProject CreatedAt is Obligatory."); + } + } +} diff --git a/Core.Blueprint.Service.API/Controllers/BlobStorageController.cs b/Core.Blueprint.Service.API/Controllers/BlobStorageController.cs new file mode 100644 index 0000000..caf3d97 --- /dev/null +++ b/Core.Blueprint.Service.API/Controllers/BlobStorageController.cs @@ -0,0 +1,119 @@ +using Asp.Versioning; +using Core.Blueprint.Application.UsesCases.BlobStorage.Ports; +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all services and business rules related to . + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + public class BlobStorageController : ControllerBase + { + private readonly IComponentHandler uploadBlobHandler; + private readonly IComponentHandler getBlobListHandler; + private readonly IComponentHandler downloadBlobHandler; + private readonly IComponentHandler deleteBlobHandler; + private readonly IStoragePort port; + + /// + /// Handles all services and business rules related to . + /// + public BlobStorageController( + IComponentHandler uploadBlobHandler, + IComponentHandler getBlobListHandler, + IComponentHandler downloadBlobHandler, + IComponentHandler deleteBlobHandler, + IStoragePort port + ) + { + this.uploadBlobHandler = uploadBlobHandler; + this.getBlobListHandler = getBlobListHandler; + this.downloadBlobHandler = downloadBlobHandler; + this.deleteBlobHandler = deleteBlobHandler; + this.port = port; + } + + /// + /// Uploads a new blob. + /// + [HttpPost("UploadBlob")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UploadBlobAsync([FromBody] UploadBlobRequest newBlob, CancellationToken cancellationToken = default) + { + await uploadBlobHandler.ExecuteAsync(newBlob, cancellationToken).ConfigureAwait(false); + return port.ViewModel; + } + + /// + /// Gets all blobs into the container. + /// + [HttpGet] + [Route("GetBlobList")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetBlobList([FromQuery] string? prefix, CancellationToken cancellationToken) + { + await getBlobListHandler.ExecuteAsync(new GetBlobListRequest { Prefix = prefix }, cancellationToken).ConfigureAwait(false); + return port.ViewModel; + } + + /// + /// Downloads a blob by name. + /// + [HttpPost("DownloadBlob")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task DownloadBlobAsync([FromBody] DownloadBlobRequest request, CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(request.BlobName)) { return BadRequest("Invalid blob name"); } + + await downloadBlobHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Deletes a blob by name. + /// + [HttpDelete] + [Route("DeleteBlob")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteBlobAsync([FromBody] DeleteBlobRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.BlobName)) { return BadRequest("Invalid blob name"); } + + await deleteBlobHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.API/Controllers/KeyVaultController.cs b/Core.Blueprint.Service.API/Controllers/KeyVaultController.cs new file mode 100644 index 0000000..97fc218 --- /dev/null +++ b/Core.Blueprint.Service.API/Controllers/KeyVaultController.cs @@ -0,0 +1,124 @@ +using Asp.Versioning; +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using Core.Blueprint.Application.UsesCases.KeyVault.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all services and business rules related to . + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + public class KeyVaultController : ControllerBase + { + private readonly IComponentHandler createSecretHandler; + private readonly IComponentHandler getSecretHandler; + private readonly IComponentHandler updateSecretHandler; + private readonly IComponentHandler deleteSecretHandler; + private readonly IKeyVaultPort port; + + /// + /// Handles all services and business rules related to . + /// + public KeyVaultController( + IComponentHandler getSecretHandler, + IComponentHandler createSecretHandler, + IComponentHandler updateSecretHandler, + IComponentHandler deleteSecretHandler, + IKeyVaultPort port + ) + { + this.createSecretHandler = createSecretHandler; + this.updateSecretHandler = updateSecretHandler; + this.deleteSecretHandler = deleteSecretHandler; + this.getSecretHandler = getSecretHandler; + this.port = port; + } + + /// + /// Creates a new secret. + /// + [HttpPost("CreateSecret")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateSecretAsync([FromBody] CreateSecretRequest newSecret, CancellationToken cancellationToken = default) + { + await createSecretHandler.ExecuteAsync(newSecret, cancellationToken).ConfigureAwait(false); + return port.ViewModel; + } + + /// + /// Gets the secret by name. + /// + [HttpPost] + [Route("GetSecretByName")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetSecretByName([FromBody] GetSecretRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Name)) { return BadRequest("Invalid secret name"); } + + await getSecretHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Updates a full secret by identifier. + /// + [HttpPut("UpdateSecret")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateSecretAsync([FromBody] UpdateSecretRequest request, CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(request.Name)) { return BadRequest("Invalid secret name"); } + + if (string.IsNullOrEmpty(request.Value)) { return BadRequest("Invalid secret value"); } + + await updateSecretHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Deletes a secret by name. + /// + [HttpDelete] + [Route("DeleteSecret")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteSecretAsync([FromBody] DeleteSecretRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request.Name)) { return BadRequest("Invalid secret name"); } + + await deleteSecretHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.API/Controllers/MongoBluePrintController.cs b/Core.Blueprint.Service.API/Controllers/MongoBluePrintController.cs new file mode 100644 index 0000000..c894366 --- /dev/null +++ b/Core.Blueprint.Service.API/Controllers/MongoBluePrintController.cs @@ -0,0 +1,142 @@ +using Asp.Versioning; +using Core.Blueprint.Application.UsesCases.Mongo.Input; +using Core.Blueprint.Application.UsesCases.Mongo.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all services and business rules related to . + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + public class MongoBlueprintController : ControllerBase + { + private readonly IComponentHandler createBlueprintHandler; + private readonly IComponentHandler getAllBlueprintsHandler; + private readonly IComponentHandler getBlueprintHandler; + private readonly IComponentHandler updateBlueprintHandler; + private readonly IComponentHandler deleteBlueprintHandler; + private readonly IMongoPort port; + + /// + /// Handles all services and business rules related to . + /// + public MongoBlueprintController( + IComponentHandler getBlueprintHandler, + IComponentHandler getAllBlueprintsHandler, + IComponentHandler createBlueprintHandler, + IComponentHandler updateBlueprintHandler, + IComponentHandler deleteBlueprintHandler, + IMongoPort port + ) + { + this.createBlueprintHandler = createBlueprintHandler; + this.updateBlueprintHandler = updateBlueprintHandler; + this.deleteBlueprintHandler = deleteBlueprintHandler; + this.getAllBlueprintsHandler = getAllBlueprintsHandler; + this.getBlueprintHandler = getBlueprintHandler; + this.port = port; + } + + /// + /// Creates a new blueprint. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateBlueprintAsync([FromBody] CreateBlueprintRequest newBlueprint, CancellationToken cancellationToken = default) + { + await createBlueprintHandler.ExecuteAsync(newBlueprint, cancellationToken).ConfigureAwait(false); + return port.ViewModel; + } + + /// + /// Gets all blueprints. + /// + [HttpGet("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAllBlueprintsAsync(CancellationToken cancellationToken) + { + await getAllBlueprintsHandler.ExecuteAsync(new GetAllBlueprintsRequest { }, cancellationToken).ConfigureAwait(false); + return port.ViewModel; + } + + /// + /// Gets the blueprint by identifier. + /// + [HttpPost] + [Route("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetBlueprintById([FromBody] GetBlueprintRequest request, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request._Id)) { return BadRequest("Invalid blueprint identifier"); } + + await getBlueprintHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Updates a full blueprint by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateBlueprintAsync([FromBody] UpdateBlueprintRequest request, CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(request._Id)) { return BadRequest("Invalid blueprint identifier"); } + + await updateBlueprintHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Deletes a blueprint. + /// + [HttpDelete] + [Route("Delete")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteBlueprintAsync([FromBody] DeleteBlueprintRequest request, + CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(request._Id)) { return BadRequest("Invalid blueprint identifier"); } + + await deleteBlueprintHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.API/Controllers/SQLUserProjectController.cs b/Core.Blueprint.Service.API/Controllers/SQLUserProjectController.cs new file mode 100644 index 0000000..6ccfd05 --- /dev/null +++ b/Core.Blueprint.Service.API/Controllers/SQLUserProjectController.cs @@ -0,0 +1,142 @@ +using Asp.Versioning; +using Core.Blueprint.Application.UsesCases.SQL.Input; +using Core.Blueprint.Application.UsesCases.SQL.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Cerberos.Service.API.Controllers +{ + /// + /// Handles all services and business rules related to . + /// + [ApiVersion("1.0")] + [Route("api/v{api-version:apiVersion}/[controller]")] + [Produces("application/json")] + [ApiController] + public class SQLUserProjectController : ControllerBase + { + private readonly IComponentHandler createUserProjectHandler; + private readonly IComponentHandler getAllUserProjectsHandler; + private readonly IComponentHandler getUserProjectHandler; + private readonly IComponentHandler updateUserProjectHandler; + private readonly IComponentHandler deleteUserProjectStatusHandler; + private readonly ISQLPort port; + + /// + /// Handles all services and business rules related to . + /// + public SQLUserProjectController( + IComponentHandler getUserProjectHandler, + IComponentHandler getAllUserProjectsHandler, + IComponentHandler createUserProjectHandler, + IComponentHandler updateUserProjectHandler, + IComponentHandler deleteUserProjectStatusHandler, + ISQLPort port + ) + { + this.createUserProjectHandler = createUserProjectHandler; + this.updateUserProjectHandler = updateUserProjectHandler; + this.deleteUserProjectStatusHandler = deleteUserProjectStatusHandler; + this.getAllUserProjectsHandler = getAllUserProjectsHandler; + this.getUserProjectHandler = getUserProjectHandler; + this.port = port; + } + + /// + /// Creates a new UserProject. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task CreateUserProjectAsync([FromBody] CreateUserProjectRequest newUserProject, CancellationToken cancellationToken = default) + { + await createUserProjectHandler.ExecuteAsync(newUserProject, cancellationToken).ConfigureAwait(false); + return port.ViewModel; + } + + /// + /// Gets all UserProjects. + /// + [HttpGet("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task GetAllUserProjectsAsync(CancellationToken cancellationToken) + { + await getAllUserProjectsHandler.ExecuteAsync(new GetAllUserProjectsRequest { }, cancellationToken).ConfigureAwait(false); + return port.ViewModel; + } + + /// + /// Gets the UserProject by identifier. + /// + [HttpPost] + [Route("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetUserProjectById([FromBody] GetUserProjectRequest request, CancellationToken cancellationToken) + { + if (request.Id <= 0) { return BadRequest("Invalid UserProject identifier"); } + + await getUserProjectHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Updates a full UserProject by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task UpdateUserProjectAsync([FromBody] UpdateUserProjectRequest request, CancellationToken cancellationToken = default) + { + if (request.Id <= 0) { return BadRequest("Invalid UserProject identifier"); } + + await updateUserProjectHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + + /// + /// Deletes a UserProject. + /// + [HttpDelete] + [Route("Delete")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteUserProjectStatusAsync([FromBody] DeleteUserProjectRequest request, + CancellationToken cancellationToken) + { + if (request.Id <= 0) { return BadRequest("Invalid UserProject identifier"); } + + await deleteUserProjectStatusHandler.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + + return port.ViewModel; + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.API/Core.Blueprint.Service.API.csproj b/Core.Blueprint.Service.API/Core.Blueprint.Service.API.csproj new file mode 100644 index 0000000..46f7629 --- /dev/null +++ b/Core.Blueprint.Service.API/Core.Blueprint.Service.API.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + true + a776c24d-b2ab-4520-a66b-d1802fb016fb + Linux + + + + + + + + + + + + + + + + diff --git a/Core.Blueprint.Service.API/Core.Blueprint.Service.API.http b/Core.Blueprint.Service.API/Core.Blueprint.Service.API.http new file mode 100644 index 0000000..87cde0a --- /dev/null +++ b/Core.Blueprint.Service.API/Core.Blueprint.Service.API.http @@ -0,0 +1,6 @@ +@Core.Blueprint.Service.API_HostAddress = http://localhost:5047 + +GET {{Core.Blueprint.Service.API_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Core.Blueprint.Service.API/Dockerfile b/Core.Blueprint.Service.API/Dockerfile new file mode 100644 index 0000000..6c0c9b7 --- /dev/null +++ b/Core.Blueprint.Service.API/Dockerfile @@ -0,0 +1,25 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["Core.Blueprint.Service.API/Core.Blueprint.Service.API.csproj", "Core.Blueprint.Service.API/"] +RUN dotnet restore "./Core.Blueprint.Service.API/./Core.Blueprint.Service.API.csproj" +COPY . . +WORKDIR "/src/Core.Blueprint.Service.API" +RUN dotnet build "./Core.Blueprint.Service.API.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./Core.Blueprint.Service.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Core.Blueprint.Service.API.dll"] \ No newline at end of file diff --git a/Core.Blueprint.Service.API/Extensions/ServiceCollectionExtension.cs b/Core.Blueprint.Service.API/Extensions/ServiceCollectionExtension.cs new file mode 100644 index 0000000..59499a9 --- /dev/null +++ b/Core.Blueprint.Service.API/Extensions/ServiceCollectionExtension.cs @@ -0,0 +1,111 @@ +using Core.Blueprint.Application.UsesCases.BlobStorage.Adapter; +using Core.Blueprint.Application.UsesCases.BlobStorage.Ports; +using Core.Blueprint.Application.UsesCases.KeyVault.Input; +using Core.Blueprint.Application.UsesCases.KeyVault.Ports; +using Core.Blueprint.Application.UsesCases.Mongo.Input; +using Core.Blueprint.Application.UsesCases.Mongo.Ports; +using Core.Blueprint.Application.UsesCases.MongoStorage.Adapter; +using Core.Blueprint.Application.UsesCases.SQL.Adapter; +using Core.Blueprint.Application.UsesCases.SQL.Input; +using Core.Blueprint.Application.UsesCases.SQL.Ports; +using Core.Cerberos.Application.UseCases.Blueprints; +using Core.Cerberos.Application.UseCases.Blueprints.Validator; +using Core.Cerberos.Application.UseCases.KeyVault; +using Core.Cerberos.Application.UseCases.KeyVault.Validator; +using Core.Cerberos.Application.UseCases.SQL.Validator; +using Core.Cerberos.Application.UseCases.UserProjects; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.API.Extensions +{ + public static class ServiceCollectionExtension + { + public static IServiceCollection AddServiceConfigurationLayer(this IServiceCollection services) + { + #region Mongo Services + services.AddScoped(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, CreateBlueprintValidator>(); + services.AddScoped, MongoHandler>(); + + services.AddScoped, MongoHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, GetBlueprintValidator>(); + services.AddScoped, MongoHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UpdateBlueprintValidator>(); + services.AddScoped, MongoHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, DeleteBlueprintValidator>(); + services.AddScoped, MongoHandler>(); + #endregion + + #region SQL Services + services.AddScoped(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, CreateUserProjectValidator>(); + services.AddScoped, SQLHandler>(); + + services.AddScoped, SQLHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, GetUserProjectValidator>(); + services.AddScoped, SQLHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UpdateUserProjectValidator>(); + services.AddScoped, SQLHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, DeleteUserProjectValidator>(); + services.AddScoped, SQLHandler>(); + #endregion + + #region KeyVault Services + services.AddScoped(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, CreateSecretValidator>(); + services.AddScoped, KeyVaultHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, GetSecretValidator>(); + services.AddScoped, KeyVaultHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UpdateSecretValidator>(); + services.AddScoped, KeyVaultHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, DeleteSecretValidator>(); + services.AddScoped, KeyVaultHandler>(); + #endregion + + #region Storage Services + services.AddScoped(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, UploadBlobValidator>(); + services.AddScoped, StorageHandler>(); + + services.AddScoped, StorageHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, DownloadBlobValidator>(); + services.AddScoped, StorageHandler>(); + + services.AddValidatorsFromAssemblyContaining(); + services.AddScoped, DeleteBlobValidator>(); + services.AddScoped, StorageHandler>(); + #endregion + + return services; + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.API/Extensions/SwaggerExtensions.cs b/Core.Blueprint.Service.API/Extensions/SwaggerExtensions.cs new file mode 100644 index 0000000..b4d6586 --- /dev/null +++ b/Core.Blueprint.Service.API/Extensions/SwaggerExtensions.cs @@ -0,0 +1,71 @@ +using Asp.Versioning.ApiExplorer; +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Any; +using Swashbuckle.AspNetCore.SwaggerGen; +using Swashbuckle.AspNetCore.SwaggerUI; + +namespace Core.Blueprint.Service.API.Extensions +{ + public static class SwaggerExtensions + { + public static void AddSwagger(this IServiceCollection services) + { + services.AddEndpointsApiExplorer(); + services.AddSwaggerGen(); + services.AddTransient, ConfigureSwaggerOptions>(); + } + + public static void ConfigureSwagger(this WebApplication app) + { + app.UseSwagger(); + app.UseSwaggerUI(options => + { + foreach (var version in app.DescribeApiVersions().Select(version => version.GroupName)) + options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version); + + options.DisplayRequestDuration(); + options.EnableTryItOutByDefault(); + options.DocExpansion(DocExpansion.None); + }); + } + public static IServiceCollection AddVersioning(this IServiceCollection services) + { + services.AddApiVersioning(options => options.ReportApiVersions = true) + .AddApiExplorer(options => + { + options.GroupNameFormat = "'v'VVV"; + options.SubstituteApiVersionInUrl = true; + }); + + return services; + } + } + public class ConfigureSwaggerOptions : IConfigureOptions + { + private readonly IApiVersionDescriptionProvider _provider; + + public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) + { + _provider = provider; + } + + public void Configure(SwaggerGenOptions options) + { + foreach (var description in _provider.ApiVersionDescriptions) + options.SwaggerDoc(description.GroupName, new() + { + Title = AppDomain.CurrentDomain.FriendlyName, + Version = description.ApiVersion.ToString() + }); + + //Map ALL Values Format TODO + options.MapType(() => new() + { + Format = "date", + Example = new OpenApiString(DateOnly.MinValue.ToString()) + }); + + options.CustomSchemaIds(type => type.ToString().Replace("+", ".")); + } + } +} diff --git a/Core.Blueprint.Service.API/Program.cs b/Core.Blueprint.Service.API/Program.cs new file mode 100644 index 0000000..97aefa3 --- /dev/null +++ b/Core.Blueprint.Service.API/Program.cs @@ -0,0 +1,98 @@ + +using Azure.Identity; +using Core.Blueprint.External.ClientConfiguration; +using Core.Blueprint.Logging.Configuration; +using Core.Blueprint.Service.API.Extensions; +using Microsoft.AspNetCore.HttpLogging; +using Microsoft.Extensions.Configuration.AzureAppConfiguration; +using System.Reflection; +using System.Text.Json.Serialization; + +var builder = WebApplication.CreateBuilder(args); + +builder.Configuration.AddAzureAppConfiguration(options => +{ + var endpoint = builder.Configuration.GetSection("Endpoints:AppConfigurationURI").Value; + + if (string.IsNullOrEmpty(endpoint)) + throw new ArgumentException("The app configuration is missing"); + + options.Connect(new Uri(endpoint), new DefaultAzureCredential()) + .Select(KeyFilter.Any, "blueprint_service"); + + options.ConfigureKeyVault(keyVaultOptions => + { + keyVaultOptions.SetCredential(new DefaultAzureCredential()); + }); +}); + +builder.Services.AddLogs(builder); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Configuration + .AddUserSecrets(Assembly.GetExecutingAssembly()) + .AddEnvironmentVariables(); + +builder.Services.RegisterExternalLayer(builder.Configuration); +builder.Services.AddServiceConfigurationLayer(); +builder.Services.AddResponseCompression(); +builder.Services.AddProblemDetails(); +builder.Services.AddMemoryCache(); + +builder.Host.ConfigureServices((context, services) => +{ + + services.AddLogging(); + services.AddControllers(); + services.AddProblemDetails(); + services.AddCors(options + => options.AddDefaultPolicy(policyBuilder + => policyBuilder + .AllowAnyOrigin() + .AllowAnyHeader() + .AllowAnyMethod())); + + builder.Services.Configure(options => + { + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + + services + .AddEndpointsApiExplorer() + .AddVersioning() + .AddSwagger(); + + services.AddHealthChecks(); + services.AddHttpLogging(options => options.LoggingFields = HttpLoggingFields.All); + + builder.Services.AddOutputCache(options => + { + options.AddBasePolicy(builder => + builder.Expire(TimeSpan.FromSeconds(10))); + options.AddPolicy("Expire20", builder => + builder.Expire(TimeSpan.FromSeconds(20))); + options.AddPolicy("Expire30", builder => + builder.Expire(TimeSpan.FromSeconds(30))); + }); + +}); + +var app = builder.Build(); + +app.UseSwagger(); +app.UseSwaggerUI(); + +app.MapControllers(); +app.UseCors(); +app.ConfigureSwagger(); +app.UseHttpsRedirection(); +app.UseStaticFiles(); +app.UseRouting(); +app.UseResponseCompression(); +app.UseOutputCache(); +app.UseResponseCaching(); +app.UseLogging(builder.Configuration); +app.MapHealthChecks("/health"); + +app.Run(); \ No newline at end of file diff --git a/Core.Blueprint.Service.API/Properties/launchSettings.json b/Core.Blueprint.Service.API/Properties/launchSettings.json new file mode 100644 index 0000000..0b4c801 --- /dev/null +++ b/Core.Blueprint.Service.API/Properties/launchSettings.json @@ -0,0 +1,52 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5047" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7243;http://localhost:5047" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_HTTPS_PORTS": "8081", + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:13744", + "sslPort": 44338 + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.API/appsettings.Development.json b/Core.Blueprint.Service.API/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Core.Blueprint.Service.API/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Core.Blueprint.Service.API/appsettings.Local.json b/Core.Blueprint.Service.API/appsettings.Local.json new file mode 100644 index 0000000..3b21203 --- /dev/null +++ b/Core.Blueprint.Service.API/appsettings.Local.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "LocalGateways": { + "BlueprintDAL": "https://localhost:7075/api" + } +} + \ No newline at end of file diff --git a/Core.Blueprint.Service.API/appsettings.json b/Core.Blueprint.Service.API/appsettings.json new file mode 100644 index 0000000..d321977 --- /dev/null +++ b/Core.Blueprint.Service.API/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Endpoints": { + "AppConfigurationURI": "https://sandbox-hci-usc-appcg.azconfig.io" + } +} diff --git a/Core.Blueprint.Service.Domain/Core.Blueprint.Service.Domain.csproj b/Core.Blueprint.Service.Domain/Core.Blueprint.Service.Domain.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/Core.Blueprint.Service.Domain/Core.Blueprint.Service.Domain.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Core.Blueprint.Service.Domain/Dtos/SampleImageUrlDto.cs b/Core.Blueprint.Service.Domain/Dtos/SampleImageUrlDto.cs new file mode 100644 index 0000000..f76e623 --- /dev/null +++ b/Core.Blueprint.Service.Domain/Dtos/SampleImageUrlDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.Domain.Dtos +{ + public class SampleImageUrlDto + { + public string Url { get; set; } + } +} diff --git a/Core.Blueprint.Service.Domain/Entities/BlobSampleImageEntity.cs b/Core.Blueprint.Service.Domain/Entities/BlobSampleImageEntity.cs new file mode 100644 index 0000000..76738ae --- /dev/null +++ b/Core.Blueprint.Service.Domain/Entities/BlobSampleImageEntity.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.Domain.Entities +{ + public class BlobSampleImageEntity + { + public Guid? Id { get; set; } + public byte[] FileContent { get; set; } = []; + } +} diff --git a/Core.Blueprint.Service.Domain/Entities/SecretEntity.cs b/Core.Blueprint.Service.Domain/Entities/SecretEntity.cs new file mode 100644 index 0000000..41d878d --- /dev/null +++ b/Core.Blueprint.Service.Domain/Entities/SecretEntity.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.Domain.Entities +{ + public class SecretEntity + { + public string? Value { get; set; } + } +} diff --git a/Core.Blueprint.Service.Domain/Entities/SqlSampleItemEntity.cs b/Core.Blueprint.Service.Domain/Entities/SqlSampleItemEntity.cs new file mode 100644 index 0000000..aae35e3 --- /dev/null +++ b/Core.Blueprint.Service.Domain/Entities/SqlSampleItemEntity.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.Domain.Entities +{ + public class SqlSampleItemEntity + { + public string? Id { get; set; } + public string TestName { get; set; } = string.Empty; + public char StatusCode { get; set; } = 'P'; + public int NumValue { get; set; } = 0; + public DateTime CreatedAt { get; set; } = DateTime.Now; + } +} diff --git a/Core.Blueprint.Service.External/ClientConfiguration/RegisterClientConfiguration.cs b/Core.Blueprint.Service.External/ClientConfiguration/RegisterClientConfiguration.cs new file mode 100644 index 0000000..02415cd --- /dev/null +++ b/Core.Blueprint.Service.External/ClientConfiguration/RegisterClientConfiguration.cs @@ -0,0 +1,58 @@ +using Core.Blueprint.Service.External.Clients; +using Core.Blueprint.Service.External.GatewayConfigurations; +using Core.Blueprint.Service.External.Helpers.Token; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Refit; + +namespace Core.Blueprint.External.ClientConfiguration +{ + public static class RegisterClientConfiguration + { + public static IServiceCollection RegisterExternalLayer(this IServiceCollection services, IConfiguration configuration) + { + var gatewayConfiguration = new GatewayConfiguration(); + var gatewaySettingsConfiguration = new GatewaySettingsConfiguration(configuration); + + // Register GatewayConfiguration as a singleton + services.AddSingleton(gatewayConfiguration); + + // Register IHttpContextAccessor + services.AddSingleton(); + + // Register ITokenProvider + services.AddSingleton(); + + // Register the custom AuthenticatedHttpClientHandler + services.AddTransient(provider => + { + var tokenProvider = provider.GetRequiredService(); + var handler = new AuthenticatedHttpClientHandler(tokenProvider) + { + InnerHandler = new HttpClientHandler() // Setting the InnerHandler manually + }; + return handler; + }); + + var secretServiceApiUrl = GatewaySettingsConfiguration.GetBlueprintApiEndpoint.Endpoint.Uri; + + // Register IBlueprintServiceClient with the manually created HttpClient + services.AddScoped(provider => + { + var handler = provider.GetRequiredService(); + var httpClient = new HttpClient(handler) + { + BaseAddress = secretServiceApiUrl, + Timeout = TimeSpan.FromMinutes(1) + }; + return RestService.For(httpClient); + }); + + services.AddScoped(); + + return services; + } + } +} diff --git a/Core.Blueprint.Service.External/Clients/Adapters/BlueprintAdapter.cs b/Core.Blueprint.Service.External/Clients/Adapters/BlueprintAdapter.cs new file mode 100644 index 0000000..153ef97 --- /dev/null +++ b/Core.Blueprint.Service.External/Clients/Adapters/BlueprintAdapter.cs @@ -0,0 +1,15 @@ +namespace Core.Blueprint.Service.External.Clients.Adapters +{ + public class BlueprintAdapter + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string _Id { get; set; } = null!; + public string Id { get; init; } = null!; + public DateTime CreatedAt { get; set; } + public string? CreatedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public string? UpdatedBy { get; set; } + public StatusEnum Status { get; set; } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.External/Clients/Adapters/KeyVaultAdapter.cs b/Core.Blueprint.Service.External/Clients/Adapters/KeyVaultAdapter.cs new file mode 100644 index 0000000..80bdaa4 --- /dev/null +++ b/Core.Blueprint.Service.External/Clients/Adapters/KeyVaultAdapter.cs @@ -0,0 +1,10 @@ +using Core.Blueprint.KeyVault; + +namespace Core.Blueprint.Service.External.Clients.Adapters +{ + public class KeyVaultAdapter + { + public KeyVaultResponse Item1 { get; set; } + public string Item2 { get; set; } + } +} diff --git a/Core.Blueprint.Service.External/Clients/Adapters/StatusEnum.cs b/Core.Blueprint.Service.External/Clients/Adapters/StatusEnum.cs new file mode 100644 index 0000000..219b637 --- /dev/null +++ b/Core.Blueprint.Service.External/Clients/Adapters/StatusEnum.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace Core.Blueprint.Service.External.Clients.Adapters +{ + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum StatusEnum + { + + Active = 0, + + Inactive = 1, + + Deleted = 2 + } +} diff --git a/Core.Blueprint.Service.External/Clients/Adapters/UserProjectAdapter.cs b/Core.Blueprint.Service.External/Clients/Adapters/UserProjectAdapter.cs new file mode 100644 index 0000000..9723eac --- /dev/null +++ b/Core.Blueprint.Service.External/Clients/Adapters/UserProjectAdapter.cs @@ -0,0 +1,16 @@ +namespace Core.Blueprint.Service.External.Clients.Adapters +{ + public class UserProjectAdapter + { + public string ProjectCode { get; set; } = null!; + public string ProjectDescription { get; set; } = null!; + public string UserId { get; set; } = null!; + public int Id { get; set; } + public string Guid { get; set; } = null!; + public DateTime CreatedAt { get; set; } + public string? CreatedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public string? UpdatedBy { get; set; } + public StatusEnum Status { get; set; } + } +} diff --git a/Core.Blueprint.Service.External/Clients/IBlueprintServiceClient.cs b/Core.Blueprint.Service.External/Clients/IBlueprintServiceClient.cs new file mode 100644 index 0000000..57b7e10 --- /dev/null +++ b/Core.Blueprint.Service.External/Clients/IBlueprintServiceClient.cs @@ -0,0 +1,67 @@ +using Core.Blueprint.KeyVault; +using Core.Blueprint.Service.External.Clients.Adapters; +using Core.Blueprint.Service.External.Clients.Requests; +using Core.Blueprint.Storage; +using Core.Blueprint.Storage.Adapters; +using Microsoft.AspNetCore.Mvc; +using Refit; + +namespace Core.Blueprint.Service.External.Clients +{ + public interface IBlueprintServiceClient + { + [Post("/v1/MongoBlueprint/Create")] + Task CreateBlueprintAsync([FromBody] BlueprintRequest newBlueprint, CancellationToken cancellationToken = default); + + [Get("/v1/MongoBlueprint/GetAll")] + Task> GetAllBlueprintsAsync(CancellationToken cancellationToken = default); + + [Get("/v1/MongoBlueprint/{_id}/GetBy_Id")] + Task GetBlueprintByIdAsync([FromRoute] string _id, CancellationToken cancellationToken = default); + + [Put("/v1/MongoBlueprint/{_id}/Update")] + Task UpdateBlueprintAsync([FromRoute] string _id, [FromBody] BlueprintAdapter entity, CancellationToken cancellationToken = default); + + [Delete("/v1/MongoBlueprint/{_id}/Delete")] + Task DeleteBlueprintAsync([FromRoute] string _id, CancellationToken cancellationToken = default); + + [Post("/v1/UserProject/Create")] + Task CreateUserProjectAsync([FromBody] UserProjectRequest newUserProject, CancellationToken cancellationToken = default); + + [Get("/v1/UserProject/GetAll")] + Task> GetAllUserProjectsAsync(CancellationToken cancellationToken = default); + + [Get("/v1/UserProject/{id}/GetById")] + Task GetUserProjectByIdAsync([FromRoute] int id, CancellationToken cancellationToken = default); + + [Put("/v1/UserProject/{id}/Update")] + Task UpdateUserProjectAsync([FromRoute] int id, [FromBody] UserProjectAdapter entity, CancellationToken cancellationToken = default); + + [Delete("/v1/UserProject/{id}/Delete")] + Task DeleteUserProjectAsync([FromRoute] int id, CancellationToken cancellationToken = default); + + [Post("/v1/KeyVault/CreateSecret")] + Task CreateSecretAsync([FromBody] KeyVaultRequest newKeyVault, CancellationToken cancellationToken = default); + + [Get("/v1/KeyVault/{secretName}/GetSecret")] + Task GetSecretByNameAsync([FromRoute] string secretName, CancellationToken cancellationToken = default); + + [Put("/v1/KeyVault/UpdateSecret")] + Task UpdateSecretAsync([FromBody] KeyVaultRequest entity, CancellationToken cancellationToken = default); + + [Delete("/v1/KeyVault/{secretName}/DeleteSecret")] + Task DeleteSecretAsync([FromRoute] string secretName, CancellationToken cancellationToken = default); + + [Post("/v1/BlobStorage/UploadBlob")] + Task UploadBlobAsync([FromQuery] BlobAddDto request, CancellationToken cancellationToken = default); + + [Get("/v1/BlobStorage/GetBlobList")] + Task> GetBlobListAsync([FromQuery] string? prefix, CancellationToken cancellationToken = default); + + [Get("/v1/BlobStorage/DownloadBlob")] + Task DownloadBlobAsync([FromQuery] string blobName, CancellationToken cancellationToken = default); + + [Delete("/v1/BlobStorage/DeleteBlob")] + Task DeleteBlobAsync([FromQuery] string blobName, CancellationToken cancellationToken = default); + } +} diff --git a/Core.Blueprint.Service.External/Clients/Requests/BlueprintRequest.cs b/Core.Blueprint.Service.External/Clients/Requests/BlueprintRequest.cs new file mode 100644 index 0000000..9bf5437 --- /dev/null +++ b/Core.Blueprint.Service.External/Clients/Requests/BlueprintRequest.cs @@ -0,0 +1,8 @@ +namespace Core.Blueprint.Service.External.Clients.Requests +{ + public class BlueprintRequest + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + } +} diff --git a/Core.Blueprint.Service.External/Clients/Requests/UserProjectRequest.cs b/Core.Blueprint.Service.External/Clients/Requests/UserProjectRequest.cs new file mode 100644 index 0000000..f111663 --- /dev/null +++ b/Core.Blueprint.Service.External/Clients/Requests/UserProjectRequest.cs @@ -0,0 +1,9 @@ +namespace Core.Blueprint.Service.External.Clients.Requests +{ + public class UserProjectRequest + { + public string ProjectCode { get; set; } = null!; + public string ProjectDescription { get; set; } = null!; + public string UserId { get; set; } = null!; + } +} diff --git a/Core.Blueprint.Service.External/Core.Blueprint.Service.External.csproj b/Core.Blueprint.Service.External/Core.Blueprint.Service.External.csproj new file mode 100644 index 0000000..35e567a --- /dev/null +++ b/Core.Blueprint.Service.External/Core.Blueprint.Service.External.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + ..\..\Dependencies\LSA.Core.Adapters.dll + + + + diff --git a/Core.Blueprint.Service.External/GatewayConfigurations/GatewayConfiguration.cs b/Core.Blueprint.Service.External/GatewayConfigurations/GatewayConfiguration.cs new file mode 100644 index 0000000..030ffd7 --- /dev/null +++ b/Core.Blueprint.Service.External/GatewayConfigurations/GatewayConfiguration.cs @@ -0,0 +1,24 @@ +using Core.Blueprint.External; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.External.GatewayConfigurations +{ + public record GatewayConfiguration + { + public GatewayConfiguration() + { + BlueprintServiceAPI = new BlueprintServiceApi(); + } + public BlueprintServiceApi BlueprintServiceAPI { get; set; } + } + + public record BlueprintServiceApi + { + public string Channel { get; set; } + public BaseEndpoint Endpoint { get; set; } + } +} diff --git a/Core.Blueprint.Service.External/GatewayConfigurations/GatewaySettingsConfiguration.cs b/Core.Blueprint.Service.External/GatewayConfigurations/GatewaySettingsConfiguration.cs new file mode 100644 index 0000000..30144e9 --- /dev/null +++ b/Core.Blueprint.Service.External/GatewayConfigurations/GatewaySettingsConfiguration.cs @@ -0,0 +1,43 @@ +using Core.Blueprint.External; +using Microsoft.Extensions.Configuration; + +namespace Core.Blueprint.Service.External.GatewayConfigurations +{ + public class GatewaySettingsConfiguration + { + private readonly IConfiguration _configuration; + public GatewaySettingsConfiguration(IConfiguration configuration) + { + _configuration = configuration; + this.SetBlueprintServiceApiEndpoint(); + } + private static GatewayConfiguration GatewayConfiguration { get; set; } = new GatewayConfiguration(); + + public static BlueprintServiceApi GetBlueprintApiEndpoint => GatewayConfiguration.BlueprintServiceAPI; + + private GatewayConfiguration SetBlueprintServiceApiEndpoint() + { + IConfigurationSection source; + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? string.Empty; + + if (environment == "Local") + source = _configuration.GetSection("LocalGateways"); + else + source = _configuration.GetSection("Gateways"); + + var endpoint = source["BlueprintDAL"]; + GatewayConfiguration.BlueprintServiceAPI = new BlueprintServiceApi + { + Endpoint = new BaseEndpoint() + { + Uri = new Uri(endpoint), + Url = endpoint, + Token = string.Empty, + APIName = "Blueprint API" + } + }; + + return GatewayConfiguration; + } + } +} diff --git a/Core.Blueprint.Service.External/Helpers/Token/AuthenticatedHttpClientHandler.cs b/Core.Blueprint.Service.External/Helpers/Token/AuthenticatedHttpClientHandler.cs new file mode 100644 index 0000000..e708f7d --- /dev/null +++ b/Core.Blueprint.Service.External/Helpers/Token/AuthenticatedHttpClientHandler.cs @@ -0,0 +1,32 @@ +// *********************************************************************** +// +// Heath +// +// *********************************************************************** + +namespace Core.Blueprint.Service.External.Helpers.Token +{ + /// + /// Class to inject the token in all requests. + /// + public class AuthenticatedHttpClientHandler : DelegatingHandler + { + private readonly ITokenProvider _tokenProvider; + + public AuthenticatedHttpClientHandler(ITokenProvider tokenProvider) + { + _tokenProvider = tokenProvider; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var token = _tokenProvider.GetToken(); + if (!string.IsNullOrEmpty(token)) + { + request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + } + + return await base.SendAsync(request, cancellationToken); + } + } +} diff --git a/Core.Blueprint.Service.External/Helpers/Token/HttpContextTokenProvider.cs b/Core.Blueprint.Service.External/Helpers/Token/HttpContextTokenProvider.cs new file mode 100644 index 0000000..4480e3a --- /dev/null +++ b/Core.Blueprint.Service.External/Helpers/Token/HttpContextTokenProvider.cs @@ -0,0 +1,31 @@ +// *********************************************************************** +// +// Heath +// +// *********************************************************************** + +using Microsoft.AspNetCore.Http; + +namespace Core.Blueprint.Service.External.Helpers.Token +{ + /// + /// Class to return the access token to controllers. + /// + public class HttpContextTokenProvider : ITokenProvider + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public HttpContextTokenProvider(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + /// + /// Get token from headers. + /// + public string GetToken() + { + return _httpContextAccessor.HttpContext?.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last(); + } + } +} diff --git a/Core.Blueprint.Service.External/Helpers/Token/ITokenProvider.cs b/Core.Blueprint.Service.External/Helpers/Token/ITokenProvider.cs new file mode 100644 index 0000000..7c68a0a --- /dev/null +++ b/Core.Blueprint.Service.External/Helpers/Token/ITokenProvider.cs @@ -0,0 +1,19 @@ +// *********************************************************************** +// +// Heath +// +// *********************************************************************** + +namespace Core.Blueprint.Service.External.Helpers.Token +{ + /// + /// Interface for token provider. + /// + public interface ITokenProvider + { + /// + /// Get token from headers. + /// + string GetToken(); + } +} diff --git a/Core.Blueprint.Service.Testing/Core.Blueprint.Service.Testing.csproj b/Core.Blueprint.Service.Testing/Core.Blueprint.Service.Testing.csproj new file mode 100644 index 0000000..7dc0a2a --- /dev/null +++ b/Core.Blueprint.Service.Testing/Core.Blueprint.Service.Testing.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/Core.Blueprint.Service.Testing/GlobalUsings.cs b/Core.Blueprint.Service.Testing/GlobalUsings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/Core.Blueprint.Service.Testing/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/Core.Blueprint.Service.Testing/UnitTest1.cs b/Core.Blueprint.Service.Testing/UnitTest1.cs new file mode 100644 index 0000000..938ec39 --- /dev/null +++ b/Core.Blueprint.Service.Testing/UnitTest1.cs @@ -0,0 +1,11 @@ +namespace Core.Blueprint.Service.Testing +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.Service.UseCases/BluePrint/BlueprintService.cs b/Core.Blueprint.Service.UseCases/BluePrint/BlueprintService.cs new file mode 100644 index 0000000..e4d97fa --- /dev/null +++ b/Core.Blueprint.Service.UseCases/BluePrint/BlueprintService.cs @@ -0,0 +1,90 @@ +using Core.Blueprint.Service.External.Clients; +using Core.Blueprint.Service.External.Clients.BluePrintService; +using Refit; + +namespace Core.Blueprint.Service.UseCases.BluePrint +{ + public interface IBlueprintService + { + Task> GetBlueprintsAsync(); + Task GetBlueprintAsync(string id); + Task CreateBlueprintAsync(MongoBlueprintCollection blueprint); + Task UpdateBlueprintAsync(string id, MongoBlueprintCollection blueprint); + Task DeleteBlueprintAsync(string id); + + } + public class BlueprintService: IBlueprintService + { + private readonly IBluePrintServiceClient _blueprintApi; + + public BlueprintService(IBluePrintServiceClient client) + { + _blueprintApi = client; + } + + public async Task> GetBlueprintsAsync() + { + try + { + return await _blueprintApi.GetBlueprintsAsync(); + } + catch (ApiException ex) + { + Console.WriteLine($"Error fetching blueprints: {ex.Message}"); + throw; + } + } + + public async Task GetBlueprintAsync(string id) + { + try + { + return await _blueprintApi.GetBlueprintAsync(id); + } + catch (ApiException ex) + { + Console.WriteLine($"Error fetching blueprint with ID {id}: {ex.Message}"); + throw; + } + } + + public async Task CreateBlueprintAsync(MongoBlueprintCollection blueprint) + { + try + { + return await _blueprintApi.CreateBlueprintAsync(blueprint); + } + catch (ApiException ex) + { + Console.WriteLine($"Error creating blueprint: {ex.Message}"); + throw; + } + } + + public async Task UpdateBlueprintAsync(string id, MongoBlueprintCollection blueprint) + { + try + { + await _blueprintApi.UpdateBlueprintAsync(id, blueprint); + } + catch (ApiException ex) + { + Console.WriteLine($"Error updating blueprint with ID {id}: {ex.Message}"); + throw; + } + } + + public async Task DeleteBlueprintAsync(string id) + { + try + { + await _blueprintApi.DeleteBlueprintAsync(id); + } + catch (ApiException ex) + { + Console.WriteLine($"Error deleting blueprint with ID {id}: {ex.Message}"); + throw; + } + } + } +} diff --git a/Core.Blueprint.Service.UseCases/Configuration/UseCasesConfiguration.cs b/Core.Blueprint.Service.UseCases/Configuration/UseCasesConfiguration.cs new file mode 100644 index 0000000..f6c605a --- /dev/null +++ b/Core.Blueprint.Service.UseCases/Configuration/UseCasesConfiguration.cs @@ -0,0 +1,74 @@ +using Core.Blueprint.Service.UseCases.CreateSampleItem; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Adapter; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Input; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Ports; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Validator; +using Core.Blueprint.Service.UseCases.DeleteSampleItem; +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Adapter; +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Input; +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Ports; +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Validator; +using Core.Blueprint.Service.UseCases.GetOneSampleItem; +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Adapter; +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Input; +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Ports; +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Validator; +using Core.Blueprint.Service.UseCases.GetSampleImage; +using Core.Blueprint.Service.UseCases.GetSampleImage.Adapter; +using Core.Blueprint.Service.UseCases.GetSampleImage.Input; +using Core.Blueprint.Service.UseCases.GetSampleImage.Ports; +using Core.Blueprint.Service.UseCases.GetSampleImage.Validator; +using Core.Blueprint.Service.UseCases.GetSampleItems; +using Core.Blueprint.Service.UseCases.GetSampleItems.Adapter; +using Core.Blueprint.Service.UseCases.GetSampleItems.Input; +using Core.Blueprint.Service.UseCases.GetSampleItems.Ports; +using Core.Blueprint.Service.UseCases.GetSampleItems.Validator; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Adapter; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Input; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Ports; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Validator; +using Core.Blueprint.Service.UseCases.UpdateSampleItem; +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Adapter; +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Input; +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Ports; +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Validator; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using Microsoft.Extensions.DependencyInjection; + +namespace Core.Blueprint.Service.UseCases.Configuration +{ + public static class UseCasesConfiguration + { + public static IServiceCollection AddUseCasesLayer(this IServiceCollection services) + { + services + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + + .AddScoped, GetSampleItemValidator>() + .AddScoped, GetOneSampleItemValidator>() + .AddScoped, CreateSampleItemValidator>() + .AddScoped, UpdateSampleItemValidator>() + .AddScoped, DeleteSampleItemValidator>() + .AddScoped, GetSampleImageValidator>() + .AddScoped, GetUploadUrlValidator>() + + .AddScoped, GetSampleItemsHandler>() + .AddScoped, GetOneSampleItemHandler>() + .AddScoped, CreateSampleItemHandler>() + .AddScoped, UpdateSampleItemHandler>() + .AddScoped, DeleteSampleItemHandler>() + .AddScoped, GetSampleImageHandler>() + .AddScoped, GetUploadUrlHandler>(); + + return services; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/Core.Blueprint.Service.UseCases.csproj b/Core.Blueprint.Service.UseCases/Core.Blueprint.Service.UseCases.csproj new file mode 100644 index 0000000..8342531 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/Core.Blueprint.Service.UseCases.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/Core.Blueprint.Service.UseCases/CreateSampleImage/Adapter/CreateSampleImagePort.cs b/Core.Blueprint.Service.UseCases/CreateSampleImage/Adapter/CreateSampleImagePort.cs new file mode 100644 index 0000000..0abf8a1 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleImage/Adapter/CreateSampleImagePort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.UseCases.CreateSampleImage.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.CreateSampleImage.Adapter +{ + public class CreateSampleImagePort : BasePresenter, ICreateSampleImagePort + { + public void Success(SqlSampleItemEntity output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleImage/CreateSampleItemHandler.cs b/Core.Blueprint.Service.UseCases/CreateSampleImage/CreateSampleItemHandler.cs new file mode 100644 index 0000000..7f8fd0a --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleImage/CreateSampleItemHandler.cs @@ -0,0 +1,44 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.External.Clients.SampleItemClient; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Input; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.CreateSampleImage +{ + public class CreateSampleItemHandler(ICreateSampleItemPort port, IValidator validator, ISampleItemClientService clientService) : IComponentHandler + { + private readonly ICreateSampleItemPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleItemClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(CreateSampleItemRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _clientService.CreateSampleItemAsync( + new SqlSampleItemEntity { TestName = command.TestName, NumValue = command.NumValue }); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch(Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleImage/Input/CreateSampleImageRequest.cs b/Core.Blueprint.Service.UseCases/CreateSampleImage/Input/CreateSampleImageRequest.cs new file mode 100644 index 0000000..9a3b168 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleImage/Input/CreateSampleImageRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.CreateSampleImage.Input +{ + public class CreateSampleImageRequest : Notificator, ICommand + { + public Guid? Id; + public byte[] NumValue { get; set; } = []; + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleImage/Ports/ICreateSampleImagePort.cs b/Core.Blueprint.Service.UseCases/CreateSampleImage/Ports/ICreateSampleImagePort.cs new file mode 100644 index 0000000..3b6f508 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleImage/Ports/ICreateSampleImagePort.cs @@ -0,0 +1,9 @@ +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.CreateSampleImage.Ports +{ + public interface ICreateSampleImagePort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleImage/Validator/CreateSampleImageValidator.cs b/Core.Blueprint.Service.UseCases/CreateSampleImage/Validator/CreateSampleImageValidator.cs new file mode 100644 index 0000000..c3ac2d6 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleImage/Validator/CreateSampleImageValidator.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.UseCases.CreateSampleItem.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.CreateSampleImage.Validator +{ + [ExcludeFromCodeCoverage] + public class CreateSampleImageValidator : AbstractValidator + { + public CreateSampleImageValidator() + { + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleItem/Adapter/CreateSampleItemPort.cs b/Core.Blueprint.Service.UseCases/CreateSampleItem/Adapter/CreateSampleItemPort.cs new file mode 100644 index 0000000..ccb0ec6 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleItem/Adapter/CreateSampleItemPort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Adapter +{ + public class CreateSampleItemPort : BasePresenter, ICreateSampleItemPort + { + public void Success(SqlSampleItemEntity output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleItem/CreateSampleItemHandler.cs b/Core.Blueprint.Service.UseCases/CreateSampleItem/CreateSampleItemHandler.cs new file mode 100644 index 0000000..0b9b2e9 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleItem/CreateSampleItemHandler.cs @@ -0,0 +1,44 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.External.Clients.SampleItemClient; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Input; +using Core.Blueprint.Service.UseCases.CreateSampleItem.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.CreateSampleItem +{ + public class CreateSampleItemHandler(ICreateSampleItemPort port, IValidator validator, ISampleItemClientService clientService) : IComponentHandler + { + private readonly ICreateSampleItemPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleItemClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(CreateSampleItemRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _clientService.CreateSampleItemAsync( + new SqlSampleItemEntity { TestName = command.TestName, NumValue = command.NumValue }); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch(Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleItem/Input/CreateSampleItemRequest.cs b/Core.Blueprint.Service.UseCases/CreateSampleItem/Input/CreateSampleItemRequest.cs new file mode 100644 index 0000000..8ced923 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleItem/Input/CreateSampleItemRequest.cs @@ -0,0 +1,14 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Input +{ + public class CreateSampleItemRequest : Notificator, ICommand + { + public string TestName { get; set; } = string.Empty; + public int NumValue { get; set; } = 0; + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleItem/Ports/ICreateSampleItemPort.cs b/Core.Blueprint.Service.UseCases/CreateSampleItem/Ports/ICreateSampleItemPort.cs new file mode 100644 index 0000000..6f9e2e5 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleItem/Ports/ICreateSampleItemPort.cs @@ -0,0 +1,9 @@ +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Ports +{ + public interface ICreateSampleItemPort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/CreateSampleItem/Validator/CreateSampleItemValidator.cs b/Core.Blueprint.Service.UseCases/CreateSampleItem/Validator/CreateSampleItemValidator.cs new file mode 100644 index 0000000..36c4dc4 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/CreateSampleItem/Validator/CreateSampleItemValidator.cs @@ -0,0 +1,16 @@ +using Core.Blueprint.Service.UseCases.CreateSampleItem.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Validator +{ + [ExcludeFromCodeCoverage] + public class CreateSampleItemValidator : AbstractValidator + { + public CreateSampleItemValidator() + { + RuleFor(i => i.TestName).NotNull().NotEmpty().WithMessage("Is required."); + RuleFor(i => i.NumValue).GreaterThanOrEqualTo(1).LessThanOrEqualTo(100).WithMessage("Should be between 1-100."); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/DeleteSampleItem/Adapter/DeleteSampleItemPort.cs b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Adapter/DeleteSampleItemPort.cs new file mode 100644 index 0000000..2f83a9a --- /dev/null +++ b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Adapter/DeleteSampleItemPort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.DeleteSampleItem.Adapter +{ + public class DeleteSampleItemPort : BasePresenter, IDeleteSampleItemPort + { + public void Success(SqlSampleItemEntity output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/DeleteSampleItem/DeleteSampleItemHandler.cs b/Core.Blueprint.Service.UseCases/DeleteSampleItem/DeleteSampleItemHandler.cs new file mode 100644 index 0000000..ecbf443 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/DeleteSampleItem/DeleteSampleItemHandler.cs @@ -0,0 +1,42 @@ +using Core.Blueprint.Service.External.Clients.SampleItemClient; +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Input; +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.DeleteSampleItem +{ + public class DeleteSampleItemHandler(IDeleteSampleItemPort port, IValidator validator, ISampleItemClientService clientService) : IComponentHandler + { + private readonly IDeleteSampleItemPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleItemClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(DeleteSampleItemRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + var entity = await _clientService.GetSampleItemAsync(command.Id); + if (entity == null) + { + _port.BusinessError("Not Found"); + return; + } + entity.StatusCode = 'D'; + await _clientService.UpdateSampleItemAsync(command.Id, entity); + + _port.NoContentSuccess(); + } + catch(Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/DeleteSampleItem/Input/DeleteSampleItemRequest.cs b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Input/DeleteSampleItemRequest.cs new file mode 100644 index 0000000..688b5e3 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Input/DeleteSampleItemRequest.cs @@ -0,0 +1,13 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.DeleteSampleItem.Input +{ + public class DeleteSampleItemRequest : Notificator, ICommand + { + public string Id { get; set; } = string.Empty; + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/DeleteSampleItem/Ports/IDeleteSampleItemPort.cs b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Ports/IDeleteSampleItemPort.cs new file mode 100644 index 0000000..71d17f7 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Ports/IDeleteSampleItemPort.cs @@ -0,0 +1,9 @@ +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.DeleteSampleItem.Ports +{ + public interface IDeleteSampleItemPort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/DeleteSampleItem/Validator/DeleteSampleItemValidator.cs b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Validator/DeleteSampleItemValidator.cs new file mode 100644 index 0000000..09d870a --- /dev/null +++ b/Core.Blueprint.Service.UseCases/DeleteSampleItem/Validator/DeleteSampleItemValidator.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.UseCases.DeleteSampleItem.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.DeleteSampleItem.Validator +{ + [ExcludeFromCodeCoverage] + public class DeleteSampleItemValidator : AbstractValidator + { + public DeleteSampleItemValidator() + { + RuleFor(i => i.Id).NotNull().NotEmpty().WithMessage("Is required."); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetOneSampleItem/Adapter/GetOneSampleItemPort.cs b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Adapter/GetOneSampleItemPort.cs new file mode 100644 index 0000000..5ab7ba0 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Adapter/GetOneSampleItemPort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.GetOneSampleItem.Adapter +{ + public class GetOneSampleItemPort : BasePresenter, IGetOneSampleItemPort + { + public void Success(SqlSampleItemEntity output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetOneSampleItem/GetOneSampleItemHandler.cs b/Core.Blueprint.Service.UseCases/GetOneSampleItem/GetOneSampleItemHandler.cs new file mode 100644 index 0000000..210da3f --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetOneSampleItem/GetOneSampleItemHandler.cs @@ -0,0 +1,42 @@ +using Core.Blueprint.Service.External.Clients.SampleItemClient; +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Input; +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetOneSampleItem +{ + public class GetOneSampleItemHandler(IGetOneSampleItemPort port, IValidator validator, ISampleItemClientService clientService) : IComponentHandler + { + private readonly IGetOneSampleItemPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleItemClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(GetOneSampleItemRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _clientService.GetSampleItemAsync(command.Id); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch(Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetOneSampleItem/Input/GetOneSampleItemRequest.cs b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Input/GetOneSampleItemRequest.cs new file mode 100644 index 0000000..f5a128c --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Input/GetOneSampleItemRequest.cs @@ -0,0 +1,17 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetOneSampleItem.Input +{ + public class GetOneSampleItemRequest : Notificator, ICommand + { + public GetOneSampleItemRequest(string id) + { + Id = id; + } + public string Id { get; set; } = string.Empty; + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetOneSampleItem/Ports/IGetOneSampleItemPort.cs b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Ports/IGetOneSampleItemPort.cs new file mode 100644 index 0000000..a7faf7c --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Ports/IGetOneSampleItemPort.cs @@ -0,0 +1,9 @@ +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetOneSampleItem.Ports +{ + public interface IGetOneSampleItemPort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/GetOneSampleItem/Validator/GetOneSampleItemValidator.cs b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Validator/GetOneSampleItemValidator.cs new file mode 100644 index 0000000..6015ecb --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetOneSampleItem/Validator/GetOneSampleItemValidator.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.UseCases.GetOneSampleItem.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.GetOneSampleItem.Validator +{ + [ExcludeFromCodeCoverage] + public class GetOneSampleItemValidator : AbstractValidator + { + public GetOneSampleItemValidator() + { + RuleFor(i => i.Id).NotNull().NotEmpty().WithMessage("Is required."); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleImage/Adapter/GetSampleImagePort.cs b/Core.Blueprint.Service.UseCases/GetSampleImage/Adapter/GetSampleImagePort.cs new file mode 100644 index 0000000..a4baa61 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleImage/Adapter/GetSampleImagePort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Dtos; +using Core.Blueprint.Service.UseCases.GetSampleImage.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.GetSampleImage.Adapter +{ + public class GetSampleImagePort : BasePresenter, IGetSampleImagePort + { + public void Success(SampleImageUrlDto output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleImage/GetSampleImageHandler.cs b/Core.Blueprint.Service.UseCases/GetSampleImage/GetSampleImageHandler.cs new file mode 100644 index 0000000..a441526 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleImage/GetSampleImageHandler.cs @@ -0,0 +1,43 @@ +using Core.Blueprint.Service.Domain.Dtos; +using Core.Blueprint.Service.External.Clients.SampleImageClient; +using Core.Blueprint.Service.UseCases.GetSampleImage.Input; +using Core.Blueprint.Service.UseCases.GetSampleImage.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetSampleImage +{ + public class GetSampleImageHandler(IGetSampleImagePort port, IValidator validator, ISampleImageClientService clientService) : IComponentHandler + { + private readonly IGetSampleImagePort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleImageClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(GetSampleImageRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _clientService.GetFirstImageUrl(); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch(Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleImage/Input/GetSampleImageRequest.cs b/Core.Blueprint.Service.UseCases/GetSampleImage/Input/GetSampleImageRequest.cs new file mode 100644 index 0000000..92c74d3 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleImage/Input/GetSampleImageRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetSampleImage.Input +{ + public class GetSampleImageRequest : Notificator, ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleImage/Ports/IGetSampleImagePort.cs b/Core.Blueprint.Service.UseCases/GetSampleImage/Ports/IGetSampleImagePort.cs new file mode 100644 index 0000000..74a062d --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleImage/Ports/IGetSampleImagePort.cs @@ -0,0 +1,10 @@ +using Core.Blueprint.Service.Domain.Dtos; +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetSampleImage.Ports +{ + public interface IGetSampleImagePort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleImage/Validator/GetSampleImageValidator.cs b/Core.Blueprint.Service.UseCases/GetSampleImage/Validator/GetSampleImageValidator.cs new file mode 100644 index 0000000..b196341 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleImage/Validator/GetSampleImageValidator.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.UseCases.GetSampleImage.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.GetSampleImage.Validator +{ + [ExcludeFromCodeCoverage] + public class GetSampleImageValidator : AbstractValidator + { + public GetSampleImageValidator() + { + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleItems/Adapter/GetSampleItemsPort.cs b/Core.Blueprint.Service.UseCases/GetSampleItems/Adapter/GetSampleItemsPort.cs new file mode 100644 index 0000000..38c14eb --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleItems/Adapter/GetSampleItemsPort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.UseCases.GetSampleItems.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.GetSampleItems.Adapter +{ + public class GetSampleItemsPort : BasePresenter, IGetSampleItemsPort + { + public void Success(List output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleItems/GetSampleItemsHandler.cs b/Core.Blueprint.Service.UseCases/GetSampleItems/GetSampleItemsHandler.cs new file mode 100644 index 0000000..261c270 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleItems/GetSampleItemsHandler.cs @@ -0,0 +1,42 @@ +using Core.Blueprint.Service.External.Clients.SampleItemClient; +using Core.Blueprint.Service.UseCases.GetSampleItems.Ports; +using Core.Blueprint.Service.UseCases.GetSampleItems.Input; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetSampleItems +{ + public class GetSampleItemsHandler(IGetSampleItemsPort port, IValidator validator, ISampleItemClientService clientService) : IComponentHandler + { + private readonly IGetSampleItemsPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleItemClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(GetSampleItemsRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + } + + var result = await _clientService.GetSampleItemsAsync(); + + if (!result.Any()) + { + _port.NoContentSuccess(); + return; + } + + + _port.Success(result.Where(item => item.StatusCode != 'D').ToList()); + } + catch(Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleItems/Input/GetSampleItemsRequest.cs b/Core.Blueprint.Service.UseCases/GetSampleItems/Input/GetSampleItemsRequest.cs new file mode 100644 index 0000000..53a678f --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleItems/Input/GetSampleItemsRequest.cs @@ -0,0 +1,15 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetSampleItems.Input +{ + public class GetSampleItemsRequest : Notificator, ICommand + { + public Guid Id { get; set; } + public string TestName { get; set; } + public int NumValue { get; set; } + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleItems/Ports/IGetSampleItemsPort.cs b/Core.Blueprint.Service.UseCases/GetSampleItems/Ports/IGetSampleItemsPort.cs new file mode 100644 index 0000000..71bc162 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleItems/Ports/IGetSampleItemsPort.cs @@ -0,0 +1,9 @@ +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetSampleItems.Ports +{ + public interface IGetSampleItemsPort : IBasePort, ICommandSuccessPort>, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSampleItems/Validator/GetSampleItemValidator.cs b/Core.Blueprint.Service.UseCases/GetSampleItems/Validator/GetSampleItemValidator.cs new file mode 100644 index 0000000..2ab2507 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSampleItems/Validator/GetSampleItemValidator.cs @@ -0,0 +1,16 @@ +using Core.Blueprint.Service.UseCases.GetSampleItems.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.GetSampleItems.Validator +{ + [ExcludeFromCodeCoverage] + public class GetSampleItemValidator : AbstractValidator + { + public GetSampleItemValidator() + { + RuleFor(i => i.NumValue).GreaterThanOrEqualTo(0).LessThanOrEqualTo(100).WithMessage("Should be between 0 and 100."); + RuleFor(i => i.TestName).NotNull().NotEmpty().WithMessage("Is required."); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSecret/Adapter/GetSecretPort.cs b/Core.Blueprint.Service.UseCases/GetSecret/Adapter/GetSecretPort.cs new file mode 100644 index 0000000..0f07026 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSecret/Adapter/GetSecretPort.cs @@ -0,0 +1,22 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.UseCases.GetSampleItems.Ports; +using Core.Blueprint.Service.UseCases.GetSecret.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.UseCases.GetSecret.Adapter +{ + public class GetSecretPort : BasePresenter, IGetSecretPort + { + + public void Success(SecretEntity output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSecret/GetSecretHandler.cs b/Core.Blueprint.Service.UseCases/GetSecret/GetSecretHandler.cs new file mode 100644 index 0000000..01c864d --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSecret/GetSecretHandler.cs @@ -0,0 +1,50 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.External.Clients.SecretClient; +using Core.Blueprint.Service.UseCases.GetSampleItems.Input; +using Core.Blueprint.Service.UseCases.GetSampleItems.Ports; +using Core.Blueprint.Service.UseCases.GetSecret.Input; +using Core.Blueprint.Service.UseCases.GetSecret.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.UseCases.GetSecret +{ + public class GetSecretHandler(IGetSecretPort port, IValidator validator, ISecretService secretService) : IComponentHandler + { + private readonly IGetSecretPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISecretService _secretService = secretService; + + public async ValueTask ExecuteAsync(GetSecretRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + } + + var result = await _secretService.GetSecretAsync(command.Secret); + + if (result is null || string.IsNullOrWhiteSpace(result.Value)) + { + _port.NoContentSuccess(); + return; + } + + + _port.Success(result); + } + catch (Exception ex) + { + _port.BusinessError(ex.Message); + } + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSecret/Input/GetSecretRequest.cs b/Core.Blueprint.Service.UseCases/GetSecret/Input/GetSecretRequest.cs new file mode 100644 index 0000000..af073e3 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSecret/Input/GetSecretRequest.cs @@ -0,0 +1,19 @@ +using Lib.Architecture.BuildingBlocks; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.UseCases.GetSecret.Input +{ + public class GetSecretRequest : Notificator, ICommand + { + public string? Secret { get; set; } + + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSecret/Ports/IGetSecretPort.cs b/Core.Blueprint.Service.UseCases/GetSecret/Ports/IGetSecretPort.cs new file mode 100644 index 0000000..354242f --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSecret/Ports/IGetSecretPort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Dtos; +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.UseCases.GetSecret.Ports +{ + public interface IGetSecretPort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/GetSecret/Validator/GetSecretValidator.cs b/Core.Blueprint.Service.UseCases/GetSecret/Validator/GetSecretValidator.cs new file mode 100644 index 0000000..66d7133 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetSecret/Validator/GetSecretValidator.cs @@ -0,0 +1,21 @@ +using Core.Blueprint.Service.UseCases.GetSampleItems.Input; +using Core.Blueprint.Service.UseCases.GetSecret.Input; +using FluentValidation; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Blueprint.Service.UseCases.GetSecret.Validator +{ + [ExcludeFromCodeCoverage] + public class GetSecretValidator : AbstractValidator + { + public GetSecretValidator() + { + RuleFor(i => i.Secret).NotNull().NotEmpty().WithMessage("Is required."); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Adapter/GetUploadUrlPort.cs b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Adapter/GetUploadUrlPort.cs new file mode 100644 index 0000000..c4fe7cc --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Adapter/GetUploadUrlPort.cs @@ -0,0 +1,16 @@ +using Core.Blueprint.Service.Domain.Dtos; +using Core.Blueprint.Service.UseCases.GetSampleImage.Ports; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.GetUploadImageUrl.Adapter +{ + public class GetUploadUrlPort : BasePresenter, IGetUploadUrlPort + { + public void Success(SampleImageUrlDto output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetUploadImageUrl/GetUploadUrlHandler.cs b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/GetUploadUrlHandler.cs new file mode 100644 index 0000000..1815f62 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/GetUploadUrlHandler.cs @@ -0,0 +1,42 @@ +using Core.Blueprint.Service.External.Clients.SampleImageClient; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Input; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetUploadImageUrl +{ + public class GetUploadUrlHandler(IGetUploadUrlPort port, IValidator validator, ISampleImageClientService clientService) : IComponentHandler + { + private readonly IGetUploadUrlPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleImageClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(GetUploadUrlRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _clientService.GetUploadUrl(); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch(Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Input/GetUploadUrlRequest.cs b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Input/GetUploadUrlRequest.cs new file mode 100644 index 0000000..c60e93f --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Input/GetUploadUrlRequest.cs @@ -0,0 +1,12 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetUploadImageUrl.Input +{ + public class GetUploadUrlRequest : Notificator, ICommand + { + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Ports/IGetUploadUrlPort.cs b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Ports/IGetUploadUrlPort.cs new file mode 100644 index 0000000..3d2e93b --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Ports/IGetUploadUrlPort.cs @@ -0,0 +1,10 @@ +using Core.Blueprint.Service.Domain.Dtos; +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.GetUploadImageUrl.Ports +{ + public interface IGetUploadUrlPort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Validator/GetUploadUrlValidator.cs b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Validator/GetUploadUrlValidator.cs new file mode 100644 index 0000000..3ea37f0 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/GetUploadImageUrl/Validator/GetUploadUrlValidator.cs @@ -0,0 +1,16 @@ +using Core.Blueprint.Service.UseCases.GetSampleImage.Input; +using Core.Blueprint.Service.UseCases.GetUploadImageUrl.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.GetUploadImageUrl.Validator +{ + [ExcludeFromCodeCoverage] + public class GetUploadUrlValidator : AbstractValidator + { + public GetUploadUrlValidator() + { + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/UpdateSampleItem/Adapter/UpdateSampleItemPort.cs b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Adapter/UpdateSampleItemPort.cs new file mode 100644 index 0000000..c20d75a --- /dev/null +++ b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Adapter/UpdateSampleItemPort.cs @@ -0,0 +1,15 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Ports; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; + +namespace Core.Blueprint.Service.UseCases.UpdateSampleItem.Adapter +{ + public class UpdateSampleItemPort : BasePresenter, IUpdateSampleItemPort + { + public void Success(SqlSampleItemEntity output) + { + ViewModel = new OkObjectResult(output); + } + } +} diff --git a/Core.Blueprint.Service.UseCases/UpdateSampleItem/Input/UpdateSampleItemRequest.cs b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Input/UpdateSampleItemRequest.cs new file mode 100644 index 0000000..d5ae095 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Input/UpdateSampleItemRequest.cs @@ -0,0 +1,17 @@ +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.UpdateSampleItem.Input +{ + public class UpdateSampleItemRequest : Notificator, ICommand + { + public string Id { get; set; } = string.Empty; + public string TestName { get; set; } = string.Empty; + public int NumValue { get; set; } = 0; + public char StatusCode { get; set; } = 'P'; + + public bool Validate() + { + return true; + } + } +} diff --git a/Core.Blueprint.Service.UseCases/UpdateSampleItem/Ports/IUpdateSampleItemPort.cs b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Ports/IUpdateSampleItemPort.cs new file mode 100644 index 0000000..a3e4125 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Ports/IUpdateSampleItemPort.cs @@ -0,0 +1,9 @@ +using Core.Blueprint.Service.Domain.Entities; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.UpdateSampleItem.Ports +{ + public interface IUpdateSampleItemPort : IBasePort, ICommandSuccessPort, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort + { + } +} diff --git a/Core.Blueprint.Service.UseCases/UpdateSampleItem/UpdateSampleItemHandler.cs b/Core.Blueprint.Service.UseCases/UpdateSampleItem/UpdateSampleItemHandler.cs new file mode 100644 index 0000000..dfc52a2 --- /dev/null +++ b/Core.Blueprint.Service.UseCases/UpdateSampleItem/UpdateSampleItemHandler.cs @@ -0,0 +1,45 @@ +using Core.Blueprint.Service.Domain.Entities; +using Core.Blueprint.Service.External.Clients.SampleItemClient; +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Input; +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Ports; +using FluentValidation; +using Lib.Architecture.BuildingBlocks; + +namespace Core.Blueprint.Service.UseCases.UpdateSampleItem +{ + public class UpdateSampleItemHandler(IUpdateSampleItemPort port, IValidator validator, ISampleItemClientService clientService) : IComponentHandler + { + private readonly IUpdateSampleItemPort _port = port; + private readonly IValidator _validator = validator; + private readonly ISampleItemClientService _clientService = clientService; + + public async ValueTask ExecuteAsync(UpdateSampleItemRequest command, CancellationToken cancellationToken = default) + { + try + { + if (!command.IsValid(_validator)) + { + _port.ValidationErrors(command.Notifications); + return; + } + + var result = await _clientService.UpdateSampleItemAsync(command.Id, + + new SqlSampleItemEntity { Id = command.Id, TestName = command.TestName, NumValue = command.NumValue, StatusCode = command.StatusCode }); + + if (result == null) + { + _port.NoContentSuccess(); + return; + } + + _port.Success(result); + } + catch (Exception ex) + { + _port.BusinessError(ex.Message); + } + + } + } +} diff --git a/Core.Blueprint.Service.UseCases/UpdateSampleItem/Validator/UpdateSampleItemValidator.cs b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Validator/UpdateSampleItemValidator.cs new file mode 100644 index 0000000..2e900ac --- /dev/null +++ b/Core.Blueprint.Service.UseCases/UpdateSampleItem/Validator/UpdateSampleItemValidator.cs @@ -0,0 +1,16 @@ +using Core.Blueprint.Service.UseCases.UpdateSampleItem.Input; +using FluentValidation; +using System.Diagnostics.CodeAnalysis; + +namespace Core.Blueprint.Service.UseCases.UpdateSampleItem.Validator +{ + [ExcludeFromCodeCoverage] + public class UpdateSampleItemValidator : AbstractValidator + { + public UpdateSampleItemValidator() + { + RuleFor(i => i.TestName).NotNull().NotEmpty().WithMessage("Is required."); + RuleFor(i => i.NumValue).GreaterThanOrEqualTo(1).LessThanOrEqualTo(100).WithMessage("Should be between 1-100."); + } + } +} diff --git a/Core.Blueprint.Service.sln b/Core.Blueprint.Service.sln new file mode 100644 index 0000000..fa2c60c --- /dev/null +++ b/Core.Blueprint.Service.sln @@ -0,0 +1,55 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34309.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.Service.API", "Core.Blueprint.Service.API\Core.Blueprint.Service.API.csproj", "{9233C05A-ABE8-44AB-B69B-5CF24CB30D81}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.Service.External", "Core.Blueprint.Service.External\Core.Blueprint.Service.External.csproj", "{96B13FBF-EF87-4544-9A02-AC59856366F3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Testing", "Testing", "{BECF75F3-FA74-4A0D-8E0C-7C8C1A7C1B26}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.Service.Testing", "Core.Blueprint.Service.Testing\Core.Blueprint.Service.Testing.csproj", "{9D42C248-4553-4E1C-B4AE-E9F2D7E37587}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{0445D673-FB74-412E-9227-6C5BDB60DA82}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{E7AD384D-7A0F-4278-8337-2B52EDB4BE82}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.Application", "Core.Blueprint.Application\Core.Blueprint.Application.csproj", "{CF193A31-A157-4B93-9EE6-DDBC7C7E712E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9233C05A-ABE8-44AB-B69B-5CF24CB30D81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9233C05A-ABE8-44AB-B69B-5CF24CB30D81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9233C05A-ABE8-44AB-B69B-5CF24CB30D81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9233C05A-ABE8-44AB-B69B-5CF24CB30D81}.Release|Any CPU.Build.0 = Release|Any CPU + {96B13FBF-EF87-4544-9A02-AC59856366F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96B13FBF-EF87-4544-9A02-AC59856366F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96B13FBF-EF87-4544-9A02-AC59856366F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96B13FBF-EF87-4544-9A02-AC59856366F3}.Release|Any CPU.Build.0 = Release|Any CPU + {9D42C248-4553-4E1C-B4AE-E9F2D7E37587}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D42C248-4553-4E1C-B4AE-E9F2D7E37587}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D42C248-4553-4E1C-B4AE-E9F2D7E37587}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D42C248-4553-4E1C-B4AE-E9F2D7E37587}.Release|Any CPU.Build.0 = Release|Any CPU + {CF193A31-A157-4B93-9EE6-DDBC7C7E712E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF193A31-A157-4B93-9EE6-DDBC7C7E712E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF193A31-A157-4B93-9EE6-DDBC7C7E712E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF193A31-A157-4B93-9EE6-DDBC7C7E712E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {9233C05A-ABE8-44AB-B69B-5CF24CB30D81} = {E7AD384D-7A0F-4278-8337-2B52EDB4BE82} + {96B13FBF-EF87-4544-9A02-AC59856366F3} = {0445D673-FB74-412E-9227-6C5BDB60DA82} + {9D42C248-4553-4E1C-B4AE-E9F2D7E37587} = {BECF75F3-FA74-4A0D-8E0C-7C8C1A7C1B26} + {CF193A31-A157-4B93-9EE6-DDBC7C7E712E} = {0445D673-FB74-412E-9227-6C5BDB60DA82} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {56E05DCF-C9EE-4A59-95A7-25C4887286B4} + EndGlobalSection +EndGlobal