Add project files.

This commit is contained in:
Sergio Matias Urquin
2025-04-29 18:39:57 -06:00
parent 116793710f
commit 6358f5f199
110 changed files with 4484 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
using Asp.Versioning;
using Core.Blueprint.DAL.Storage.Contracts;
using Core.Blueprint.Storage;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Core.Blueprint.DAL.API.Controllers
{
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
[AllowAnonymous]
public class BlobStorageController(IBlobStorageService storageService) : ControllerBase
{
[HttpPost("UploadBlobFromFileBrowser")]
[Consumes("multipart/form-data")]
public async Task<IActionResult> UploadBlobAsync([FromQuery] string blobName, IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file uploaded.");
using var stream = file.OpenReadStream();
var result = await storageService.UploadBlobAsync(blobName, stream);
return Ok(result);
}
[HttpPost("UploadBlob")]
public async Task<IActionResult> UploadBlobAsync([FromBody] BlobAddDto newBlob)
{
var result = await storageService.UploadBlobAsync(newBlob);
return Ok(result);
}
[HttpGet("GetBlobList")]
public async Task<IActionResult> GetBlobsListAsync([FromQuery] string? prefix)
{
var result = await storageService.GetBlobsListAsync(prefix).ConfigureAwait(false);
return Ok(result);
}
[HttpGet("DownloadBlob")]
public IActionResult DownloadBlobAsync([FromQuery] string blobName)
{
var result = storageService.DownloadBlobAsync(blobName);
return Ok(result);
}
[HttpDelete("DeleteBlob")]
public async Task<IActionResult> DeleteFileAsync([FromQuery] string blobName)
{
var result = await storageService.DeleteBlobAsync(blobName).ConfigureAwait(false);
if (result is null) return NotFound($"Blob {blobName} doesn't exist");
return Ok(result);
}
}
}

View File

@@ -0,0 +1,44 @@
using Asp.Versioning;
using Core.Blueprint.DAL.KeyVault.Contracts;
using Core.Blueprint.KeyVault;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Core.Blueprint.DAL.API.Controllers
{
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
[AllowAnonymous]
public class KeyVaultController(IKeyVaultService service) : ControllerBase
{
[HttpPost("CreateSecret")]
public async Task<IActionResult> CreateSecret([FromBody] KeyVaultRequest newSecret, CancellationToken cancellationToken)
{
var result = await service.CreateSecretAsync(newSecret, cancellationToken);
return Ok(result);
}
[HttpGet("{secretName}/GetSecret")]
public async Task<IActionResult> GetSecret([FromRoute] string secretName, CancellationToken cancellationToken)
{
var result = await service.GetSecretAsync(secretName, cancellationToken);
return Ok(result);
}
[HttpPut("UpdateSecret")]
public async Task<IActionResult> UpdateSecret([FromBody] KeyVaultRequest newSecret, CancellationToken cancellationToken)
{
var result = await service.UpdateSecretAsync(newSecret, cancellationToken);
return Ok(result);
}
[HttpDelete("{secretName}/DeleteSecret")]
public async Task<IActionResult> DeleteSecret([FromRoute] string secretName, CancellationToken cancellationToken)
{
var result = await service.DeleteSecretAsync(secretName, cancellationToken);
return Ok(result);
}
}
}

View File

