From dacb004ae981d589dc8c15e8e21604890a310b1f Mon Sep 17 00:00:00 2001 From: Sergio Matias Urquin Date: Tue, 29 Apr 2025 18:37:40 -0600 Subject: [PATCH] Add project files. --- .dockerignore | 30 ++++ .../Controllers/BaseController.cs | 48 +++++ .../Controllers/BlobStorageController.cs | 130 ++++++++++++++ .../Controllers/KeyVaultController.cs | 136 +++++++++++++++ .../Controllers/MongoBlueprintController.cs | 160 +++++++++++++++++ .../Controllers/SQLUserProjectController.cs | 165 ++++++++++++++++++ Core.Blueprint.API/Core.Blueprint.API.http | 6 + .../Core.Blueprint.BFF.API.csproj | 30 ++++ Core.Blueprint.API/Dockerfile | 25 +++ Core.Blueprint.API/Program.cs | 135 ++++++++++++++ .../Properties/launchSettings.json | 52 ++++++ .../appsettings.Development.json | 8 + Core.Blueprint.API/appsettings.Local.json | 11 ++ Core.Blueprint.API/appsettings.json | 12 ++ Core.Blueprint.BFF.sln | 39 +++++ .../RegisterClientConfiguration.cs | 65 +++++++ .../Blueprint/Adapters/BlueprintAdapter.cs | 17 ++ .../Blueprint/Adapters/KeyVaultAdapter.cs | 10 ++ .../Blueprint/Adapters/UserProjectAdapter.cs | 18 ++ .../Blueprint/IBlueprintServiceClient.cs | 70 ++++++++ .../Requests/BlobStorage/DeleteBlobRequest.cs | 7 + .../BlobStorage/DownloadBlobRequest.cs | 7 + .../BlobStorage/GetBlobListRequest.cs | 7 + .../Requests/BlobStorage/UploadBlobRequest.cs | 9 + .../Requests/KeyVault/CreateSecretRequest.cs | 9 + .../Requests/KeyVault/DeleteSecretRequest.cs | 6 + .../Requests/KeyVault/GetSecretRequest.cs | 7 + .../Requests/KeyVault/UpdateSecretRequest.cs | 8 + .../Requests/Mongo/CreateBlueprintRequest.cs | 9 + .../Requests/Mongo/DeleteBlueprintRequest.cs | 7 + .../Requests/Mongo/GetAllBlueprintsRequest.cs | 6 + .../Requests/Mongo/GetBlueprintRequest.cs | 7 + .../Requests/Mongo/UpdateBlueprintRequest.cs | 15 ++ .../Requests/SQL/CreateUserProjectRequest.cs | 9 + .../Requests/SQL/DeleteUserProjectRequest.cs | 7 + .../Requests/SQL/GetAllUserProjectsRequest.cs | 6 + .../Requests/SQL/GetUserProjectRequest.cs | 7 + .../Requests/SQL/UpdateUserProjectRequest.cs | 16 ++ .../Clients/Blueprint/Requests/StatusEnum.cs | 15 ++ .../Core.Blueprint.External.csproj | 20 +++ .../GatewayConfiguration.cs | 17 ++ .../GatewaySettingsConfigurations.cs | 46 +++++ .../TrackingMechanismExtension.cs | 18 ++ 43 files changed, 1432 insertions(+) create mode 100644 .dockerignore create mode 100644 Core.Blueprint.API/Controllers/BaseController.cs create mode 100644 Core.Blueprint.API/Controllers/BlobStorageController.cs create mode 100644 Core.Blueprint.API/Controllers/KeyVaultController.cs create mode 100644 Core.Blueprint.API/Controllers/MongoBlueprintController.cs create mode 100644 Core.Blueprint.API/Controllers/SQLUserProjectController.cs create mode 100644 Core.Blueprint.API/Core.Blueprint.API.http create mode 100644 Core.Blueprint.API/Core.Blueprint.BFF.API.csproj create mode 100644 Core.Blueprint.API/Dockerfile create mode 100644 Core.Blueprint.API/Program.cs create mode 100644 Core.Blueprint.API/Properties/launchSettings.json create mode 100644 Core.Blueprint.API/appsettings.Development.json create mode 100644 Core.Blueprint.API/appsettings.Local.json create mode 100644 Core.Blueprint.API/appsettings.json create mode 100644 Core.Blueprint.BFF.sln create mode 100644 Core.Blueprint.External/ClientConfiguration/RegisterClientConfiguration.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Adapters/BlueprintAdapter.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Adapters/KeyVaultAdapter.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Adapters/UserProjectAdapter.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/IBlueprintServiceClient.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DeleteBlobRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DownloadBlobRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/GetBlobListRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/UploadBlobRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/CreateSecretRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/DeleteSecretRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/GetSecretRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/UpdateSecretRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/CreateBlueprintRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/DeleteBlueprintRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetAllBlueprintsRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetBlueprintRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/UpdateBlueprintRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/SQL/CreateUserProjectRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/SQL/DeleteUserProjectRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetAllUserProjectsRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetUserProjectRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/SQL/UpdateUserProjectRequest.cs create mode 100644 Core.Blueprint.External/Clients/Blueprint/Requests/StatusEnum.cs create mode 100644 Core.Blueprint.External/Core.Blueprint.External.csproj create mode 100644 Core.Blueprint.External/GatewayConfigurations/GatewayConfiguration.cs create mode 100644 Core.Blueprint.External/GatewayConfigurations/GatewaySettingsConfigurations.cs create mode 100644 Core.Blueprint.External/TrackingMechanismExtension.cs diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/Core.Blueprint.API/Controllers/BaseController.cs b/Core.Blueprint.API/Controllers/BaseController.cs new file mode 100644 index 0000000..0b39a17 --- /dev/null +++ b/Core.Blueprint.API/Controllers/BaseController.cs @@ -0,0 +1,48 @@ +using Lib.Architecture.BuildingBlocks.Presentation.Adapters; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using Refit; + +namespace Core.Blueprint.API.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class BaseController(ILogger logger) : ControllerBase + { + private readonly ILogger _logger = logger; + + protected Guid TrackingId => (Guid)(HttpContext.Items["TrackingId"] ?? Guid.NewGuid()); + + protected async Task Handle(Func>> apiCall) where T : class + { + var response = await apiCall().ConfigureAwait(false); + + _logger.LogInformation($"{TrackingId} - {response.RequestMessage?.Method} {response.RequestMessage?.RequestUri} - Status: {response.StatusCode}"); + + return FromAPIResponse(response); + } + + private IActionResult FromAPIResponse(ApiResponse response) where T : class + { + if (response.IsSuccessful) + return StatusCode((int)response.StatusCode, response.Content); + else + { + dynamic errorContent = string.Empty; + + try + { + errorContent = JsonConvert.DeserializeObject(response.Error?.Content ?? string.Empty) ?? string.Empty; + } + catch (Exception) + { + errorContent = JsonConvert.DeserializeObject(response.Error?.Content); + if (errorContent?.Error?.ErrorCode is null && errorContent?.Error?.Message is null && errorContent?.Error?.Target is null) + errorContent = JsonConvert.DeserializeObject(response.Error?.Content); + + } + return StatusCode((int)response.StatusCode, errorContent); + } + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.API/Controllers/BlobStorageController.cs b/Core.Blueprint.API/Controllers/BlobStorageController.cs new file mode 100644 index 0000000..c1faf4c --- /dev/null +++ b/Core.Blueprint.API/Controllers/BlobStorageController.cs @@ -0,0 +1,130 @@ +using Core.Blueprint.API.Controllers; +using Core.Blueprint.External.Clients.Blueprint; +using Core.Blueprint.External.Clients.Blueprint.Requests.BlobStorage; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; +using System.Text.Json; + +namespace Core.Blob.API.Controllers +{ + /// + /// Handles all requests for blob. + /// + [ApiVersion("1.0")] + //[Route("api/v{version:apiVersion}/[controller]")] + [Consumes("application/json")] + [Produces("application/json")] + [ApiController] + public class BlobStorageController(IBlueprintServiceClient blueprintServiceClient, ILogger logger) : BaseController(logger) + { + /// + /// Uploads a new blob. + /// + [HttpPost("UploadBlob")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task UploadBlobService(UploadBlobRequest newBlob, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(UploadBlobService)} - Request received - Payload: {JsonSerializer.Serialize(newBlob)}"); + + if (newBlob == null) return BadRequest("Invalid blob object"); + + if (string.IsNullOrEmpty(newBlob.BlobName)) return BadRequest("Invalid blob name"); + + if (newBlob.BlobContent is null) return BadRequest("Invalid blob content"); + + return await Handle(() => blueprintServiceClient.UploadBlobService(newBlob, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(UploadBlobService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(newBlob)}"); + throw; + } + } + + /// + /// Gets all blobs into the container. + /// + [HttpGet("GetBlobList")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetBlobListService([FromQuery] string? prefix, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(GetBlobListService)} - Request received - Payload: "); + + return await Handle(() => blueprintServiceClient.GetBlobListAsync(prefix, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(GetBlobListService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload"); + throw; + } + } + + /// + /// Donwloads a blob by name. + /// + [HttpPost("DownloadBlob")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DownloadBlobService(DownloadBlobRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(DownloadBlobService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (string.IsNullOrEmpty(request.BlobName)) return BadRequest("Invalid blob name"); + + return await Handle(() => blueprintServiceClient.DownloadBlobAsync(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(DownloadBlobService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + + /// + /// Deletes the blob by identifier. + /// + [HttpDelete("Delete")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteBlobService([FromBody] DeleteBlobRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(DeleteBlobService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (string.IsNullOrEmpty(request.BlobName)) return BadRequest("Invalid blob name"); + + return await Handle(() => blueprintServiceClient.DeleteBlobService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(DeleteBlobService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + } +} diff --git a/Core.Blueprint.API/Controllers/KeyVaultController.cs b/Core.Blueprint.API/Controllers/KeyVaultController.cs new file mode 100644 index 0000000..50e1a37 --- /dev/null +++ b/Core.Blueprint.API/Controllers/KeyVaultController.cs @@ -0,0 +1,136 @@ +using Core.Blueprint.API.Controllers; +using Core.Blueprint.External.Clients.Blueprint; +using Core.Blueprint.External.Clients.Blueprint.Requests.KeyVault; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; +using System.Text.Json; + +namespace Core.Secret.API.Controllers +{ + /// + /// Handles all requests for secret. + /// + [ApiVersion("1.0")] + //[Route("api/v{version:apiVersion}/[controller]")] + [Consumes("application/json")] + [Produces("application/json")] + [ApiController] + public class KeyVaultController(IBlueprintServiceClient blueprintServiceClient, ILogger logger) : BaseController(logger) + { + /// + /// Creates a new secret. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task CreateSecretService(CreateSecretRequest newSecret, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(CreateSecretService)} - Request received - Payload: {JsonSerializer.Serialize(newSecret)}"); + + if (newSecret == null) return BadRequest("Invalid secret object"); + + if (string.IsNullOrEmpty(newSecret.Name)) return BadRequest("Invalid secret name"); + + if (string.IsNullOrEmpty(newSecret.Value)) return BadRequest("Invalid secret description"); + + return await Handle(() => blueprintServiceClient.CreateSecretService(newSecret, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(CreateSecretService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(newSecret)}"); + throw; + } + } + + /// + /// Gets the secret by identifier. + /// + [HttpPost("GetSecretByName")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetSecretByNameService(GetSecretRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(GetSecretByNameService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (string.IsNullOrEmpty(request.Name)) return BadRequest("Invalid secret name"); + + return await Handle(() => blueprintServiceClient.GetSecretByNameService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(GetSecretByNameService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + + /// + /// Updates a full secret by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task UpdateSecretService(UpdateSecretRequest newSecret, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(UpdateSecretService)} - Request received - Payload: {JsonSerializer.Serialize(newSecret)}"); + + if (newSecret == null) return BadRequest("Invalid secret object"); + + if (string.IsNullOrEmpty(newSecret.Name)) return BadRequest("Invalid secret name"); + + if (string.IsNullOrEmpty(newSecret.Value)) return BadRequest("Invalid secret value"); + + return await Handle(() => blueprintServiceClient.UpdateSecretService(newSecret, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(UpdateSecretService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(newSecret)}"); + throw; + } + } + + /// + /// Deletes the secret by identifier. + /// + [HttpPost("Delete")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteSecretService(DeleteSecretRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(DeleteSecretService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (string.IsNullOrEmpty(request.Name)) return BadRequest("Invalid secret name"); + + return await Handle(() => blueprintServiceClient.DeleteSecretService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(DeleteSecretService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + } +} diff --git a/Core.Blueprint.API/Controllers/MongoBlueprintController.cs b/Core.Blueprint.API/Controllers/MongoBlueprintController.cs new file mode 100644 index 0000000..c952528 --- /dev/null +++ b/Core.Blueprint.API/Controllers/MongoBlueprintController.cs @@ -0,0 +1,160 @@ +using Core.Blueprint.External.Clients.Blueprint; +using Core.Blueprint.External.Clients.Blueprint.Requests.Mongo; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; +using System.Text.Json; + +namespace Core.Blueprint.API.Controllers +{ + /// + /// Handles all requests for blueprint. + /// + [ApiVersion("1.0")] + //[Route("api/v{version:apiVersion}/[controller]")] + [Consumes("application/json")] + [Produces("application/json")] + [ApiController] + public class MongoBlueprintController(IBlueprintServiceClient blueprintServiceClient, ILogger logger) : BaseController(logger) + { + /// + /// Creates a new blueprint. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task CreateBlueprintService(CreateBlueprintRequest newBlueprint, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(CreateBlueprintService)} - Request received - Payload: {JsonSerializer.Serialize(newBlueprint)}"); + + if (newBlueprint == null) return BadRequest("Invalid blueprint object"); + + if (string.IsNullOrEmpty(newBlueprint.Name)) return BadRequest("Invalid blueprint name"); + + if (string.IsNullOrEmpty(newBlueprint.Description)) return BadRequest("Invalid blueprint description"); + + return await Handle(() => blueprintServiceClient.CreateBlueprintService(newBlueprint, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(CreateBlueprintService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(newBlueprint)}"); + throw; + } + } + + /// + /// Gets all blueprints. + /// + [HttpGet("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetAllBlueprintsService(CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(GetAllBlueprintsService)} - Request received - Payload: "); + + return await Handle(() => blueprintServiceClient.GetAllBlueprintsService(cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(GetAllBlueprintsService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload"); + throw; + } + } + + /// + /// Gets the blueprint by identifier. + /// + [HttpPost("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetBlueprintByIdService(GetBlueprintRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(GetBlueprintByIdService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (string.IsNullOrEmpty(request._Id)) return BadRequest("Invalid blueprint identifier"); + + return await Handle(() => blueprintServiceClient.GetBlueprintByIdService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(GetBlueprintByIdService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + + /// + /// Updates a full blueprint by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task UpdateBlueprintService(UpdateBlueprintRequest newBlueprint, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(UpdateBlueprintService)} - Request received - Payload: {JsonSerializer.Serialize(newBlueprint)}"); + + if (newBlueprint == null) return BadRequest("Invalid blueprint object"); + + if (string.IsNullOrEmpty(newBlueprint.Name)) return BadRequest("Invalid blueprint name"); + + if (string.IsNullOrEmpty(newBlueprint.Description)) return BadRequest("Invalid blueprint description"); + + return await Handle(() => blueprintServiceClient.UpdateBlueprintService(newBlueprint, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(UpdateBlueprintService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(newBlueprint)}"); + throw; + } + } + + /// + /// Deletes the blueprint by identifier. + /// + [HttpPost("Delete")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteBlueprintService(DeleteBlueprintRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(DeleteBlueprintService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (string.IsNullOrEmpty(request._Id)) return BadRequest("Invalid blueprint identifier"); + + return await Handle(() => blueprintServiceClient.DeleteBlueprintService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(DeleteBlueprintService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + } +} diff --git a/Core.Blueprint.API/Controllers/SQLUserProjectController.cs b/Core.Blueprint.API/Controllers/SQLUserProjectController.cs new file mode 100644 index 0000000..1279be6 --- /dev/null +++ b/Core.Blueprint.API/Controllers/SQLUserProjectController.cs @@ -0,0 +1,165 @@ +using Core.Blueprint.API.Controllers; +using Core.Blueprint.External.Clients.Blueprint; +using Core.Blueprint.External.Clients.Blueprint.Requests.SQL; +using Lib.Architecture.BuildingBlocks; +using Microsoft.AspNetCore.Mvc; +using System.Text.Json; + +namespace Core.UserProject.API.Controllers +{ + /// + /// Handles all requests for user project. + /// + [ApiVersion("1.0")] + //[Route("api/v{version:apiVersion}/[controller]")] + [Consumes("application/json")] + [Produces("application/json")] + [ApiController] + public class SQLUserProjectController(IBlueprintServiceClient blueprintServiceClient, ILogger logger) : BaseController(logger) + { + /// + /// Creates a new user project. + /// + [HttpPost("Create")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task CreateUserProjectService(CreateUserProjectRequest newUserProject, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(CreateUserProjectService)} - Request received - Payload: {JsonSerializer.Serialize(newUserProject)}"); + + if (newUserProject == null) return BadRequest("Invalid user project object"); + + if (string.IsNullOrEmpty(newUserProject.ProjectCode)) return BadRequest("Invalid project code"); + + if (string.IsNullOrEmpty(newUserProject.ProjectDescription)) return BadRequest("Invalid project description"); + + if (string.IsNullOrEmpty(newUserProject.UserId)) return BadRequest("Invalid user identifier"); + + return await Handle(() => blueprintServiceClient.CreateUserProjectService(newUserProject, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(CreateUserProjectService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(newUserProject)}"); + throw; + } + } + + /// + /// Gets all user projects. + /// + [HttpGet("GetAll")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetAllUserProjectsService(CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(GetAllUserProjectsService)} - Request received - Payload: "); + + return await Handle(() => blueprintServiceClient.GetAllUserProjectsService(cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(GetAllUserProjectsService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload"); + throw; + } + } + + /// + /// Gets the user project by identifier. + /// + [HttpPost("GetById")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetUserProjectByIdService(GetUserProjectRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(GetUserProjectByIdService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (request.Id <= 0) return BadRequest("Invalid user project identifier"); + + return await Handle(() => blueprintServiceClient.GetUserProjectByIdService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(GetUserProjectByIdService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + + /// + /// Updates a full user project by identifier. + /// + [HttpPut("Update")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task UpdateUserProjectService(UpdateUserProjectRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(UpdateUserProjectService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (request == null) return BadRequest("Invalid user project object"); + + if (string.IsNullOrEmpty(request.ProjectCode)) return BadRequest("Invalid user project code"); + + if (string.IsNullOrEmpty(request.ProjectDescription)) return BadRequest("Invalid user project description"); + + if (string.IsNullOrEmpty(request.UserId)) return BadRequest("Invalid user identifier"); + + return await Handle(() => blueprintServiceClient.UpdateUserProjectService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(UpdateUserProjectService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + + /// + /// Deletes the user project by identifier. + /// + [HttpPost("Delete")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(Notification), StatusCodes.Status422UnprocessableEntity)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task DeleteUserProjectService(DeleteUserProjectRequest request, CancellationToken cancellationToken) + { + try + { + logger.LogInformation($"{nameof(DeleteUserProjectService)} - Request received - Payload: {JsonSerializer.Serialize(request)}"); + + if (request.Id <= 0) return BadRequest("Invalid user project identifier"); + + return await Handle(() => blueprintServiceClient.DeleteUserProjectService(request, cancellationToken)).ConfigureAwait(false); + } + catch (Exception ex) + { + logger.LogError($"{nameof(DeleteUserProjectService)} - An Error Occurred- {ex.Message} - {ex.InnerException} - {ex.StackTrace} - with payload {JsonSerializer.Serialize(request)}"); + throw; + } + } + } +} diff --git a/Core.Blueprint.API/Core.Blueprint.API.http b/Core.Blueprint.API/Core.Blueprint.API.http new file mode 100644 index 0000000..b7e88fa --- /dev/null +++ b/Core.Blueprint.API/Core.Blueprint.API.http @@ -0,0 +1,6 @@ +@Core.Blueprint.API_HostAddress = http://localhost:5239 + +GET {{Core.Blueprint.API_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Core.Blueprint.API/Core.Blueprint.BFF.API.csproj b/Core.Blueprint.API/Core.Blueprint.BFF.API.csproj new file mode 100644 index 0000000..f91cc7a --- /dev/null +++ b/Core.Blueprint.API/Core.Blueprint.BFF.API.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + a9738f26-cc0a-4362-9b27-8e8bacd0b42d + Linux + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core.Blueprint.API/Dockerfile b/Core.Blueprint.API/Dockerfile new file mode 100644 index 0000000..eacc833 --- /dev/null +++ b/Core.Blueprint.API/Dockerfile @@ -0,0 +1,25 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["Core.Blueprint.API/Core.Blueprint.API.csproj", "Core.Blueprint.API/"] +RUN dotnet restore "./Core.Blueprint.API/Core.Blueprint.API.csproj" +COPY . . +WORKDIR "/src/Core.Blueprint.API" +RUN dotnet build "./Core.Blueprint.API.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./Core.Blueprint.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.API.dll"] \ No newline at end of file diff --git a/Core.Blueprint.API/Program.cs b/Core.Blueprint.API/Program.cs new file mode 100644 index 0000000..c313102 --- /dev/null +++ b/Core.Blueprint.API/Program.cs @@ -0,0 +1,135 @@ +using Azure.Identity; +using Core.Blueprint.External; +using Core.Blueprint.External.ClientConfiguration; +using Core.Blueprint.Logging.Configuration; +using Microsoft.AspNetCore.ResponseCompression; +using Microsoft.Extensions.Configuration.AzureAppConfiguration; +using OpenTelemetry.Logs; +using OpenTelemetry.Resources; +using System.IO.Compression; +using System.Reflection; + +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_api"); + + options.ConfigureKeyVault(keyVaultOptions => + { + keyVaultOptions.SetCredential(new DefaultAzureCredential()); + }); +}); + +builder.Services.AddEndpointsApiExplorer(); +builder.Configuration + .AddUserSecrets(Assembly.GetExecutingAssembly()) + .AddEnvironmentVariables(); + +builder.Services.AddResponseCompression(); +builder.Services.AddProblemDetails(); +builder.Services.AddLogs(builder); +builder.Services.AddMemoryCache(); +builder.Services.AddResponseCaching(configureOptions => { configureOptions.UseCaseSensitivePaths = true; }); +builder.Logging.AddOpenTelemetry(options => +{ + options.IncludeScopes = true; + options.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("core.blueprint.bff.api")).AddConsoleExporter(); +}); + +builder.Host.ConfigureServices((context, services) => +{ + builder.Services.AddHsts(options => + { + options.Preload = true; + options.IncludeSubDomains = true; + options.MaxAge = TimeSpan.FromDays(60); + }); + builder.Services.AddResponseCaching(configureOptions => + { + configureOptions.UseCaseSensitivePaths = true; + configureOptions.MaximumBodySize = 2048; + }); + builder.Services.AddHttpsRedirection(options => + { + options.RedirectStatusCode = 308; + }); + + services.AddHttpLogging(http => + { + http.CombineLogs = true; + }); + services.AddAntiforgery(); + + services.AddCors(options => + { + options.AddPolicy("AllowAll", policyBuilder => + policyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); + }); + services.AddMvc().AddJsonOptions(options => + { + options.JsonSerializerOptions.WriteIndented = true; + options.JsonSerializerOptions.MaxDepth = 20; + options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals; + }); + services.Configure(options => + { + options.Level = CompressionLevel.SmallestSize; + }); + services.Configure(options => + { + options.Level = CompressionLevel.SmallestSize; + }); + services.AddResponseCompression(options => + { + options.EnableForHttps = true; + options.Providers.Add(); + options.Providers.Add(); + }); + services.AddResponseCaching(); + services.AddControllers(); + services.AddEndpointsApiExplorer(); + services.AddSwaggerGen(); + services.AddLogging(); + services.AddProblemDetails(); + services.AddHttpContextAccessor(); + services.AddTransient(); // Register the TrackingIdHandler + services.RegisterExternalLayer(builder.Configuration); +}); + +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy( + builder => + { + builder.AllowAnyOrigin() + .AllowAnyHeader() + .AllowAnyMethod(); + }); +}); + +//*************************************************************************// +var app = builder.Build(); + + +app.UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()); +app.UseSwagger(); +app.UseSwaggerUI(); +app.UseResponseCompression(); +app.UseResponseCaching(); +app.UseHttpsRedirection(); + +app.UseAuthentication(); +app.UseAuthorization(); +app.MapControllers(); +app.UseHsts(); +app.UseAntiforgery(); +app.UseLogging(builder.Configuration); + +app.Run(); \ No newline at end of file diff --git a/Core.Blueprint.API/Properties/launchSettings.json b/Core.Blueprint.API/Properties/launchSettings.json new file mode 100644 index 0000000..0b1e36e --- /dev/null +++ b/Core.Blueprint.API/Properties/launchSettings.json @@ -0,0 +1,52 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5239" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7056;http://localhost:5239" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + } + }, + "Container (Dockerfile)": { + "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:54447", + "sslPort": 44347 + } + } +} \ No newline at end of file diff --git a/Core.Blueprint.API/appsettings.Development.json b/Core.Blueprint.API/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Core.Blueprint.API/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Core.Blueprint.API/appsettings.Local.json b/Core.Blueprint.API/appsettings.Local.json new file mode 100644 index 0000000..4ec0805 --- /dev/null +++ b/Core.Blueprint.API/appsettings.Local.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "LocalGateways": { + "BlueprintService": "https://localhost:7243/api" + } +} diff --git a/Core.Blueprint.API/appsettings.json b/Core.Blueprint.API/appsettings.json new file mode 100644 index 0000000..d321977 --- /dev/null +++ b/Core.Blueprint.API/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Endpoints": { + "AppConfigurationURI": "https://sandbox-hci-usc-appcg.azconfig.io" + } +} diff --git a/Core.Blueprint.BFF.sln b/Core.Blueprint.BFF.sln new file mode 100644 index 0000000..ba9f002 --- /dev/null +++ b/Core.Blueprint.BFF.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34309.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{F3994F88-26E0-4123-8304-1FB0346E6A1F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.BFF.API", "Core.Blueprint.API\Core.Blueprint.BFF.API.csproj", "{DD6855D6-B19A-4125-BC53-3BD856BF7D0B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{9DBA13A6-339F-4FD6-B53D-43F2D015C840}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Blueprint.External", "Core.Blueprint.External\Core.Blueprint.External.csproj", "{F18C641D-3064-4DCA-B843-CFE4D5F361F9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DD6855D6-B19A-4125-BC53-3BD856BF7D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD6855D6-B19A-4125-BC53-3BD856BF7D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD6855D6-B19A-4125-BC53-3BD856BF7D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD6855D6-B19A-4125-BC53-3BD856BF7D0B}.Release|Any CPU.Build.0 = Release|Any CPU + {F18C641D-3064-4DCA-B843-CFE4D5F361F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F18C641D-3064-4DCA-B843-CFE4D5F361F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F18C641D-3064-4DCA-B843-CFE4D5F361F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F18C641D-3064-4DCA-B843-CFE4D5F361F9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {DD6855D6-B19A-4125-BC53-3BD856BF7D0B} = {F3994F88-26E0-4123-8304-1FB0346E6A1F} + {F18C641D-3064-4DCA-B843-CFE4D5F361F9} = {9DBA13A6-339F-4FD6-B53D-43F2D015C840} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {771B556E-9EA3-46CD-BC3F-5DCF1098A8B7} + EndGlobalSection +EndGlobal diff --git a/Core.Blueprint.External/ClientConfiguration/RegisterClientConfiguration.cs b/Core.Blueprint.External/ClientConfiguration/RegisterClientConfiguration.cs new file mode 100644 index 0000000..384f528 --- /dev/null +++ b/Core.Blueprint.External/ClientConfiguration/RegisterClientConfiguration.cs @@ -0,0 +1,65 @@ +using Core.Blueprint.External.Clients.Blueprint; +using Core.Blueprint.External.GatewayConfigurations; +using Lib.Architecture.BuildingBlocks.Helpers.Token; +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 GatewaySettingsConfigurations(configuration); + + // Register GatewayConfiguration as a singleton + services.AddSingleton(gatewayConfiguration); + + // Register IHttpContextAccessor + services.AddSingleton(); + + // Register ITokenProvider + services.AddSingleton(); + + // Register the custom AuthenticatedHttpClientHandler + services.AddTransient(provider => + { + var tokenProvider = provider.GetRequiredService(); + var trackingIdHandler = new TrackingMechanismExtension(provider.GetRequiredService()); + + var handler = new AuthenticatedHttpClientHandler(tokenProvider) + { + InnerHandler = new HttpClientHandler() // Setting the InnerHandler manually + }; + + // Attach the TrackingIdHandler as the outermost handler + trackingIdHandler.InnerHandler = handler; + + return handler; + }); + + var blueprintServiceApiUrl = GatewaySettingsConfigurations.GetBlueprintServiceAPIEndpoint().Endpoint.Url; + + // Register IDashBoardServiceClient with the manually created HttpClient + services.AddScoped(provider => + { + var handler = provider.GetRequiredService(); + var handlerTrackingId = new TrackingMechanismExtension(provider.GetRequiredService()); // Using the TrackingIdHandler here + // Chain the handlers + handlerTrackingId.InnerHandler = handler; //chaining + + var httpClient = new HttpClient(handlerTrackingId) + { + BaseAddress = new Uri(blueprintServiceApiUrl), + Timeout = TimeSpan.FromMinutes(1) + }; + return RestService.For(httpClient); + }); + + return services; + } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Adapters/BlueprintAdapter.cs b/Core.Blueprint.External/Clients/Blueprint/Adapters/BlueprintAdapter.cs new file mode 100644 index 0000000..77e35c8 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Adapters/BlueprintAdapter.cs @@ -0,0 +1,17 @@ +using Core.Blueprint.External.Clients.Blueprint.Requests; + +namespace Core.Blueprint.External.Clients.Blueprint.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; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Adapters/KeyVaultAdapter.cs b/Core.Blueprint.External/Clients/Blueprint/Adapters/KeyVaultAdapter.cs new file mode 100644 index 0000000..0c9111d --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Adapters/KeyVaultAdapter.cs @@ -0,0 +1,10 @@ +using Core.Blueprint.KeyVault; + +namespace Core.Blueprint.External.Clients.Blueprint.Adapters +{ + public class KeyVaultAdapter + { + public KeyVaultResponse Item1 { get; set; } + public string Item2 { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Adapters/UserProjectAdapter.cs b/Core.Blueprint.External/Clients/Blueprint/Adapters/UserProjectAdapter.cs new file mode 100644 index 0000000..08ac0ed --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Adapters/UserProjectAdapter.cs @@ -0,0 +1,18 @@ +using Core.Blueprint.External.Clients.Blueprint.Requests; + +namespace Core.Blueprint.External.Clients.Blueprint.Adapters +{ + public class UserProjectAdapter + { + public string ProjectCode { get; set; } = null!; + public string ProjectDescription { get; set; } = null!; + public string UserId { get; set; } = null!; + public int Id { get; set; } + public string Guid { get; set; } = null!; + public DateTime CreatedAt { get; set; } + public string? CreatedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public string? UpdatedBy { get; set; } + public StatusEnum Status { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/IBlueprintServiceClient.cs b/Core.Blueprint.External/Clients/Blueprint/IBlueprintServiceClient.cs new file mode 100644 index 0000000..65ce714 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/IBlueprintServiceClient.cs @@ -0,0 +1,70 @@ +using Core.Blueprint.External.Clients.Blueprint.Adapters; +using Core.Blueprint.External.Clients.Blueprint.Requests.BlobStorage; +using Core.Blueprint.External.Clients.Blueprint.Requests.KeyVault; +using Core.Blueprint.External.Clients.Blueprint.Requests.Mongo; +using Core.Blueprint.External.Clients.Blueprint.Requests.SQL; +using Core.Blueprint.KeyVault; +using Core.Blueprint.Storage; +using Core.Blueprint.Storage.Adapters; +using Microsoft.AspNetCore.Mvc; +using Refit; + +namespace Core.Blueprint.External.Clients.Blueprint +{ + public interface IBlueprintServiceClient + { + [Post("/v1/MongoBlueprint/Create")] + Task> CreateBlueprintService([Body] CreateBlueprintRequest newBlueprint, CancellationToken cancellationToken = default); + + [Get("/v1/MongoBlueprint/GetAll")] + Task>> GetAllBlueprintsService(CancellationToken cancellationToken = default); + + [Post("/v1/MongoBlueprint/GetById")] + Task> GetBlueprintByIdService([Body] GetBlueprintRequest request, CancellationToken cancellationToken = default); + + [Put("/v1/MongoBlueprint/Update")] + Task> UpdateBlueprintService([Body] UpdateBlueprintRequest entity, CancellationToken cancellationToken = default); + + [Delete("/v1/MongoBlueprint/Delete")] + Task> DeleteBlueprintService([Body] DeleteBlueprintRequest request, CancellationToken cancellationToken = default); + + [Post("/v1/SQLUserProject/Create")] + Task> CreateUserProjectService([Body] CreateUserProjectRequest newUserProject, CancellationToken cancellationToken = default); + + [Get("/v1/SQLUserProject/GetAll")] + Task>> GetAllUserProjectsService(CancellationToken cancellationToken = default); + + [Post("/v1/SQLUserProject/GetById")] + Task> GetUserProjectByIdService([Body] GetUserProjectRequest request, CancellationToken cancellationToken = default); + + [Put("/v1/SQLUserProject/Update")] + Task> UpdateUserProjectService([Body] UpdateUserProjectRequest entity, CancellationToken cancellationToken = default); + + [Delete("/v1/SQLUserProject/Delete")] + Task> DeleteUserProjectService([Body] DeleteUserProjectRequest request, CancellationToken cancellationToken = default); + + [Post("/v1/KeyVault/CreateSecret")] + Task> CreateSecretService([Body] CreateSecretRequest newKeyVault, CancellationToken cancellationToken = default); + + [Post("/v1/KeyVault/GetSecretByName")] + Task> GetSecretByNameService([Body] GetSecretRequest request, CancellationToken cancellationToken = default); + + [Put("/v1/KeyVault/UpdateSecret")] + Task> UpdateSecretService([Body] UpdateSecretRequest entity, CancellationToken cancellationToken = default); + + [Delete("/v1/KeyVault/DeleteSecret")] + Task> DeleteSecretService([Body] DeleteSecretRequest request, CancellationToken cancellationToken = default); + + [Post("/v1/BlobStorage/UploadBlob")] + Task> UploadBlobService([Body] UploadBlobRequest request, CancellationToken cancellationToken = default); + + [Get("/v1/BlobStorage/GetBlobList")] + Task>> GetBlobListAsync([FromQuery] string? prefix, CancellationToken cancellationToken = default); + + [Post("/v1/BlobStorage/DownloadBlob")] + Task> DownloadBlobAsync([Body] DownloadBlobRequest request, CancellationToken cancellationToken = default); + + [Delete("/v1/BlobStorage/DeleteBlob")] + Task> DeleteBlobService([Body] DeleteBlobRequest request, CancellationToken cancellationToken = default); + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DeleteBlobRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DeleteBlobRequest.cs new file mode 100644 index 0000000..40c2dbd --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DeleteBlobRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.BlobStorage +{ + public class DeleteBlobRequest + { + public string BlobName { get; set; } = null!; + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DownloadBlobRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DownloadBlobRequest.cs new file mode 100644 index 0000000..6fbb8da --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/DownloadBlobRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.BlobStorage +{ + public class DownloadBlobRequest + { + public string BlobName { get; set; } = null!; + } +} \ No newline at end of file diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/GetBlobListRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/GetBlobListRequest.cs new file mode 100644 index 0000000..4ca8bb2 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/GetBlobListRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.BlobStorage +{ + public class GetBlobListRequest + { + public string? Prefix { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/UploadBlobRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/UploadBlobRequest.cs new file mode 100644 index 0000000..f07aaf3 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/BlobStorage/UploadBlobRequest.cs @@ -0,0 +1,9 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.BlobStorage +{ + public class UploadBlobRequest + { + public string BlobName { get; set; } = null!; + + public byte[] BlobContent { get; set; } = null!; + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/CreateSecretRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/CreateSecretRequest.cs new file mode 100644 index 0000000..9791d1b --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/CreateSecretRequest.cs @@ -0,0 +1,9 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.KeyVault +{ + public class CreateSecretRequest + { + public string Name { get; set; } = null!; + + public string Value { get; set; } = null!; + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/DeleteSecretRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/DeleteSecretRequest.cs new file mode 100644 index 0000000..c97ee84 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/DeleteSecretRequest.cs @@ -0,0 +1,6 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.KeyVault; + +public class DeleteSecretRequest +{ + public string Name { get; set; } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/GetSecretRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/GetSecretRequest.cs new file mode 100644 index 0000000..cb79483 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/GetSecretRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.KeyVault +{ + public class GetSecretRequest + { + public string Name { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/UpdateSecretRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/UpdateSecretRequest.cs new file mode 100644 index 0000000..50c8794 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/KeyVault/UpdateSecretRequest.cs @@ -0,0 +1,8 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.KeyVault +{ + public class UpdateSecretRequest + { + public string Name { get; set; } = null!; + public string Value { get; set; } = null!; + } +} \ No newline at end of file diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/CreateBlueprintRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/CreateBlueprintRequest.cs new file mode 100644 index 0000000..c5ccb82 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/CreateBlueprintRequest.cs @@ -0,0 +1,9 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.Mongo +{ + public class CreateBlueprintRequest + { + public string Name { get; set; } = null!; + + public string? Description { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/DeleteBlueprintRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/DeleteBlueprintRequest.cs new file mode 100644 index 0000000..c1a6b7e --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/DeleteBlueprintRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.Mongo +{ + public class DeleteBlueprintRequest + { + public string _Id { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetAllBlueprintsRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetAllBlueprintsRequest.cs new file mode 100644 index 0000000..7a302ee --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetAllBlueprintsRequest.cs @@ -0,0 +1,6 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.Mongo +{ + public class GetAllBlueprintsRequest + { + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetBlueprintRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetBlueprintRequest.cs new file mode 100644 index 0000000..5197677 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/GetBlueprintRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.Mongo +{ + public class GetBlueprintRequest + { + public string _Id { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/UpdateBlueprintRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/UpdateBlueprintRequest.cs new file mode 100644 index 0000000..8cd933a --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/Mongo/UpdateBlueprintRequest.cs @@ -0,0 +1,15 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.Mongo +{ + public class UpdateBlueprintRequest + { + 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; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/CreateUserProjectRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/CreateUserProjectRequest.cs new file mode 100644 index 0000000..15d6f57 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/CreateUserProjectRequest.cs @@ -0,0 +1,9 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.SQL +{ + public class CreateUserProjectRequest + { + public string ProjectCode { get; set; } = null!; + public string ProjectDescription { get; set; } = null!; + public string UserId { get; set; } = null!; + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/DeleteUserProjectRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/DeleteUserProjectRequest.cs new file mode 100644 index 0000000..e673b26 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/DeleteUserProjectRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.SQL +{ + public class DeleteUserProjectRequest + { + public int Id { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetAllUserProjectsRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetAllUserProjectsRequest.cs new file mode 100644 index 0000000..cdb3c49 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetAllUserProjectsRequest.cs @@ -0,0 +1,6 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.SQL +{ + public class GetAllUserProjectsRequest + { + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetUserProjectRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetUserProjectRequest.cs new file mode 100644 index 0000000..c5f0d2e --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/GetUserProjectRequest.cs @@ -0,0 +1,7 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.SQL +{ + public class GetUserProjectRequest + { + public int Id { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/UpdateUserProjectRequest.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/UpdateUserProjectRequest.cs new file mode 100644 index 0000000..041694c --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/SQL/UpdateUserProjectRequest.cs @@ -0,0 +1,16 @@ +namespace Core.Blueprint.External.Clients.Blueprint.Requests.SQL +{ + public class UpdateUserProjectRequest + { + public string ProjectCode { get; set; } = null!; + public string ProjectDescription { get; set; } = null!; + public string UserId { get; set; } = null!; + public int Id { get; set; } + public string Guid { get; set; } = null!; + public DateTime CreatedAt { get; set; } + public string? CreatedBy { get; set; } + public DateTime? UpdatedAt { get; set; } + public string? UpdatedBy { get; set; } + public StatusEnum Status { get; set; } + } +} diff --git a/Core.Blueprint.External/Clients/Blueprint/Requests/StatusEnum.cs b/Core.Blueprint.External/Clients/Blueprint/Requests/StatusEnum.cs new file mode 100644 index 0000000..85f3372 --- /dev/null +++ b/Core.Blueprint.External/Clients/Blueprint/Requests/StatusEnum.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace Core.Blueprint.External.Clients.Blueprint.Requests +{ + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum StatusEnum + { + + Active = 0, + + Inactive = 1, + + Deleted = 2 + } +} diff --git a/Core.Blueprint.External/Core.Blueprint.External.csproj b/Core.Blueprint.External/Core.Blueprint.External.csproj new file mode 100644 index 0000000..7113500 --- /dev/null +++ b/Core.Blueprint.External/Core.Blueprint.External.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + diff --git a/Core.Blueprint.External/GatewayConfigurations/GatewayConfiguration.cs b/Core.Blueprint.External/GatewayConfigurations/GatewayConfiguration.cs new file mode 100644 index 0000000..68c192d --- /dev/null +++ b/Core.Blueprint.External/GatewayConfigurations/GatewayConfiguration.cs @@ -0,0 +1,17 @@ +namespace Core.Blueprint.External.GatewayConfigurations +{ + public record GatewayConfiguration + { + public GatewayConfiguration() + { + BlueprintService = new BlueprintServiceAPI(); + } + + public BlueprintServiceAPI BlueprintService { get; set; } + } + public record BlueprintServiceAPI + { + public string Channel { get; set; } + public BaseEndpoint Endpoint { get; set; } + } +} diff --git a/Core.Blueprint.External/GatewayConfigurations/GatewaySettingsConfigurations.cs b/Core.Blueprint.External/GatewayConfigurations/GatewaySettingsConfigurations.cs new file mode 100644 index 0000000..3521dcb --- /dev/null +++ b/Core.Blueprint.External/GatewayConfigurations/GatewaySettingsConfigurations.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.Configuration; + +namespace Core.Blueprint.External.GatewayConfigurations +{ + public class GatewaySettingsConfigurations + { + private static GatewayConfiguration GatewayConfigurations { get; set; } = new GatewayConfiguration(); + private readonly IConfiguration _configuration; + + public GatewaySettingsConfigurations(IConfiguration configuration) + { + _configuration = configuration; + SetBlueprintServiceAPIEndpoint(); + } + public static BlueprintServiceAPI GetBlueprintServiceAPIEndpoint() + { + return GatewayConfigurations.BlueprintService; + } + 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["BlueprintService"] ?? string.Empty; + + GatewayConfigurations.BlueprintService = new BlueprintServiceAPI() + { + Endpoint = new BaseEndpoint() + { + Uri = new Uri(endpoint), + Url = endpoint, + Token = string.Empty, + APIName = "Blueprint Service" + } + }; + + return GatewayConfigurations; + } + } +} + diff --git a/Core.Blueprint.External/TrackingMechanismExtension.cs b/Core.Blueprint.External/TrackingMechanismExtension.cs new file mode 100644 index 0000000..c998513 --- /dev/null +++ b/Core.Blueprint.External/TrackingMechanismExtension.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Http; + +namespace Core.Blueprint.External +{ + public sealed class TrackingMechanismExtension(IHttpContextAccessor httpContextAccessor) : DelegatingHandler + { + private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (_httpContextAccessor.HttpContext != null) + { + request.Headers.Add("TrackingId", Guid.NewGuid().ToString()); + } + return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); + } + } +}