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