@@ -0,0 +1,67 @@
using Asp.Versioning;
using Core.Blueprint.DAL.Mongo.Contracts;
using Core.Blueprint.DAL.Mongo.Entities.Collections;
using Core.Blueprint.DAL.Mongo.Entities.Requests;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Core.Blueprint.DAL.API.Controllers
{
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
[AllowAnonymous]
public class MongoBlueprintController(IBlueprintService service) : ControllerBase
{
[HttpPost("Create")]
public async Task<IActionResult> CreateBlueprint([FromBody] BlueprintRequest entity, CancellationToken cancellationToken)
{
var result = await service.CreateBlueprint(entity, cancellationToken).ConfigureAwait(false);
return Created("CreatedWithIdAsync", result);
}
[HttpGet("GetAll")]
public async Task<IActionResult> GetEntities(CancellationToken cancellationToken)
{
var result = await service.GetAllBlueprints(cancellationToken).ConfigureAwait(false);
return Ok(result);
}
[HttpGet("{_id}/GetBy_Id")]
public async Task<IActionResult> GetBlueprint([FromRoute] string _id, CancellationToken cancellationToken)
{
var result = await service.GetBlueprintById(_id, cancellationToken).ConfigureAwait(false);
if (result == null)
{
return NotFound("Entity not found");
}
return Ok(result);
}
[HttpPut("{_id}/Update")]
public async Task<IActionResult> UpdateBlueprint([FromRoute] string _id, [FromBody] BlueprintCollection entity, CancellationToken cancellationToken)
{
if (_id != entity._Id?.ToString())
{
return BadRequest("Blueprint ID mismatch");
}
var result = await service.UpdateBlueprint(_id, entity, cancellationToken).ConfigureAwait(false);
return Ok(result);
}
[HttpDelete("{_id}/Delete")]
public async Task<IActionResult> DeleteBlueprint([FromRoute] string _id, CancellationToken cancellationToken)
{
var result = await service.DeleteBlueprint(_id, cancellationToken).ConfigureAwait(false);
if (result is null) return NotFound();
return Ok(result);
}
}
}

View File

@@ -0,0 +1,63 @@
using Asp.Versioning;
using Core.Blueprint.DAL.SQLServer.Contracts;
using Core.Blueprint.DAL.SQLServer.Entities;
using Core.Blueprint.DAL.SQLServer.Entities.Request;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Core.Blueprint.DAL.API.Controllers
{
[ApiVersion("1.0")]
[Route("api/v{api-version:apiVersion}/[controller]")]
[Produces("application/json")]
[ApiController]
[AllowAnonymous]
public class UserProjectController(IUserProjectService service) : ControllerBase
{
[HttpPost("Create")]
public async Task<ActionResult<UserProject>> CreateEntity([FromBody] UserProjectRequest request)
{
var result = await service.AddUserProject(request).ConfigureAwait(false);
return Created("CreatedWithIdAsync", result);
}
[HttpGet("GetAll")]
public async Task<ActionResult<IEnumerable<UserProject>>> GetEntities()
{
var result = await service.GetAllUserProjects().ConfigureAwait(false);
return Ok(result);
}
[HttpGet("{id}/GetById")]
public async Task<ActionResult<UserProject>> GetEntity(int id)
{
var result = await service.GetUserProjectById(id).ConfigureAwait(false);
if (result is null) return NotFound("User Project not found");
return Ok(result);
}
[HttpPut("{id}/Update")]
public async Task<ActionResult<UserProject>> UpdateEntity(int id, UserProject entity)
{
if (id != entity.Id)
{
return BadRequest("ID mismatch");
}
var result = await service.UpdateUserProject(entity).ConfigureAwait(false);
return Ok(entity);
}
[HttpDelete("{id}/Delete")]
public async Task<IActionResult> DeleteEntity(int id)
{
var result = await service.DeleteUserProject(id).ConfigureAwait(false);
if (result is null) return NotFound();
return Ok(result);
}
}
}

View File

