Add project files.

This commit is contained in:
Sergio Matias Urquin 2025-04-29 18:44:41 -06:00
parent c4ec91852f
commit b2635193dc
133 changed files with 4100 additions and 0 deletions

30
.dockerignore Normal file
View File

@ -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/**

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="UsesCases\BlobStorage\Storage.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageReference Include="Core.Blueprint.KeyVault" Version="0.3.0-alpha0037" />
<PackageReference Include="MongoDB.Bson" Version="3.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core.Blueprint.Service.External\Core.Blueprint.Service.External.csproj" />
</ItemGroup>
</Project>

View File

@ -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<BlobFileAdapter> output)
{
ViewModel = new OkObjectResult(output);
}
public void Success(BlobFileAdapter output)
{
ViewModel = new OkObjectResult(output);
}
public void Success(BlobDownloadUriAdapter output)
{
ViewModel = new OkObjectResult(output);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<List<BlobFileAdapter>>,
ICommandSuccessPort<BlobFileAdapter>,
ICommandSuccessPort<BlobDownloadUriAdapter>,
INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort,
INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort,
IBadRequestPort
{
}
}

View File

@ -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<CreateBlobRequest>,
IComponentHandler<GetBlobListRequest>,
IComponentHandler<UpdateBlobRequest>,
IComponentHandler<DeleteBlobRequest>
{
private readonly IKeyVaultPort _port;
private readonly IValidator<CreateBlobRequest> _createKeyVaultValidator;
private readonly IValidator<GetBlobListRequest> _getKeyVaultValidator;
private readonly IValidator<UpdateBlobRequest> _updateKeyVaultValidator;
private readonly IValidator<DeleteBlobRequest> _deleteKeyVaultValidator;
private readonly IBlueprintServiceClient _keyVaultDALService;
public Storage(
IKeyVaultPort port,
IValidator<CreateBlobRequest> createKeyVaultValidator,
IValidator<GetBlobListRequest> getKeyVaultValidator,
IValidator<UpdateBlobRequest> updateKeyVaultValidator,
IValidator<DeleteBlobRequest> 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);
}
}
}
}

View File

@ -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<UploadBlobRequest>,
IComponentHandler<GetBlobListRequest>,
IComponentHandler<DownloadBlobRequest>,
IComponentHandler<DeleteBlobRequest>
{
private readonly IStoragePort _port;
private readonly IValidator<UploadBlobRequest> _uploadBlobValidator;
private readonly IValidator<DownloadBlobRequest> _downloadBlobValidator;
private readonly IValidator<DeleteBlobRequest> _deleteBlobValidator;
private readonly IBlueprintServiceClient _storageDALService;
public StorageHandler(
IStoragePort port,
IValidator<UploadBlobRequest> uploadBlobValidator,
IValidator<DownloadBlobRequest> downloadBlobValidator,
IValidator<DeleteBlobRequest> 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);
}
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.KeyVault.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.KeyVault.Validator
{
public class DeleteBlobValidator : AbstractValidator<DeleteBlobRequest>
{
public DeleteBlobValidator()
{
RuleFor(i => i.BlobName).NotEmpty().NotNull().OverridePropertyName(x => x.BlobName).WithName("Blob Name").WithMessage("Blob Name is Obligatory.");
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.KeyVault.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.KeyVault.Validator
{
public class DownloadBlobValidator : AbstractValidator<DownloadBlobRequest>
{
public DownloadBlobValidator()
{
RuleFor(i => i.BlobName).NotEmpty().NotNull().OverridePropertyName(x => x.BlobName).WithName("Blob Name").WithMessage("Blob Name is Obligatory.");
}
}
}

View File

@ -0,0 +1,14 @@
using Core.Blueprint.Application.UsesCases.KeyVault.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.KeyVault.Validator
{
public class UploadBlobValidator : AbstractValidator<UploadBlobRequest>
{
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.");
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<CreateSecretRequest>,
IComponentHandler<GetSecretRequest>,
IComponentHandler<UpdateSecretRequest>,
IComponentHandler<DeleteSecretRequest>
{
private readonly IKeyVaultPort _port;
private readonly IValidator<CreateSecretRequest> _createSecretValidator;
private readonly IValidator<GetSecretRequest> _getSecretValidator;
private readonly IValidator<UpdateSecretRequest> _updateSecretValidator;
private readonly IValidator<DeleteSecretRequest> _deleteSecretValidator;
private readonly IBlueprintServiceClient _keyVaultDALService;
public KeyVaultHandler(
IKeyVaultPort port,
IValidator<CreateSecretRequest> createSecretValidator,
IValidator<GetSecretRequest> getSecretValidator,
IValidator<UpdateSecretRequest> updateSecretValidator,
IValidator<DeleteSecretRequest> 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);
}
}
}
}

View File

@ -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<KeyVaultResponse>,
ICommandSuccessPort<KeyVaultAdapter>,
INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort,
INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort,
IBadRequestPort
{
}
}

View File

@ -0,0 +1,14 @@
using Core.Blueprint.Application.UsesCases.KeyVault.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.KeyVault.Validator
{
public class CreateSecretValidator : AbstractValidator<CreateSecretRequest>
{
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.");
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.KeyVault.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.KeyVault.Validator
{
public class DeleteSecretValidator : AbstractValidator<DeleteSecretRequest>
{
public DeleteSecretValidator()
{
RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Secret Name").WithMessage("Secret Name is Obligatory.");
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.KeyVault.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.KeyVault.Validator
{
public class GetSecretValidator : AbstractValidator<GetSecretRequest>
{
public GetSecretValidator()
{
RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Secret Name").WithMessage("Secret Name is Obligatory.");
}
}
}

View File

@ -0,0 +1,14 @@
using Core.Blueprint.Application.UsesCases.KeyVault.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.KeyVault.Validator
{
public class UpdateSecretValidator : AbstractValidator<UpdateSecretRequest>
{
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.");
}
}
}

View File

@ -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<BlueprintAdapter> output)
{
ViewModel = new OkObjectResult(output);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<CreateBlueprintRequest>,
IComponentHandler<GetBlueprintRequest>,
IComponentHandler<GetAllBlueprintsRequest>,
IComponentHandler<UpdateBlueprintRequest>,
IComponentHandler<DeleteBlueprintRequest>
{
private readonly IMongoPort _port;
private readonly IValidator<CreateBlueprintRequest> _createBlueprintValidator;
private readonly IValidator<GetBlueprintRequest> _getBlueprintValidator;
private readonly IValidator<UpdateBlueprintRequest> _updateBlueprintValidator;
private readonly IValidator<DeleteBlueprintRequest> _deleteBlueprintValidator;
private readonly IBlueprintServiceClient _mongoDALService;
public MongoHandler(
IMongoPort port,
IValidator<CreateBlueprintRequest> createBlueprintValidator,
IValidator<GetBlueprintRequest> getBlueprintValidator,
IValidator<UpdateBlueprintRequest> updateBlueprintValidator,
IValidator<DeleteBlueprintRequest> 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);
}
}
}
}

View File

@ -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<BlueprintAdapter>,
ICommandSuccessPort<List<BlueprintAdapter>>,
INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort,
INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort,
IBadRequestPort
{
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.Mongo.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.Blueprints.Validator
{
public class CreateBlueprintValidator : AbstractValidator<CreateBlueprintRequest>
{
public CreateBlueprintValidator()
{
RuleFor(i => i.Name).NotEmpty().NotNull().OverridePropertyName(x => x.Name).WithName("Blueprint Name").WithMessage("Blueprint Name is Obligatory.");
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.Mongo.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.Blueprints.Validator
{
public class DeleteBlueprintValidator : AbstractValidator<DeleteBlueprintRequest>
{
public DeleteBlueprintValidator()
{
RuleFor(i => i._Id).NotEmpty().NotNull().OverridePropertyName(x => x._Id).WithName("Blueprint Mongo Identifier").WithMessage("Blueprint Mongo Identifier is Obligatory.");
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.Mongo.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.Blueprints.Validator
{
public class GetBlueprintValidator : AbstractValidator<GetBlueprintRequest>
{
public GetBlueprintValidator()
{
RuleFor(i => i._Id).NotEmpty().NotNull().OverridePropertyName(x => x._Id).WithName("Blueprint Mongo Identifier").WithMessage("Blueprint Mongo Identifier is Obligatory.");
}
}
}

View File

@ -0,0 +1,17 @@
using Core.Blueprint.Application.UsesCases.Mongo.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.Blueprints.Validator
{
public class UpdateBlueprintValidator : AbstractValidator<UpdateBlueprintRequest>
{
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.");
}
}
}

View File

@ -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<UserProjectAdapter> output)
{
ViewModel = new OkObjectResult(output);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<UserProjectAdapter>,
ICommandSuccessPort<List<UserProjectAdapter>>,
INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort,
INotFoundPort, IForbiddenPort, IUnauthorizedPort, IInternalServerErrorPort,
IBadRequestPort
{
}
}

View File

@ -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<CreateUserProjectRequest>,
IComponentHandler<GetUserProjectRequest>,
IComponentHandler<GetAllUserProjectsRequest>,
IComponentHandler<UpdateUserProjectRequest>,
IComponentHandler<DeleteUserProjectRequest>
{
private readonly ISQLPort _port;
private readonly IValidator<CreateUserProjectRequest> _createUserProjectValidator;
private readonly IValidator<GetUserProjectRequest> _getUserProjectValidator;
private readonly IValidator<UpdateUserProjectRequest> _updateUserProjectValidator;
private readonly IValidator<DeleteUserProjectRequest> _deleteUserProjectValidator;
private readonly IBlueprintServiceClient _SQLDALService;
public SQLHandler(
ISQLPort port,
IValidator<CreateUserProjectRequest> createUserProjectValidator,
IValidator<GetUserProjectRequest> getUserProjectValidator,
IValidator<UpdateUserProjectRequest> updateUserProjectValidator,
IValidator<DeleteUserProjectRequest> 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);
}
}
}
}

View File

@ -0,0 +1,15 @@
using Core.Blueprint.Application.UsesCases.SQL.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.SQL.Validator
{
public class CreateUserProjectValidator : AbstractValidator<CreateUserProjectRequest>
{
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.");
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.SQL.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.SQL.Validator
{
public class DeleteUserProjectValidator : AbstractValidator<DeleteUserProjectRequest>
{
public DeleteUserProjectValidator()
{
RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("User Project Identifier").WithMessage("User Project Identifier is Obligatory.");
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Application.UsesCases.SQL.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.SQL.Validator
{
public class GetUserProjectValidator : AbstractValidator<GetUserProjectRequest>
{
public GetUserProjectValidator()
{
RuleFor(i => i.Id).NotEmpty().NotNull().OverridePropertyName(x => x.Id).WithName("User Project Identifier").WithMessage("User Project Identifier is Obligatory.");
}
}
}

View File

@ -0,0 +1,19 @@
using Core.Blueprint.Application.UsesCases.SQL.Input;
using FluentValidation;
namespace Core.Cerberos.Application.UseCases.SQL.Validator
{
public class UpdateUserProjectValidator : AbstractValidator<UpdateUserProjectRequest>
{
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.");
}
}
}

View File

@ -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
{
/// <summary>
/// Handles all services and business rules related to <see cref="MStorageController"/>.
/// </summary>
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
public class BlobStorageController : ControllerBase
{
private readonly IComponentHandler<UploadBlobRequest> uploadBlobHandler;
private readonly IComponentHandler<GetBlobListRequest> getBlobListHandler;
private readonly IComponentHandler<DownloadBlobRequest> downloadBlobHandler;
private readonly IComponentHandler<DeleteBlobRequest> deleteBlobHandler;
private readonly IStoragePort port;
/// <summary>
/// Handles all services and business rules related to <see cref="MStorageController"/>.
/// </summary>
public BlobStorageController(
IComponentHandler<UploadBlobRequest> uploadBlobHandler,
IComponentHandler<GetBlobListRequest> getBlobListHandler,
IComponentHandler<DownloadBlobRequest> downloadBlobHandler,
IComponentHandler<DeleteBlobRequest> deleteBlobHandler,
IStoragePort port
)
{
this.uploadBlobHandler = uploadBlobHandler;
this.getBlobListHandler = getBlobListHandler;
this.downloadBlobHandler = downloadBlobHandler;
this.deleteBlobHandler = deleteBlobHandler;
this.port = port;
}
/// <summary>
/// Uploads a new blob.
/// </summary>
[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<IActionResult> UploadBlobAsync([FromBody] UploadBlobRequest newBlob, CancellationToken cancellationToken = default)
{
await uploadBlobHandler.ExecuteAsync(newBlob, cancellationToken).ConfigureAwait(false);
return port.ViewModel;
}
/// <summary>
/// Gets all blobs into the container.
/// </summary>
[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<IActionResult> GetBlobList([FromQuery] string? prefix, CancellationToken cancellationToken)
{
await getBlobListHandler.ExecuteAsync(new GetBlobListRequest { Prefix = prefix }, cancellationToken).ConfigureAwait(false);
return port.ViewModel;
}
/// <summary>
/// Downloads a blob by name.
/// </summary>
[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<IActionResult> 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;
}
/// <summary>
/// Deletes a blob by name.
/// </summary>
[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<IActionResult> 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;
}
}
}

View File

@ -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
{
/// <summary>
/// Handles all services and business rules related to <see cref="MKeyVaultController"/>.
/// </summary>
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
public class KeyVaultController : ControllerBase
{
private readonly IComponentHandler<CreateSecretRequest> createSecretHandler;
private readonly IComponentHandler<GetSecretRequest> getSecretHandler;
private readonly IComponentHandler<UpdateSecretRequest> updateSecretHandler;
private readonly IComponentHandler<DeleteSecretRequest> deleteSecretHandler;
private readonly IKeyVaultPort port;
/// <summary>
/// Handles all services and business rules related to <see cref="MKeyVaultController"/>.
/// </summary>
public KeyVaultController(
IComponentHandler<GetSecretRequest> getSecretHandler,
IComponentHandler<CreateSecretRequest> createSecretHandler,
IComponentHandler<UpdateSecretRequest> updateSecretHandler,
IComponentHandler<DeleteSecretRequest> deleteSecretHandler,
IKeyVaultPort port
)
{
this.createSecretHandler = createSecretHandler;
this.updateSecretHandler = updateSecretHandler;
this.deleteSecretHandler = deleteSecretHandler;
this.getSecretHandler = getSecretHandler;
this.port = port;
}
/// <summary>
/// Creates a new secret.
/// </summary>
[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<IActionResult> CreateSecretAsync([FromBody] CreateSecretRequest newSecret, CancellationToken cancellationToken = default)
{
await createSecretHandler.ExecuteAsync(newSecret, cancellationToken).ConfigureAwait(false);
return port.ViewModel;
}
/// <summary>
/// Gets the secret by name.
/// </summary>
[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<IActionResult> 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;
}
/// <summary>
/// Updates a full secret by identifier.
/// </summary>
[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<IActionResult> 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;
}
/// <summary>
/// Deletes a secret by name.
/// </summary>
[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<IActionResult> 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;
}
}
}

View File

@ -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
{
/// <summary>
/// Handles all services and business rules related to <see cref="MongoBlueprintController"/>.
/// </summary>
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
public class MongoBlueprintController : ControllerBase
{
private readonly IComponentHandler<CreateBlueprintRequest> createBlueprintHandler;
private readonly IComponentHandler<GetAllBlueprintsRequest> getAllBlueprintsHandler;
private readonly IComponentHandler<GetBlueprintRequest> getBlueprintHandler;
private readonly IComponentHandler<UpdateBlueprintRequest> updateBlueprintHandler;
private readonly IComponentHandler<DeleteBlueprintRequest> deleteBlueprintHandler;
private readonly IMongoPort port;
/// <summary>
/// Handles all services and business rules related to <see cref="MongoBlueprintController"/>.
/// </summary>
public MongoBlueprintController(
IComponentHandler<GetBlueprintRequest> getBlueprintHandler,
IComponentHandler<GetAllBlueprintsRequest> getAllBlueprintsHandler,
IComponentHandler<CreateBlueprintRequest> createBlueprintHandler,
IComponentHandler<UpdateBlueprintRequest> updateBlueprintHandler,
IComponentHandler<DeleteBlueprintRequest> deleteBlueprintHandler,
IMongoPort port
)
{
this.createBlueprintHandler = createBlueprintHandler;
this.updateBlueprintHandler = updateBlueprintHandler;
this.deleteBlueprintHandler = deleteBlueprintHandler;
this.getAllBlueprintsHandler = getAllBlueprintsHandler;
this.getBlueprintHandler = getBlueprintHandler;
this.port = port;
}
/// <summary>
/// Creates a new blueprint.
/// </summary>
[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<IActionResult> CreateBlueprintAsync([FromBody] CreateBlueprintRequest newBlueprint, CancellationToken cancellationToken = default)
{
await createBlueprintHandler.ExecuteAsync(newBlueprint, cancellationToken).ConfigureAwait(false);
return port.ViewModel;
}
/// <summary>
/// Gets all blueprints.
/// </summary>
[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<IActionResult> GetAllBlueprintsAsync(CancellationToken cancellationToken)
{
await getAllBlueprintsHandler.ExecuteAsync(new GetAllBlueprintsRequest { }, cancellationToken).ConfigureAwait(false);
return port.ViewModel;
}
/// <summary>
/// Gets the blueprint by identifier.
/// </summary>
[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<IActionResult> 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;
}
/// <summary>
/// Updates a full blueprint by identifier.
/// </summary>
[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<IActionResult> 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;
}
/// <summary>
/// Deletes a blueprint.
/// </summary>
[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<IActionResult> 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;
}
}
}

View File

@ -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
{
/// <summary>
/// Handles all services and business rules related to <see cref="SQLUserProjectController"/>.
/// </summary>
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
public class SQLUserProjectController : ControllerBase
{
private readonly IComponentHandler<CreateUserProjectRequest> createUserProjectHandler;
private readonly IComponentHandler<GetAllUserProjectsRequest> getAllUserProjectsHandler;
private readonly IComponentHandler<GetUserProjectRequest> getUserProjectHandler;
private readonly IComponentHandler<UpdateUserProjectRequest> updateUserProjectHandler;
private readonly IComponentHandler<DeleteUserProjectRequest> deleteUserProjectStatusHandler;
private readonly ISQLPort port;
/// <summary>
/// Handles all services and business rules related to <see cref="SQLUserProjectController"/>.
/// </summary>
public SQLUserProjectController(
IComponentHandler<GetUserProjectRequest> getUserProjectHandler,
IComponentHandler<GetAllUserProjectsRequest> getAllUserProjectsHandler,
IComponentHandler<CreateUserProjectRequest> createUserProjectHandler,
IComponentHandler<UpdateUserProjectRequest> updateUserProjectHandler,
IComponentHandler<DeleteUserProjectRequest> deleteUserProjectStatusHandler,
ISQLPort port
)
{
this.createUserProjectHandler = createUserProjectHandler;
this.updateUserProjectHandler = updateUserProjectHandler;
this.deleteUserProjectStatusHandler = deleteUserProjectStatusHandler;
this.getAllUserProjectsHandler = getAllUserProjectsHandler;
this.getUserProjectHandler = getUserProjectHandler;
this.port = port;
}
/// <summary>
/// Creates a new UserProject.
/// </summary>
[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<IActionResult> CreateUserProjectAsync([FromBody] CreateUserProjectRequest newUserProject, CancellationToken cancellationToken = default)
{
await createUserProjectHandler.ExecuteAsync(newUserProject, cancellationToken).ConfigureAwait(false);
return port.ViewModel;
}
/// <summary>
/// Gets all UserProjects.
/// </summary>
[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<IActionResult> GetAllUserProjectsAsync(CancellationToken cancellationToken)
{
await getAllUserProjectsHandler.ExecuteAsync(new GetAllUserProjectsRequest { }, cancellationToken).ConfigureAwait(false);
return port.ViewModel;
}
/// <summary>
/// Gets the UserProject by identifier.
/// </summary>
[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<IActionResult> 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;
}
/// <summary>
/// Updates a full UserProject by identifier.
/// </summary>
[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<IActionResult> 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;
}
/// <summary>
/// Deletes a UserProject.
/// </summary>
[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<IActionResult> 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;
}
}
}

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<UserSecretsId>a776c24d-b2ab-4520-a66b-d1802fb016fb</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageReference Include="Core.Blueprint.Logging" Version="0.3.0-alpha0034" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.1.0-preview" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core.Blueprint.Application\Core.Blueprint.Application.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
@Core.Blueprint.Service.API_HostAddress = http://localhost:5047
GET {{Core.Blueprint.Service.API_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -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"]

View File

@ -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<IMongoPort, MongoPort>();
services.AddValidatorsFromAssemblyContaining<CreateBlueprintValidator>();
services.AddScoped<IValidator<CreateBlueprintRequest>, CreateBlueprintValidator>();
services.AddScoped<IComponentHandler<CreateBlueprintRequest>, MongoHandler>();
services.AddScoped<IComponentHandler<GetAllBlueprintsRequest>, MongoHandler>();
services.AddValidatorsFromAssemblyContaining<GetBlueprintValidator>();
services.AddScoped<IValidator<GetBlueprintRequest>, GetBlueprintValidator>();
services.AddScoped<IComponentHandler<GetBlueprintRequest>, MongoHandler>();
services.AddValidatorsFromAssemblyContaining<UpdateBlueprintValidator>();
services.AddScoped<IValidator<UpdateBlueprintRequest>, UpdateBlueprintValidator>();
services.AddScoped<IComponentHandler<UpdateBlueprintRequest>, MongoHandler>();
services.AddValidatorsFromAssemblyContaining<DeleteBlueprintValidator>();
services.AddScoped<IValidator<DeleteBlueprintRequest>, DeleteBlueprintValidator>();
services.AddScoped<IComponentHandler<DeleteBlueprintRequest>, MongoHandler>();
#endregion
#region SQL Services
services.AddScoped<ISQLPort, SQLPort>();
services.AddValidatorsFromAssemblyContaining<CreateUserProjectValidator>();
services.AddScoped<IValidator<CreateUserProjectRequest>, CreateUserProjectValidator>();
services.AddScoped<IComponentHandler<CreateUserProjectRequest>, SQLHandler>();
services.AddScoped<IComponentHandler<GetAllUserProjectsRequest>, SQLHandler>();
services.AddValidatorsFromAssemblyContaining<GetUserProjectValidator>();
services.AddScoped<IValidator<GetUserProjectRequest>, GetUserProjectValidator>();
services.AddScoped<IComponentHandler<GetUserProjectRequest>, SQLHandler>();
services.AddValidatorsFromAssemblyContaining<UpdateUserProjectValidator>();
services.AddScoped<IValidator<UpdateUserProjectRequest>, UpdateUserProjectValidator>();
services.AddScoped<IComponentHandler<UpdateUserProjectRequest>, SQLHandler>();
services.AddValidatorsFromAssemblyContaining<DeleteUserProjectValidator>();
services.AddScoped<IValidator<DeleteUserProjectRequest>, DeleteUserProjectValidator>();
services.AddScoped<IComponentHandler<DeleteUserProjectRequest>, SQLHandler>();
#endregion
#region KeyVault Services
services.AddScoped<IKeyVaultPort, KeyVaultPort>();
services.AddValidatorsFromAssemblyContaining<CreateSecretValidator>();
services.AddScoped<IValidator<CreateSecretRequest>, CreateSecretValidator>();
services.AddScoped<IComponentHandler<CreateSecretRequest>, KeyVaultHandler>();
services.AddValidatorsFromAssemblyContaining<GetSecretValidator>();
services.AddScoped<IValidator<GetSecretRequest>, GetSecretValidator>();
services.AddScoped<IComponentHandler<GetSecretRequest>, KeyVaultHandler>();
services.AddValidatorsFromAssemblyContaining<UpdateSecretValidator>();
services.AddScoped<IValidator<UpdateSecretRequest>, UpdateSecretValidator>();
services.AddScoped<IComponentHandler<UpdateSecretRequest>, KeyVaultHandler>();
services.AddValidatorsFromAssemblyContaining<DeleteSecretValidator>();
services.AddScoped<IValidator<DeleteSecretRequest>, DeleteSecretValidator>();
services.AddScoped<IComponentHandler<DeleteSecretRequest>, KeyVaultHandler>();
#endregion
#region Storage Services
services.AddScoped<IStoragePort, StoragePort>();
services.AddValidatorsFromAssemblyContaining<UploadBlobValidator>();
services.AddScoped<IValidator<UploadBlobRequest>, UploadBlobValidator>();
services.AddScoped<IComponentHandler<UploadBlobRequest>, StorageHandler>();
services.AddScoped<IComponentHandler<GetBlobListRequest>, StorageHandler>();
services.AddValidatorsFromAssemblyContaining<DownloadBlobValidator>();
services.AddScoped<IValidator<DownloadBlobRequest>, DownloadBlobValidator>();
services.AddScoped<IComponentHandler<DownloadBlobRequest>, StorageHandler>();
services.AddValidatorsFromAssemblyContaining<DeleteBlobValidator>();
services.AddScoped<IValidator<DeleteBlobRequest>, DeleteBlobValidator>();
services.AddScoped<IComponentHandler<DeleteBlobRequest>, StorageHandler>();
#endregion
return services;
}
}
}

View File

@ -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<IConfigureOptions<SwaggerGenOptions>, 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<SwaggerGenOptions>
{
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<DateOnly>(() => new()
{
Format = "date",
Example = new OpenApiString(DateOnly.MinValue.ToString())
});
options.CustomSchemaIds(type => type.ToString().Replace("+", "."));
}
}
}

View File

@ -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<Microsoft.AspNetCore.Http.Json.JsonOptions>(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();

View File

@ -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
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"LocalGateways": {
"BlueprintDAL": "https://localhost:7075/api"
}
}

View File

@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Endpoints": {
"AppConfigurationURI": "https://sandbox-hci-usc-appcg.azconfig.io"
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -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; }
}
}

View File

@ -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; } = [];
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}

View File

@ -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<IHttpContextAccessor, HttpContextAccessor>();
// Register ITokenProvider
services.AddSingleton<ITokenProvider, HttpContextTokenProvider>();
// Register the custom AuthenticatedHttpClientHandler
services.AddTransient(provider =>
{
var tokenProvider = provider.GetRequiredService<ITokenProvider>();
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<IBlueprintServiceClient>(provider =>
{
var handler = provider.GetRequiredService<AuthenticatedHttpClientHandler>();
var httpClient = new HttpClient(handler)
{
BaseAddress = secretServiceApiUrl,
Timeout = TimeSpan.FromMinutes(1)
};
return RestService.For<IBlueprintServiceClient>(httpClient);
});
services.AddScoped<IAuthenticationService, AuthenticationService>();
return services;
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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
}
}

View File

@ -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; }
}
}

View File

@ -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<BlueprintAdapter> CreateBlueprintAsync([FromBody] BlueprintRequest newBlueprint, CancellationToken cancellationToken = default);
[Get("/v1/MongoBlueprint/GetAll")]
Task<IEnumerable<BlueprintAdapter>> GetAllBlueprintsAsync(CancellationToken cancellationToken = default);
[Get("/v1/MongoBlueprint/{_id}/GetBy_Id")]
Task<BlueprintAdapter> GetBlueprintByIdAsync([FromRoute] string _id, CancellationToken cancellationToken = default);
[Put("/v1/MongoBlueprint/{_id}/Update")]
Task<BlueprintAdapter> UpdateBlueprintAsync([FromRoute] string _id, [FromBody] BlueprintAdapter entity, CancellationToken cancellationToken = default);
[Delete("/v1/MongoBlueprint/{_id}/Delete")]
Task<BlueprintAdapter> DeleteBlueprintAsync([FromRoute] string _id, CancellationToken cancellationToken = default);
[Post("/v1/UserProject/Create")]
Task<UserProjectAdapter> CreateUserProjectAsync([FromBody] UserProjectRequest newUserProject, CancellationToken cancellationToken = default);
[Get("/v1/UserProject/GetAll")]
Task<IEnumerable<UserProjectAdapter>> GetAllUserProjectsAsync(CancellationToken cancellationToken = default);
[Get("/v1/UserProject/{id}/GetById")]
Task<UserProjectAdapter> GetUserProjectByIdAsync([FromRoute] int id, CancellationToken cancellationToken = default);
[Put("/v1/UserProject/{id}/Update")]
Task<UserProjectAdapter> UpdateUserProjectAsync([FromRoute] int id, [FromBody] UserProjectAdapter entity, CancellationToken cancellationToken = default);
[Delete("/v1/UserProject/{id}/Delete")]
Task<UserProjectAdapter> DeleteUserProjectAsync([FromRoute] int id, CancellationToken cancellationToken = default);
[Post("/v1/KeyVault/CreateSecret")]
Task<KeyVaultResponse> CreateSecretAsync([FromBody] KeyVaultRequest newKeyVault, CancellationToken cancellationToken = default);
[Get("/v1/KeyVault/{secretName}/GetSecret")]
Task<KeyVaultAdapter> GetSecretByNameAsync([FromRoute] string secretName, CancellationToken cancellationToken = default);
[Put("/v1/KeyVault/UpdateSecret")]
Task<KeyVaultAdapter> UpdateSecretAsync([FromBody] KeyVaultRequest entity, CancellationToken cancellationToken = default);
[Delete("/v1/KeyVault/{secretName}/DeleteSecret")]
Task<KeyVaultAdapter> DeleteSecretAsync([FromRoute] string secretName, CancellationToken cancellationToken = default);
[Post("/v1/BlobStorage/UploadBlob")]
Task<BlobFileAdapter> UploadBlobAsync([FromQuery] BlobAddDto request, CancellationToken cancellationToken = default);
[Get("/v1/BlobStorage/GetBlobList")]
Task<List<BlobFileAdapter>> GetBlobListAsync([FromQuery] string? prefix, CancellationToken cancellationToken = default);
[Get("/v1/BlobStorage/DownloadBlob")]
Task<BlobDownloadUriAdapter> DownloadBlobAsync([FromQuery] string blobName, CancellationToken cancellationToken = default);
[Delete("/v1/BlobStorage/DeleteBlob")]
Task<BlobFileAdapter> DeleteBlobAsync([FromQuery] string blobName, CancellationToken cancellationToken = default);
}
}

View File

@ -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; }
}
}

View File

@ -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!;
}
}

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageReference Include="Core.Blueprint.KeyVault" Version="0.3.0-alpha0037" />
<PackageReference Include="Core.Blueprint.Storage" Version="0.3.0-alpha0049" />
<PackageReference Include="Lib.Architecture.BuildingBlocks" Version="0.9.0-alpha0008" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
<PackageReference Include="Refit" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="LSA.Core.Adapters">
<HintPath>..\..\Dependencies\LSA.Core.Adapters.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,32 @@
// ***********************************************************************
// <copyright file="AuthenticatedHttpClientHandler.cs">
// Heath
// </copyright>
// ***********************************************************************
namespace Core.Blueprint.Service.External.Helpers.Token
{
/// <summary>
/// Class to inject the token in all requests.
/// </summary>
public class AuthenticatedHttpClientHandler : DelegatingHandler
{
private readonly ITokenProvider _tokenProvider;
public AuthenticatedHttpClientHandler(ITokenProvider tokenProvider)
{
_tokenProvider = tokenProvider;
}
protected override async Task<HttpResponseMessage> 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);
}
}
}

View File

@ -0,0 +1,31 @@
// ***********************************************************************
// <copyright file="HttpContextTokenProvider.cs">
// Heath
// </copyright>
// ***********************************************************************
using Microsoft.AspNetCore.Http;
namespace Core.Blueprint.Service.External.Helpers.Token
{
/// <summary>
/// Class to return the access token to controllers.
/// </summary>
public class HttpContextTokenProvider : ITokenProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextTokenProvider(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
/// <summary>
/// Get token from headers.
/// </summary>
public string GetToken()
{
return _httpContextAccessor.HttpContext?.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
}
}
}

View File

@ -0,0 +1,19 @@
// ***********************************************************************
// <copyright file="ITokenProvider.cs">
// Heath
// </copyright>
// ***********************************************************************
namespace Core.Blueprint.Service.External.Helpers.Token
{
/// <summary>
/// Interface for token provider.
/// </summary>
public interface ITokenProvider
{
/// <summary>
/// Get token from headers.
/// </summary>
string GetToken();
}
}

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@ -0,0 +1 @@
global using Xunit;

View File

@ -0,0 +1,11 @@
namespace Core.Blueprint.Service.Testing
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
}

View File

@ -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<IEnumerable<MongoBlueprintCollection>> GetBlueprintsAsync();
Task<MongoBlueprintCollection> GetBlueprintAsync(string id);
Task<MongoBlueprintCollection> 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<IEnumerable<MongoBlueprintCollection>> GetBlueprintsAsync()
{
try
{
return await _blueprintApi.GetBlueprintsAsync();
}
catch (ApiException ex)
{
Console.WriteLine($"Error fetching blueprints: {ex.Message}");
throw;
}
}
public async Task<MongoBlueprintCollection> 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<MongoBlueprintCollection> 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;
}
}
}
}

View File

@ -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<IGetSampleItemsPort, GetSampleItemsPort>()
.AddScoped<IGetOneSampleItemPort, GetOneSampleItemPort>()
.AddScoped<ICreateSampleItemPort, CreateSampleItemPort>()
.AddScoped<IUpdateSampleItemPort, UpdateSampleItemPort>()
.AddScoped<IDeleteSampleItemPort, DeleteSampleItemPort>()
.AddScoped<IGetSampleImagePort, GetSampleImagePort>()
.AddScoped<IGetUploadUrlPort, GetUploadUrlPort>()
.AddScoped<IValidator<GetSampleItemsRequest>, GetSampleItemValidator>()
.AddScoped<IValidator<GetOneSampleItemRequest>, GetOneSampleItemValidator>()
.AddScoped<IValidator<CreateSampleItemRequest>, CreateSampleItemValidator>()
.AddScoped<IValidator<UpdateSampleItemRequest>, UpdateSampleItemValidator>()
.AddScoped<IValidator<DeleteSampleItemRequest>, DeleteSampleItemValidator>()
.AddScoped<IValidator<GetSampleImageRequest>, GetSampleImageValidator>()
.AddScoped<IValidator<GetUploadUrlRequest>, GetUploadUrlValidator>()
.AddScoped<IComponentHandler<GetSampleItemsRequest>, GetSampleItemsHandler>()
.AddScoped<IComponentHandler<GetOneSampleItemRequest>, GetOneSampleItemHandler>()
.AddScoped<IComponentHandler<CreateSampleItemRequest>, CreateSampleItemHandler>()
.AddScoped<IComponentHandler<UpdateSampleItemRequest>, UpdateSampleItemHandler>()
.AddScoped<IComponentHandler<DeleteSampleItemRequest>, DeleteSampleItemHandler>()
.AddScoped<IComponentHandler<GetSampleImageRequest>, GetSampleImageHandler>()
.AddScoped<IComponentHandler<GetUploadUrlRequest>, GetUploadUrlHandler>();
return services;
}
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Lib.Architecture.BuildingBlocks" Version="0.9.0-alpha0001" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core.Blueprint.Service.Domain\Core.Blueprint.Service.Domain.csproj" />
<ProjectReference Include="..\Core.Blueprint.Service.External\Core.Blueprint.Service.External.csproj" />
</ItemGroup>
</Project>

View File

@ -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);
}
}
}

View File

@ -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<CreateSampleItemRequest> validator, ISampleItemClientService clientService) : IComponentHandler<CreateSampleItemRequest>
{
private readonly ICreateSampleItemPort _port = port;
private readonly IValidator<CreateSampleItemRequest> _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);
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<SqlSampleItemEntity>, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort
{
}
}

View File

@ -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<CreateSampleItemRequest>
{
public CreateSampleImageValidator()
{
}
}
}

View File

@ -0,0 +1,15 @@
using Core.Blueprint.Service.Domain.Entities;
using Core.Blueprint.Service.UseCases.CreateSampleItem.Ports;
using Lib.Architecture.BuildingBlocks;
using Microsoft.AspNetCore.Mvc;
namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Adapter
{
public class CreateSampleItemPort : BasePresenter, ICreateSampleItemPort
{
public void Success(SqlSampleItemEntity output)
{
ViewModel = new OkObjectResult(output);
}
}
}

View File

@ -0,0 +1,44 @@
using Core.Blueprint.Service.Domain.Entities;
using Core.Blueprint.Service.External.Clients.SampleItemClient;
using Core.Blueprint.Service.UseCases.CreateSampleItem.Input;
using Core.Blueprint.Service.UseCases.CreateSampleItem.Ports;
using FluentValidation;
using Lib.Architecture.BuildingBlocks;
namespace Core.Blueprint.Service.UseCases.CreateSampleItem
{
public class CreateSampleItemHandler(ICreateSampleItemPort port, IValidator<CreateSampleItemRequest> validator, ISampleItemClientService clientService) : IComponentHandler<CreateSampleItemRequest>
{
private readonly ICreateSampleItemPort _port = port;
private readonly IValidator<CreateSampleItemRequest> _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);
}
}
}
}

View File

@ -0,0 +1,14 @@
using Lib.Architecture.BuildingBlocks;
namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Input
{
public class CreateSampleItemRequest : Notificator, ICommand
{
public string TestName { get; set; } = string.Empty;
public int NumValue { get; set; } = 0;
public bool Validate()
{
return true;
}
}
}

View File

@ -0,0 +1,9 @@
using Core.Blueprint.Service.Domain.Entities;
using Lib.Architecture.BuildingBlocks;
namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Ports
{
public interface ICreateSampleItemPort : IBasePort, ICommandSuccessPort<SqlSampleItemEntity>, INoContentPort, IBusinessErrorPort, ITimeoutPort, IValidationErrorPort
{
}
}

View File

@ -0,0 +1,16 @@
using Core.Blueprint.Service.UseCases.CreateSampleItem.Input;
using FluentValidation;
using System.Diagnostics.CodeAnalysis;
namespace Core.Blueprint.Service.UseCases.CreateSampleItem.Validator
{
[ExcludeFromCodeCoverage]
public class CreateSampleItemValidator : AbstractValidator<CreateSampleItemRequest>
{
public CreateSampleItemValidator()
{
RuleFor(i => i.TestName).NotNull().NotEmpty().WithMessage("Is required.");
RuleFor(i => i.NumValue).GreaterThanOrEqualTo(1).LessThanOrEqualTo(100).WithMessage("Should be between 1-100.");
}
}
}

View File

@ -0,0 +1,15 @@
using Core.Blueprint.Service.Domain.Entities;
using Core.Blueprint.Service.UseCases.DeleteSampleItem.Ports;
using Lib.Architecture.BuildingBlocks;
using Microsoft.AspNetCore.Mvc;
namespace Core.Blueprint.Service.UseCases.DeleteSampleItem.Adapter
{
public class DeleteSampleItemPort : BasePresenter, IDeleteSampleItemPort
{
public void Success(SqlSampleItemEntity output)
{
ViewModel = new OkObjectResult(output);
}
}
}

View File

@ -0,0 +1,42 @@
using Core.Blueprint.Service.External.Clients.SampleItemClient;
using Core.Blueprint.Service.UseCases.DeleteSampleItem.Input;
using Core.Blueprint.Service.UseCases.DeleteSampleItem.Ports;
using FluentValidation;
using Lib.Architecture.BuildingBlocks;
namespace Core.Blueprint.Service.UseCases.DeleteSampleItem
{
public class DeleteSampleItemHandler(IDeleteSampleItemPort port, IValidator<DeleteSampleItemRequest> validator, ISampleItemClientService clientService) : IComponentHandler<DeleteSampleItemRequest>
{
private readonly IDeleteSampleItemPort _port = port;
private readonly IValidator<DeleteSampleItemRequest> _validator = validator;
private readonly ISampleItemClientService _clientService = clientService;
public async ValueTask ExecuteAsync(DeleteSampleItemRequest command, CancellationToken cancellationToken = default)
{
try
{
if (!command.IsValid(_validator))
{
_port.ValidationErrors(command.Notifications);
return;
}
var entity = await _clientService.GetSampleItemAsync(command.Id);
if (entity == null)
{
_port.BusinessError("Not Found");
return;
}
entity.StatusCode = 'D';
await _clientService.UpdateSampleItemAsync(command.Id, entity);
_port.NoContentSuccess();
}
catch(Exception ex)
{
_port.BusinessError(ex.Message);
}
}
}
}

View File

@ -0,0 +1,13 @@
using Lib.Architecture.BuildingBlocks;
namespace Core.Blueprint.Service.UseCases.DeleteSampleItem.Input
{
public class DeleteSampleItemRequest : Notificator, ICommand
{
public string Id { get; set; } = string.Empty;
public bool Validate()
{
return true;
}
}
}

Some files were not shown because too many files have changed in this diff Show More