@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>b441578c-ea54-49f9-ba82-09c2b23bd830</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.10" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core.Blueprint.DAL.KeyVault\Core.Blueprint.DAL.KeyVault.csproj" />
<ProjectReference Include="..\Core.Blueprint.DAL.Logs\Core.Blueprint.DAL.Logs.csproj" />
<ProjectReference Include="..\Core.Blueprint.DAL.Mongo\Core.Blueprint.DAL.Mongo.csproj" />
<ProjectReference Include="..\Core.Blueprint.DAL.Redis\Core.Blueprint.DAL.Redis.csproj" />
<ProjectReference Include="..\Core.Blueprint.DAL.SQLServer\Core.Blueprint.DAL.SQLServer.csproj" />
<ProjectReference Include="..\Core.Blueprint.DAL.Storage\Core.Blueprint.DAL.Storage.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
@Core.Blueprint.DAL.API_HostAddress = http://localhost:5013
GET {{Core.Blueprint.DAL.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.DAL.API/Core.Blueprint.DAL.API.csproj", "Core.Blueprint.DAL.API/"]
RUN dotnet restore "./Core.Blueprint.DAL.API/./Core.Blueprint.DAL.API.csproj"
COPY . .
WORKDIR "/src/Core.Blueprint.DAL.API"
RUN dotnet build "./Core.Blueprint.DAL.API.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./Core.Blueprint.DAL.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.DAL.API.dll"]

View File

@@ -0,0 +1,36 @@
using Core.Blueprint.DAL.KeyVault.Contracts;
using Core.Blueprint.DAL.KeyVault.Services;
using Core.Blueprint.DAL.Mongo.Contracts;
using Core.Blueprint.DAL.Mongo.Entities.Collections;
using Core.Blueprint.DAL.Mongo.Service;
using Core.Blueprint.DAL.SQLServer.Context;
using Core.Blueprint.DAL.SQLServer.Contracts;
using Core.Blueprint.DAL.Storage.Contracts;
using Core.Blueprint.DAL.Storage.Service;
using Core.Blueprint.Mongo;
using Microsoft.EntityFrameworkCore;
namespace Core.Blueprint.DAL.API.Extensions
{
public static class ConfigurationExtension
{
public static IServiceCollection AddDALLayerServices(this IServiceCollection services, IConfiguration configuration)
{
//Mongo
services.AddScoped<IBlueprintService, BlueprintService>();
services.AddScoped<CollectionRepository<BlueprintCollection>>();
//SQL
services.AddDbContext<SqlServerContext>(options => options.UseSqlServer(configuration.GetConnectionString("SQLServer")));
services.AddScoped<IUserProjectService, UserProjectService>();
//Storage
services.AddScoped<IBlobStorageService, BlobStorageService>();
//KeyVault
services.AddScoped<IKeyVaultService, KeyVaultService>();
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.DAL.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,103 @@
using Azure.Identity;
using Core.Blueprint.DAL.API.Extensions;
using Core.Blueprint.DAL.Mongo.Configuration;
using Core.Blueprint.KeyVault.Configuration;
using Core.Blueprint.Logging.Configuration;
using Core.Blueprint.Redis.Configuration;
using Core.Blueprint.SQLServer.Configuration;
using Core.Blueprint.Storage.Configuration;
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_dal");
options.ConfigureKeyVault(keyVaultOptions =>
{
keyVaultOptions.SetCredential(new DefaultAzureCredential());
});
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Configuration
.AddUserSecrets(Assembly.GetExecutingAssembly())
.AddEnvironmentVariables();
builder.Services.AddResponseCompression();
builder.Services.AddProblemDetails();
builder.Services.AddMemoryCache();
builder.Services.AddLogs(builder);
builder.Services.AddKeyVault(builder.Configuration);
builder.Services.AddBlobStorage(builder.Configuration);
builder.Services.AddRedis(builder.Configuration);
builder.Services.AddMongoLayer(builder.Configuration);
builder.Services.AddSQLServer(builder.Configuration);
builder.Services.AddDALLayerServices(builder.Configuration);
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:5013"
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Local"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7075;http://localhost:5013"
},
"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:13526",
"sslPort": 44366
}
}
}

View File

@@ -0,0 +1,11 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"CacheSettings": {
"DefaultCacheDurationInMinutes": 3
}
}

View File

@@ -0,0 +1,11 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"CacheSettings": {
"DefaultCacheDurationInMinutes": 3
}
}

View File

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