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

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,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"
}
}

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Configuration\**" />
<Compile Remove="Contracts\**" />
<Compile Remove="Jobs\**" />
<Compile Remove="Provider\**" />
<EmbeddedResource Remove="Configuration\**" />
<EmbeddedResource Remove="Contracts\**" />
<EmbeddedResource Remove="Jobs\**" />
<EmbeddedResource Remove="Provider\**" />
<None Remove="Configuration\**" />
<None Remove="Contracts\**" />
<None Remove="Jobs\**" />
<None Remove="Provider\**" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,75 @@
using Azure.Identity;
using Core.Blueprint.DAL.Infrastructure.Context;
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.DAL.Infrastructure.Proxies;
using Core.Blueprint.DAL.Infrastructure.Repository;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Reflection;
using Serilog;
using Serilog.Events;
using Serilog.Exceptions;
namespace Core.Blueprint.DAL.Infrastructure.Configure
{
public static class DependencyInjection
{
public static IServiceCollection RegisterInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
var chainedCredentials = new ChainedTokenCredential(
new ManagedIdentityCredential(),
new SharedTokenCacheCredential(),
new VisualStudioCredential(),
new VisualStudioCodeCredential()
);
services.AddAzureClients(cfg =>
{
cfg.AddBlobServiceClient(configuration.GetRequiredSection("Azure:BlobStorage")).WithCredential(chainedCredentials);
cfg.AddSecretClient(configuration.GetRequiredSection("Azure:KeyVault")).WithCredential(chainedCredentials);
});
services.AddDbContext<SqlServerContext>(options => options.UseSqlServer(configuration.GetConnectionString("SQLServerConnString")));
// LogFactory
services.ConfigureLogging();
//MongoDB
services.Configure<MongoDbSettings>(configuration.GetRequiredSection("MongoDbSettings"));
services.AddScoped<IMongoDbSettings>(serviceProvider =>
serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value);
services.AddScoped<IMongoContext, MongoContext>();
services.AddScoped(serviceProvider =>
{
var mongoContext = serviceProvider.GetRequiredService<IMongoContext>();
return mongoContext.Database;
});
services.AddScoped<IProxyBlobStorage, ProxyBlobStorage>();
services.AddScoped<ISampleImageRepository, SampleImageRepository>();
services.AddScoped<ISampleItemRepository, SampleItemRepository>();
services.AddScoped<IBlueprintRepository, BlueprintRepository>();
services.AddScoped<ISecretRepository, SecretRepository>();
return services;
}
public static void ConfigureLogging(this IServiceCollection services)
{
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithProcessId()
.Enrich.WithThreadId()
.Enrich.WithProperty("Application", Assembly.GetExecutingAssembly().GetName().Name)
.Enrich.WithExceptionDetails()
.MinimumLevel.Is(LogEventLevel.Information)
.WriteTo.Console()
.CreateLogger();
services.AddSingleton(Log.Logger);
}
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core.Blueprint.DAL.Infrastructure.Configure
{
class LoggerExtension
{
}
}

View File

@ -0,0 +1,135 @@
using Azure.Core;
using Azure.Identity;
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.Domain.Shared;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
using MongoDB.Driver.Authentication.Oidc;
using System.Reflection;
namespace Core.Blueprint.DAL.Infrastructure.Context
{
public interface IMongoDbSettings
{
string DatabaseName { get; set; }
string ConnectionString { get; set; }
}
public class MongoDbSettings : IMongoDbSettings
{
public string DatabaseName { get; set; }
public string ConnectionString { get; set; }
}
public class HeathOidcCallback : IOidcCallback
{
private readonly string _audience;
public HeathOidcCallback(string audience)
{
_audience = audience;
}
public OidcAccessToken GetOidcAccessToken(OidcCallbackParameters parameters, CancellationToken cancellationToken)
{
TokenRequestContext tokenRequestContext =
new TokenRequestContext(
new[] { _audience }
);
AccessToken token =
new ChainedTokenCredential(
new ManagedIdentityCredential(),
new SharedTokenCacheCredential(),
new VisualStudioCredential(),
new VisualStudioCodeCredential()
)
.GetToken(
tokenRequestContext
);
return new(token.Token, expiresIn: null);
}
public async Task<OidcAccessToken> GetOidcAccessTokenAsync(OidcCallbackParameters parameters, CancellationToken cancellationToken)
{
TokenRequestContext tokenRequestContext =
new TokenRequestContext(
new[] { _audience }
);
AccessToken token =
await new ChainedTokenCredential(
new ManagedIdentityCredential(),
new SharedTokenCacheCredential(),
new VisualStudioCredential(),
new VisualStudioCodeCredential()
)
.GetTokenAsync(
tokenRequestContext, cancellationToken
).ConfigureAwait(false);
return new(token.Token, expiresIn: null);
}
}
public sealed class MongoContext : IMongoContext
{
private IMongoDatabase _database;
public IMongoClient _client { get; private set; }
public IMongoDatabase Database { get { return _database; } }
public MongoUrl _mongoUrl { get; private set; }
//Constructors
public MongoContext(IConfiguration configuration)
{
var mongoClientSettings = MongoClientSettings.FromConnectionString(configuration.GetConnectionString("MongoDBConnString"));
mongoClientSettings.Credential = MongoCredential.CreateOidcCredential(new HeathOidcCallback(configuration.GetValue<string>("MongoDb:Audience")));
_database = new MongoClient(mongoClientSettings).GetDatabase(configuration.GetValue<string>("MongoDb:DatabaseName")); //Mongo Database
_client = Database.Client;
}
public MongoContext(string connectionString, string audience, string databaseName)
{
var mongoClientSettings = MongoClientSettings.FromConnectionString(connectionString);
mongoClientSettings.Credential = MongoCredential.CreateOidcCredential(new HeathOidcCallback(audience));
_client = new MongoClient(mongoClientSettings);
_database = _client.GetDatabase(databaseName);
}
public MongoContext(MongoClient client, string databaseName)
{
_client = client;
_database = client.GetDatabase(databaseName);
}
public void SetUpDatabase(string database)
{
_database = new MongoClient(_mongoUrl).GetDatabase(database);
_client = Database.Client;
}
//Methods
public void DropCollection<TDocument>(string? partitionKey = null) where TDocument : class
{
Database.DropCollection(GetCollectionName<TDocument>(partitionKey));
}
public IMongoCollection<T> GetCollection<T>(string collection)
{
return _database.GetCollection<T>(collection);
}
private string GetCollectionName<TDocument>(string partitionKey)
{
var collectionName = GetAttributeCollectionName<TDocument>();
if (string.IsNullOrEmpty(partitionKey))
{
return collectionName;
}
return $"{partitionKey}-{collectionName}";
}
private string? GetAttributeCollectionName<TDocument>()
{
return (typeof(TDocument).GetTypeInfo()
.GetCustomAttributes(typeof(CollectionAttributeName))
.FirstOrDefault() as CollectionAttributeName)?.Name;
}
}
}

View File

@ -0,0 +1,16 @@
using Core.Blueprint.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace Core.Blueprint.DAL.Infrastructure.Context
{
public sealed class SqlServerContext : DbContext
{
public SqlServerContext(DbContextOptions options) : base(options) { }
public DbSet<SampleItem> BlueprintTests { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<SampleItem>().Property(p => p.Id).HasConversion(a => a, b => b);
}
}
}

View File

@ -0,0 +1,9 @@
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface IBlueprintRepository : IRepositoryIdentityBase<BlueprintCollection>
{
}
}

View File

@ -0,0 +1,13 @@
using MongoDB.Driver;
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface IMongoContext
{
IMongoClient _client { get; }
IMongoDatabase Database { get; }
void DropCollection<TDocument>(string partitionKey = null) where TDocument : class;
void SetUpDatabase(string database);
}
}

View File

@ -0,0 +1,11 @@
using Core.Blueprint.Domain.Dtos;
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface IProxyBlobStorage
{
IAsyncEnumerable<ImageUrlDto> ListAllItemsAsync();
Task<ImageUrlDto> GetFirstImageUrlAsync();
Task<ImageUrlDto> GetUploadUrl();
}
}

View File

@ -0,0 +1,11 @@
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface IRepositoryBase<T> where T : class
{
ValueTask<T> GetByIdAsync(string id);
ValueTask<IQueryable<T>> GetAllAsync();
ValueTask<T> CreateAsync(T blueprint);
Task<bool> UpdateAsync(string id, T blueprint);
Task<bool> DeleteAsync(string id);
}
}

View File

@ -0,0 +1,9 @@
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface IRepositoryIdentityBase<T> : IRepositoryBase<T> where T : AbsEntity
{
ValueTask<T> GetByIdAsync(Guid id) => GetByIdAsync(id.ToString());
}
}

View File

@ -0,0 +1,11 @@
using Core.Blueprint.Domain.Dtos;
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface ISampleImageRepository
{
IAsyncEnumerable<ImageUrlDto> GetAllImagesUrls();
Task<ImageUrlDto> GetFirstImageUrl();
Task<ImageUrlDto> GetUploadUrl();
}
}

View File

@ -0,0 +1,8 @@
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface ISampleItemRepository : IRepositoryIdentityBase<SampleItem>
{
}
}

View File

@ -0,0 +1,11 @@
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Infrastructure.Contracts
{
public interface ISecretRepository
{
Task<Secret> GetSecret(string secretName, CancellationToken cancellationToken);
Task SetSecret(string secretName, string secretValue, CancellationToken cancellationToken);
Task RemoveSecret(string secretName, CancellationToken cancellationToken);
}
}

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.7.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.8.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.66.2" />
<PackageReference Include="MongoDB.Driver" Version="3.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Enrichers.Process" Version="3.0.0" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core.Blueprint.Domain\Core.Blueprint.Domain.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,95 @@
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Sas;
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.Domain.Dtos;
using Microsoft.Extensions.Azure;
using System.Reflection.Metadata;
namespace Core.Blueprint.DAL.Infrastructure.Proxies;
public class ProxyBlobStorage : IProxyBlobStorage
{
private readonly BlobServiceClient _blobServiceClient;
private readonly BlobContainerClient _blobContainerClient;
private const string TIMESTAMP_TAG_NAME = "Timestamp";
private UserDelegationKey _blobDelegationKey;
public ProxyBlobStorage(BlobServiceClient blobServiceClient)
{
_blobServiceClient = blobServiceClient;
_blobContainerClient = blobServiceClient.GetBlobContainerClient("blueprint");
_blobDelegationKey = _blobServiceClient.GetUserDelegationKey(DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddHours(2));
}
public async IAsyncEnumerable<ImageUrlDto> ListAllItemsAsync()
{
await using (var blobs = _blobContainerClient.GetBlobsAsync().GetAsyncEnumerator())
{
while (await blobs.MoveNextAsync())
{
yield return new ImageUrlDto
{
Url = _blobContainerClient.GenerateSasUri(BlobContainerSasPermissions.Read, DateTimeOffset.UtcNow.AddMinutes(5))
};
}
}
}
public async Task<ImageUrlDto> GetFirstImageUrlAsync()
{
await using (var blob = _blobContainerClient.GetBlobsAsync().GetAsyncEnumerator())
{
System.Console.WriteLine(_blobContainerClient.Uri.ToString());
await blob.MoveNextAsync();
var blobClient = _blobContainerClient.GetBlobClient(blob.Current.Name);
var sasBuilder = new BlobSasBuilder()
{
BlobContainerName = blobClient.BlobContainerName,
BlobName = blobClient.Name,
Resource = "b",
StartsOn = DateTimeOffset.UtcNow,
ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(5),
};
sasBuilder.SetPermissions(BlobAccountSasPermissions.Read);
var blobUriBuilder = new BlobUriBuilder(blobClient.Uri){
Sas = sasBuilder.ToSasQueryParameters(_blobDelegationKey, _blobServiceClient.AccountName)
};
var uri = blobUriBuilder.ToUri();
System.Console.WriteLine(uri);
return new ImageUrlDto { Url = uri };
}
}
public async Task<ImageUrlDto> GetUploadUrl()
{
await using (var blobs = _blobContainerClient.GetBlobsAsync().GetAsyncEnumerator())
{
await blobs.MoveNextAsync();
var blobClient = _blobContainerClient.GetBlobClient(blobs.Current.Name);
var sasBuilder = new BlobSasBuilder(){
BlobContainerName = blobClient.BlobContainerName,
BlobName = blobClient.Name,
Resource = "b",
StartsOn = DateTimeOffset.UtcNow,
ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(5),
};
sasBuilder.SetPermissions(BlobAccountSasPermissions.Read);
var blobUriBuilder = new BlobUriBuilder(blobClient.Uri){
Sas = sasBuilder.ToSasQueryParameters(_blobDelegationKey, _blobServiceClient.AccountName)
};
var uri = blobUriBuilder.ToUri();
return new ImageUrlDto { Url = uri };
}
}
}

View File

@ -0,0 +1,52 @@
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.Domain.Entities;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
namespace Core.Blueprint.DAL.Infrastructure.Repository
{
public sealed class BlueprintRepository: IBlueprintRepository
{
private readonly IMongoContext _context;
private readonly ILogger<BlueprintRepository> _logger;
private readonly IMongoCollection<BlueprintCollection> _collection;
public BlueprintRepository(IMongoContext context, IProxyBlobStorage blobProxy, ILogger<BlueprintRepository> logger)
{
_context = context;
_logger = logger;
_collection = _context.Database.GetCollection<BlueprintCollection>("Blueprints");
}
public async ValueTask<BlueprintCollection> GetByIdAsync(string id)
{
var result = await _collection.FindAsync(b => b.Id == id);
return result.First();
}
async ValueTask<IQueryable<BlueprintCollection>> IRepositoryBase<BlueprintCollection>.GetAllAsync()
{
var result = await _collection.FindAsync(_ => true);
return (await result.ToListAsync()).AsQueryable();
}
async ValueTask<BlueprintCollection> IRepositoryBase<BlueprintCollection>.CreateAsync(BlueprintCollection blueprint)
{
blueprint.Id = null;
await _collection.InsertOneAsync(blueprint);
return blueprint;
}
public async Task<bool> UpdateAsync(string id, BlueprintCollection blueprint)
{
var result = await _collection.ReplaceOneAsync(b => b.Id == id, blueprint);
return result.IsAcknowledged && result.ModifiedCount > 0;
}
public async Task<bool> DeleteAsync(string id)
{
var result = await _collection.DeleteOneAsync(b => b.Id == id);
return result.IsAcknowledged && result.DeletedCount > 0;
}
}
}

View File

@ -0,0 +1,54 @@
using Core.Blueprint.DAL.Infrastructure.Context;
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Infrastructure.Repository
{
public abstract class RepositorySqlBase<T> : IRepositoryIdentityBase<T> where T: AbsEntity
{
protected SqlServerContext _dbContext;
protected RepositorySqlBase(SqlServerContext dbContext)
{
_dbContext = dbContext;
}
public async ValueTask<T> CreateAsync(T blueprint)
{
blueprint.Id = Guid.NewGuid().ToString();
_dbContext.Add(blueprint);
await _dbContext.SaveChangesAsync();
return blueprint;
}
public async Task<bool> DeleteAsync(string id)
{
var item = await GetByIdAsync(id);
if (item == null)
{
return false;
}
_dbContext.Remove(item);
await _dbContext.SaveChangesAsync();
return true;
}
public async ValueTask<IQueryable<T>> GetAllAsync()
{
return _dbContext.Set<T>();
}
public async ValueTask<T> GetByIdAsync(string id)
{
var result = await _dbContext.FindAsync<T>(id);
return result;
}
public async Task<bool> UpdateAsync(string id, T entity)
{
_dbContext.Update(entity);
await _dbContext.SaveChangesAsync();
return true;
}
}
}

View File

@ -0,0 +1,33 @@
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.Domain.Dtos;
namespace Core.Blueprint.DAL.Infrastructure.Repository
{
public class SampleImageRepository : ISampleImageRepository
{
private readonly IProxyBlobStorage _proxyBlobStorage;
public SampleImageRepository(IProxyBlobStorage proxyBlobStorage)
{
_proxyBlobStorage = proxyBlobStorage;
}
public async IAsyncEnumerable<ImageUrlDto> GetAllImagesUrls()
{
await using (var images = _proxyBlobStorage.ListAllItemsAsync().GetAsyncEnumerator())
{
await images.MoveNextAsync();
yield return images.Current;
}
}
public async Task<ImageUrlDto> GetFirstImageUrl()
{
return await _proxyBlobStorage.GetFirstImageUrlAsync();
}
public async Task<ImageUrlDto> GetUploadUrl()
{
return await _proxyBlobStorage.GetUploadUrl();
}
}
}

View File

@ -0,0 +1,16 @@
using Core.Blueprint.DAL.Infrastructure.Context;
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.Domain.Entities;
using Microsoft.Extensions.Logging;
namespace Core.Blueprint.DAL.Infrastructure.Repository
{
public class SampleItemRepository : RepositorySqlBase<SampleItem>, ISampleItemRepository
{
private readonly ILogger<SampleItemRepository> _logger;
public SampleItemRepository(SqlServerContext dbContext, ILogger<SampleItemRepository> logger) : base(dbContext)
{
_logger = logger;
}
}
}

View File

@ -0,0 +1,41 @@
using Azure.Security.KeyVault.Secrets;
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core.Blueprint.DAL.Infrastructure.Repository
{
public class SecretRepository : ISecretRepository
{
private readonly SecretClient _client;
public SecretRepository(SecretClient client)
{
_client = client;
}
public async Task<Secret> GetSecret(string secretName, CancellationToken cancellationToken)
{
var ret = await _client.GetSecretAsync(secretName, cancellationToken: cancellationToken);
return new Secret() { Value = ret.Value?.Value };
}
public async Task SetSecret(string secretName, string secretValue, CancellationToken cancellationToken)
{
await _client.SetSecretAsync(new KeyVaultSecret(secretName, secretValue), cancellationToken: cancellationToken);
}
public async Task RemoveSecret(string secretName, CancellationToken cancellationToken)
{
await _client.StartDeleteSecretAsync(secretName, cancellationToken: cancellationToken);
}
}
}

View File

@ -0,0 +1,12 @@
using Core.Blueprint.KeyVault;
namespace Core.Blueprint.DAL.KeyVault.Contracts
{
public interface IKeyVaultService
{
Task<KeyVaultResponse> CreateSecretAsync(KeyVaultRequest secret, CancellationToken cancellationToken);
Task<Tuple<KeyVaultResponse, string?>> GetSecretAsync(string secret, CancellationToken cancellationToken);
Task<Tuple<string, bool>> DeleteSecretAsync(string secretName, CancellationToken cancellationToken);
Task<Tuple<KeyVaultResponse, string>> UpdateSecretAsync(KeyVaultRequest secretName, CancellationToken cancellationToken);
}
}

View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.7.0" />
<PackageReference Include="Core.Blueprint.KeyVault" Version="0.3.0-alpha0037" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,31 @@
using Core.Blueprint.DAL.KeyVault.Contracts;
using Core.Blueprint.KeyVault;
namespace Core.Blueprint.DAL.KeyVault.Services
{
public class KeyVaultService(IKeyVaultProvider keyVaultProvider) : IKeyVaultService
{
public async Task<KeyVaultResponse> CreateSecretAsync(KeyVaultRequest newSecret, CancellationToken cancellationToken)
{
var result = await keyVaultProvider.CreateSecretAsync(newSecret, cancellationToken);
return result;
}
public async Task<Tuple<KeyVaultResponse, string?>> GetSecretAsync(string secretName, CancellationToken cancellationToken)
{
var result = await keyVaultProvider.GetSecretAsync(secretName, cancellationToken: cancellationToken);
return result;
}
public async Task<Tuple<KeyVaultResponse, string>> UpdateSecretAsync(KeyVaultRequest newSecret, CancellationToken cancellationToken)
{
var result = await keyVaultProvider.UpdateSecretAsync(newSecret, cancellationToken);
return result;
}
public async Task<Tuple<string, bool>> DeleteSecretAsync(string secretName, CancellationToken cancellationToken)
{
var result = await keyVaultProvider.DeleteSecretAsync(secretName, cancellationToken);
return result;
}
}
}

View File

@ -0,0 +1,50 @@
using Core.Blueprint.DAL.Logs.Contracts;
using Serilog;
namespace Core.Blueprint.DAL.Logs
{
public class BlueprintSerilogLogger : IBlueprintSerilogLogger
{
private readonly ILogger logger;
public BlueprintSerilogLogger(ILogger logger)
{
this.logger = logger;
}
public void LogInformation(string service, params object[] args)
{
logger.Information("Starting operation in {service} service", service, args);
}
public void LogOperationStarted(string service, params object[] args)
{
logger.Information("Starting operation in {Service} service with parameters: {@Args}", service, args);
}
public void LogOperationFinished(string service, params object[] args)
{
logger.Information("Finishing operation in {Service} service with parameters: {@Args}", service, args);
}
public void LogInformation(string message)
{
logger.Information(message);
}
public void LogWarning(string message, params object[] args)
{
logger.Warning(message, args);
}
public void LogError(string service, params object[] args)
{
logger.Error("An error occurred in `{service}` Exception: {@Args}", service, args);
}
public void LogCritical(Exception exception, string message, params object[] args)
{
logger.Fatal(exception, message, args);
}
}
}

View File

@ -0,0 +1,15 @@
using Core.Blueprint.DAL.Logs.Contracts;
using Microsoft.Extensions.DependencyInjection;
namespace Core.Blueprint.DAL.Logs.Configuration
{
public static class LogExtensionConfiguration
{
public static IServiceCollection AddLogLayer(this IServiceCollection services)
{
services.AddScoped<IBlueprintSerilogLogger, BlueprintSerilogLogger>();
return services;
}
}
}

View File

@ -0,0 +1,9 @@
namespace Core.Blueprint.DAL.Logs.Contracts
{
public interface IBlueprintLogger<T> where T : class, new()
{
//logger
//serilog...
//patterns of structuie logging
}
}

View File

@ -0,0 +1,12 @@
namespace Core.Blueprint.DAL.Logs.Contracts
{
public interface IBlueprintSerilogLogger
{
public void LogInformation(string service, params object[] args);
public void LogOperationStarted(string service, params object[] args);
public void LogOperationFinished(string service, params object[] args);
public void LogWarning(string message, params object[] args);
public void LogError(string servicee, params object[] args);
public void LogCritical(Exception exception, string message, params object[] args);
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Serilog" Version="4.2.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,24 @@
namespace Core.Blueprint.DAL.Logs;
public static partial class Log
{
//[LoggerMessage(
// EventId = 1,
// Level = LogLevel.Information,
// Message = "Starting operation in`{service}` service with parameters: {@Args}"
//)]
//static partial void OperationStarted(ILogger logger, string service, params object[] args);
//[LoggerMessage(
// EventId = 1,
// Level = LogLevel.Information,
// Message = "Operation finished in`{service}` service with parameters: {@Args}"
//)]
//static partial void OperationFinished(ILogger logger, string service, params object[] args);
//[LoggerMessage(
// EventId = 2,
// Level = LogLevel.Error,
// Message = "An error occurred in `{service}` service"
//)]
//static partial void OperationFailed(ILogger logger, string service, Exception exception);
}

View File

@ -0,0 +1,18 @@
using Core.Blueprint.DAL.Mongo.Entities.Collections;
using Core.Blueprint.DAL.Mongo.Entities.Requests;
namespace Core.Blueprint.DAL.Mongo.Contracts
{
public interface IBlueprintService
{
ValueTask<BlueprintCollection> CreateBlueprint(BlueprintRequest newBlueprint, CancellationToken cancellationToken);
ValueTask<BlueprintCollection> GetBlueprintById(string _id, CancellationToken cancellationToken);
ValueTask<IEnumerable<BlueprintCollection>> GetAllBlueprints(CancellationToken cancellationToken);
ValueTask<BlueprintCollection> UpdateBlueprint(string _id, BlueprintCollection entity, CancellationToken cancellationToken);
ValueTask<BlueprintCollection> DeleteBlueprint(string _id, CancellationToken cancellationToken);
}
}

View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Core.Blueprint.Mongo" Version="0.3.0-alpha0047" />
<PackageReference Include="Core.Blueprint.Redis" Version="0.3.0-alpha0032" />
<PackageReference Include="Mapster" Version="7.4.1-pre01" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.0" />
<PackageReference Include="MongoDB.Driver" Version="3.1.0" />
<PackageReference Include="Serilog" Version="4.2.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,11 @@
using Core.Blueprint.Mongo;
namespace Core.Blueprint.DAL.Mongo.Entities.Collections
{
[CollectionAttributeName("Blueprints")]
public class BlueprintCollection : Document
{
public string Name { get; set; } = null!;
public string? Description { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace Core.Blueprint.DAL.Mongo.Entities.Requests
{
public class BlueprintRequest
{
public string Name { get; set; } = null!;
public string? Description { get; set; }
}
}

View File

@ -0,0 +1,80 @@
using Core.Blueprint.DAL.Mongo.Contracts;
using Core.Blueprint.DAL.Mongo.Entities.Collections;
using Core.Blueprint.DAL.Mongo.Entities.Requests;
using Core.Blueprint.Mongo;
using Core.Blueprint.Redis;
using Core.Blueprint.Redis.Helpers;
using Mapster;
using Microsoft.Extensions.Options;
namespace Core.Blueprint.DAL.Mongo.Service
{
public class BlueprintService : IBlueprintService
{
private readonly CollectionRepository<BlueprintCollection> repository;
private readonly CacheSettings cacheSettings;
private readonly IRedisCacheProvider cacheProvider;
public BlueprintService(CollectionRepository<BlueprintCollection> repository,
IRedisCacheProvider cacheProvider, IOptions<CacheSettings> cacheSettings)
{
this.repository = repository;
this.repository.CollectionInitialization();
this.cacheSettings = cacheSettings.Value;
this.cacheProvider = cacheProvider;
}
public async ValueTask<BlueprintCollection> CreateBlueprint(BlueprintRequest newBlueprint, CancellationToken cancellationToken)
{
var blueprintCollection = newBlueprint.Adapt<BlueprintCollection>();
await this.repository.InsertOneAsync(blueprintCollection);
return blueprintCollection;
}
public async ValueTask<BlueprintCollection> GetBlueprintById(string _id, CancellationToken cancellationToken)
{
var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetBlueprintById", _id);
var cachedData = await cacheProvider.GetAsync<BlueprintCollection>(cacheKey);
if (cachedData is not null) { return cachedData; }
var blueprint = await this.repository.FindByIdAsync(_id);
await cacheProvider.SetAsync(cacheKey, blueprint);
return blueprint;
}
public async ValueTask<IEnumerable<BlueprintCollection>> GetAllBlueprints(CancellationToken cancellationToken)
{
var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllBlueprints");
var cachedData = await cacheProvider.GetAsync<IEnumerable<BlueprintCollection>>(cacheKey) ?? [];
if (cachedData.Any()) return cachedData;
var blueprints = await this.repository.AsQueryable();
await cacheProvider.SetAsync(cacheKey, blueprints);
return blueprints;
}
public async ValueTask<BlueprintCollection> UpdateBlueprint(string _id, BlueprintCollection entity, CancellationToken cancellationToken)
{
await this.repository.ReplaceOneAsync(entity);
return entity;
}
public async ValueTask<BlueprintCollection> DeleteBlueprint(string _id, CancellationToken cancellationToken)
{
var entity = await this.repository.DeleteOneAsync(doc => doc._Id == _id);
return entity;
}
}
}

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,134 @@
using Azure.Identity;
using Core.Blueprint.DAL.Redis.Contracts;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
using System.Text.Json;
namespace Core.Blueprint.DAL.Redis
{
public class CacheService : ICacheService
{
private IDatabase _cacheDatabase = null!;
private readonly ILogger<CacheService> _logger;
public CacheService(string connectionString, ILogger<CacheService> logger)
{
_logger = logger;
Task.Run(async () =>
{
_cacheDatabase = await GetRedisDatabase(connectionString);
}).Wait();
}
private async Task<IDatabase> GetRedisDatabase(string connectionString)
{
try
{
var configurationOptions = await ConfigurationOptions.Parse($"{connectionString}")
.ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential());
configurationOptions.AbortOnConnectFail = false;
var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions);
_logger.LogInformation("Successfully connected to Redis.");
return connectionMultiplexer.GetDatabase();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error establishing Redis connection.");
throw;
}
}
public async Task<T> GetAsync<T>(string key)
{
try
{
var value = await _cacheDatabase.StringGetAsync(key);
if (value.IsNullOrEmpty)
{
_logger.LogInformation($"Cache miss for key: {key}");
return default;
}
_logger.LogInformation($"Cache hit for key: {key}");
return JsonSerializer.Deserialize<T>(value);
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error getting cache item with key {key}");
throw;
}
}
public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
{
try
{
var json = JsonSerializer.Serialize(value);
await _cacheDatabase.StringSetAsync(key, json, expiry);
_logger.LogInformation($"Cache item set with key: {key}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error setting cache item with key {key}");
throw;
}
}
public async Task RemoveAsync(string key)
{
try
{
await _cacheDatabase.KeyDeleteAsync(key);
_logger.LogInformation($"Cache item removed with key: {key}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error removing cache item with key {key}");
throw;
}
}
public async Task<bool> ExistsAsync(string key)
{
try
{
var exists = await _cacheDatabase.KeyExistsAsync(key);
_logger.LogInformation($"Cache item exists check for key: {key} - {exists}");
return exists;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error checking existence of cache item with key {key}");
throw;
}
}
public async Task RefreshAsync(string key, TimeSpan? expiry = null)
{
try
{
var value = await _cacheDatabase.StringGetAsync(key);
if (!value.IsNullOrEmpty)
{
await _cacheDatabase.StringSetAsync(key, value, expiry);
_logger.LogInformation($"Cache item refreshed with key: {key}");
}
else
{
_logger.LogWarning($"Cache item with key: {key} does not exist, cannot refresh");
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error refreshing cache item with key {key}");
throw;
}
}
}
}

View File

@ -0,0 +1,7 @@
namespace Core.Blueprint.DAL.Redis.Configuration
{
public class CacheSettings
{
public int DefaultCacheDurationInMinutes { get; set; }
}
}

View File

@ -0,0 +1,27 @@
using Core.Blueprint.DAL.Redis.Contracts;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Core.Blueprint.DAL.Redis.Configuration
{
public static class RedisExtension
{
public static IServiceCollection AddRedisLayer(this IServiceCollection services, IConfiguration configuration)
{
var source = configuration.GetSection("ConnectionStrings");
var redisConnectionString = source["Redis"]?.ToString();
if (string.IsNullOrEmpty(redisConnectionString))
{
throw new InvalidOperationException("Redis connection string is not configured.");
}
services.AddSingleton<ICacheService>(provider =>
new CacheService(redisConnectionString, provider.GetRequiredService<ILogger<CacheService>>()));
return services;
}
}
}

View File

@ -0,0 +1,11 @@
namespace Core.Blueprint.DAL.Redis.Contracts
{
public interface ICacheService
{
Task<T> GetAsync<T>(string key);
Task SetAsync<T>(string key, T value, TimeSpan? expiry = null);
Task RemoveAsync(string key);
Task<bool> ExistsAsync(string key);
Task RefreshAsync(string key, TimeSpan? expiry = null);
}
}

View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Microsoft.Azure.StackExchangeRedis" Version="3.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.24" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,30 @@
using Core.Blueprint.DAL.Redis.Configuration;
namespace Core.Blueprint.DAL.Redis.Helpers
{
public static class CacheHelper
{
/// <summary>
/// Determines the cache duration based on specific duration, settings, or a default value.
/// </summary>
/// <param name="specificCacheDuration">Specific cache duration in minutes, if provided.</param>
/// <param name="cacheSettings">General cache settings containing default duration values.</param>
/// <returns>The cache duration as a TimeSpan.</returns>
public static TimeSpan GetCacheDuration(CacheSettings cacheSettings, int? specificCacheDuration = 0)
{
var defaultCacheDuration = TimeSpan.FromMinutes(.5);
if (specificCacheDuration.HasValue && specificCacheDuration.Value > 0)
{
return TimeSpan.FromMinutes(specificCacheDuration.Value);
}
if (cacheSettings.DefaultCacheDurationInMinutes > 0)
{
return TimeSpan.FromMinutes(cacheSettings.DefaultCacheDurationInMinutes);
}
return defaultCacheDuration;
}
}
}

View File

@ -0,0 +1,46 @@
using System.Text;
using System.Text.RegularExpressions;
namespace Core.Blueprint.DAL.Redis.Helpers
{
public static class CacheKeyHelper
{
public static string GenerateCacheKey(object instance, string methodName, params object[] parameters)
{
var className = instance.GetType().Name;
var keyBuilder = new StringBuilder($"{className}.{methodName}");
foreach (var param in parameters)
{
string normalizedParam = NormalizeParameter(param);
keyBuilder.Append($".{normalizedParam}");
}
return keyBuilder.ToString();
}
private static string NormalizeParameter(object param)
{
if (param == null)
{
return "null";
}
string paramString;
if (param is DateTime dateTime)
{
paramString = dateTime.ToString("yyyyMMdd");
}
else
{
paramString = param.ToString();
}
// Replace special characters with an underscore
string normalizedParam = Regex.Replace(paramString, @"[^a-zA-Z0-9]", "_");
return normalizedParam;
}
}
}

View File

@ -0,0 +1,25 @@
using Core.Blueprint.DAL.SQLServer.Entities;
using Core.Blueprint.SQLServer.Entities;
using Microsoft.EntityFrameworkCore;
namespace Core.Blueprint.DAL.SQLServer.Context
{
public sealed class SqlServerContext : DbContext
{
public SqlServerContext(DbContextOptions<SqlServerContext> options) : base(options) { }
public DbSet<UserProject> UserProjects { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes()
.Where(t => typeof(BaseSQLAdapter).IsAssignableFrom(t.ClrType)))
{
modelBuilder.Entity(entityType.ClrType)
.HasKey("Id");
modelBuilder.Entity(entityType.ClrType).Property("Status")
.HasConversion<string>();
}
}
}
}

View File

@ -0,0 +1,19 @@
using Core.Blueprint.DAL.SQLServer.Entities;
using Core.Blueprint.DAL.SQLServer.Entities.Request;
namespace Core.Blueprint.DAL.SQLServer.Contracts
{
public interface IUserProjectService
{
Task<IEnumerable<UserProject>> GetAllUserProjects();
Task<UserProject?> GetUserProjectById(int id);
Task<UserProject> AddUserProject(UserProjectRequest newUserProject);
Task<UserProject?> UpdateUserProject(UserProject userProject);
Task<UserProject?> DeleteUserProject(int id);
}
}

View File

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Core.Blueprint.Redis" Version="0.3.0-alpha0032" />
<PackageReference Include="Core.Blueprint.SQLServer" Version="0.3.0-alpha0030" />
<PackageReference Include="Mapster" Version="7.4.1-pre01" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
namespace Core.Blueprint.DAL.SQLServer.Entities.Request
{
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,13 @@
using Core.Blueprint.SQLServer.Entities;
using System.ComponentModel.DataAnnotations.Schema;
namespace Core.Blueprint.DAL.SQLServer.Entities
{
[Table("UserProjects")]
public class UserProject : BaseSQLAdapter
{
public string ProjectCode { get; set; } = null!;
public string ProjectDescription { get; set; } = null!;
public string UserId { get; set; } = null!;
}
}

View File

@ -0,0 +1,82 @@
using Core.Blueprint.DAL.SQLServer;
using Core.Blueprint.DAL.SQLServer.Context;
using Core.Blueprint.DAL.SQLServer.Contracts;
using Core.Blueprint.DAL.SQLServer.Entities;
using Core.Blueprint.DAL.SQLServer.Entities.Request;
using Core.Blueprint.Redis;
using Core.Blueprint.Redis.Helpers;
using Mapster;
using Microsoft.Extensions.Options;
public class UserProjectService : IUserProjectService
{
private readonly IEntityRepository<UserProject, SqlServerContext> _userProjectRepository;
private readonly CacheSettings cacheSettings;
private readonly IRedisCacheProvider cacheProvider;
public UserProjectService(IEntityRepository<UserProject, SqlServerContext> userProjectRepository, IRedisCacheProvider cacheProvider, IOptions<CacheSettings> cacheSettings)
{
_userProjectRepository = userProjectRepository;
this.cacheSettings = cacheSettings.Value;
this.cacheProvider = cacheProvider;
}
public async Task<IEnumerable<UserProject>> GetAllUserProjects()
{
var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllUserProjects");
var cachedData = await cacheProvider.GetAsync<IEnumerable<UserProject>>(cacheKey) ?? [];
if (cachedData.Any()) return cachedData;
var userProjects = await _userProjectRepository.GetAllAsync();
await cacheProvider.SetAsync(cacheKey, userProjects);
return userProjects;
}
public async Task<UserProject?> GetUserProjectById(int id)
{
var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserProjectById", id);
var cachedData = await cacheProvider.GetAsync<UserProject>(cacheKey);
if (cachedData is not null) { return cachedData; }
var userProject = await _userProjectRepository.GetByIdAsync(id);
await cacheProvider.SetAsync(cacheKey, userProject);
return userProject;
}
public async Task<UserProject> AddUserProject(UserProjectRequest newUserProject)
{
var userProject = newUserProject.Adapt<UserProject>();
await _userProjectRepository.AddAsync(userProject);
await _userProjectRepository.SaveAsync();
return userProject;
}
public async Task<UserProject?> UpdateUserProject(UserProject userProject)
{
var existingEntity = await _userProjectRepository.GetByIdAsync(userProject.Id);
if (existingEntity is null) return existingEntity;
_userProjectRepository.Update(userProject);
await _userProjectRepository.SaveAsync();
return userProject;
}
public async Task<UserProject?> DeleteUserProject(int id)
{
var userProject = await _userProjectRepository.GetByIdAsync(id);
if (userProject == null)
return null;
_userProjectRepository.Delete(userProject);
await _userProjectRepository.SaveAsync();
return userProject;
}
}

View File

@ -0,0 +1,125 @@
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.DAL.Service.Contracts;
using Core.Blueprint.Domain.Entities;
using Microsoft.AspNetCore.Http.HttpResults;
using Serilog;
namespace Core.Blueprint.DAL.Service
{
public class BlueprintService : IBlueprintService
{
private readonly ILogger _logger;
private readonly IRepositoryIdentityBase<BlueprintCollection> _repository;
public BlueprintService(IBlueprintRepository repository, ILogger logger)
{
_repository = repository;
_logger = logger;
}
public virtual async ValueTask<BlueprintCollection> CreateAsync(BlueprintCollection entity)
{
try
{
_logger.Information("Start to create the BluePrintCollection | Method: {method} | Class: {class}", nameof(CreateAsync), nameof(BlueprintService));
var ret = await _repository.CreateAsync(entity);
_logger.Information("The blueprint collection was created | Method: {method} | Class: {class}", nameof(CreateAsync), nameof(BlueprintService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(CreateAsync), nameof(BlueprintService));
return default;
}
}
public virtual async ValueTask<bool> DeleteAsync(string id)
{
try
{
_logger.Information("Start to delete BluePrintCollection | Method: {method} | Class: {class}", nameof(DeleteAsync), nameof(BlueprintService));
var ret = await _repository.DeleteAsync(id);
_logger.Information("The blueprintcollection delete Finished | Method: {method} | Class: {class}", nameof(DeleteAsync), nameof(BlueprintService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(DeleteAsync), nameof(BlueprintService));
return default;
}
}
public virtual async ValueTask<IEnumerable<BlueprintCollection>> GetAllAsync()
{
try
{
_logger.Information("Start to get the BluePrintCollection list | Method: {method} | Class: {class}", nameof(GetAllAsync), nameof(BlueprintService));
var ret = await _repository.GetAllAsync();
_logger.Information("The get blueprintcollection list Finished | Method: {method} | Class: {class}", nameof(GetAllAsync), nameof(BlueprintService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetAllAsync), nameof(BlueprintService));
return default;
}
}
public virtual async ValueTask<BlueprintCollection> GetByIdAsync(string id)
{
try
{
_logger.Information("Start to get a sigle BluePrintCollection | Method: {method} | Class: {class}", nameof(GetByIdAsync), nameof(BlueprintService));
var ret = await _repository.GetByIdAsync(id);
_logger.Information("The single blueprintcollection got | Method: {method} | Class: {class}", nameof(GetByIdAsync), nameof(BlueprintService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetByIdAsync), nameof(BlueprintService));
return default;
}
}
public virtual async Task<bool> UpdateAsync(string id, BlueprintCollection entity)
{
try
{
_logger.Information("Start to update BluePrintCollection | Method: {method} | Class: {class}", nameof(UpdateAsync), nameof(BlueprintService));
var ret = await _repository.UpdateAsync(id, entity);
_logger.Information("The blueprintcollection update Finished | Method: {method} | Class: {class}", nameof(UpdateAsync), nameof(BlueprintService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(UpdateAsync), nameof(BlueprintService));
return default;
}
}
}
}

View File

@ -0,0 +1,22 @@
using Core.Blueprint.DAL.Infrastructure.Configure;
using Core.Blueprint.DAL.Service.Contracts;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Core.Blueprint.DAL.Service.Configure
{
public static class DependencyInjection
{
public static IServiceCollection RegisterServices(this IServiceCollection services, IConfiguration configuration)
{
services.RegisterInfrastructure(configuration);
services.AddScoped<IBlueprintService, BlueprintService>();
services.AddScoped<ISampleItemService, SampleItemService>();
services.AddScoped<ISampleImageService, SampleImageService>();
services.AddScoped<ISecretService, SecretService>();
return services;
}
}
}

View File

@ -0,0 +1,13 @@
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Service.Contracts
{
public interface IBlueprintService
{
ValueTask<BlueprintCollection> CreateAsync(BlueprintCollection entity);
ValueTask<bool> DeleteAsync(string id);
ValueTask<IEnumerable<BlueprintCollection>> GetAllAsync();
ValueTask<BlueprintCollection> GetByIdAsync(string id);
Task<bool> UpdateAsync(string id, BlueprintCollection entity);
}
}

View File

@ -0,0 +1,11 @@
using Core.Blueprint.Domain.Dtos;
namespace Core.Blueprint.DAL.Service.Contracts
{
public interface ISampleImageService
{
IAsyncEnumerable<ImageUrlDto> GetAllUrl();
Task<ImageUrlDto> GetFirstUrl();
Task<ImageUrlDto> GetUploadUrl();
}
}

View File

@ -0,0 +1,14 @@
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Service.Contracts
{
public interface ISampleItemService
{
ValueTask<SampleItem> CreateAsync(SampleItem entity);
ValueTask<bool> DeleteAsync(string id);
ValueTask<IEnumerable<SampleItem>> GetAllAsync();
ValueTask<SampleItem> GetByIdAsync(string id);
Task<bool> UpdateAsync(string id, SampleItem entity);
}
}

View File

@ -0,0 +1,11 @@
using Core.Blueprint.Domain.Entities;
namespace Core.Blueprint.DAL.Service.Contracts
{
public interface ISecretService
{
Task<Secret> GetSecret(string secretName, CancellationToken cancellationToken);
Task SetSecret(string secretName, string secretValue, CancellationToken cancellationToken);
Task RemoveSecret(string secretName, CancellationToken cancellationToken);
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Core.Blueprint.DAL.Infrastrcture\Core.Blueprint.DAL.Infrastructure.csproj" />
<ProjectReference Include="..\Core.Blueprint.Domain\Core.Blueprint.Domain.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,74 @@
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.DAL.Service.Contracts;
using Core.Blueprint.Domain.Dtos;
using Serilog;
namespace Core.Blueprint.DAL.Service
{
public class SampleImageService : ISampleImageService
{
private readonly ISampleImageRepository _sampleImageRepository;
private readonly ILogger _logger;
public SampleImageService(ISampleImageRepository sampleImageRepository, ILogger logger)
{
_sampleImageRepository = sampleImageRepository;
_logger = logger;
}
public IAsyncEnumerable<ImageUrlDto> GetAllUrl()
{
try
{
_logger.Information("Starting to get the images urls list | Method: {method} | Class: {class}", nameof(GetAllUrl), nameof(SampleImageService));
var ret = _sampleImageRepository.GetAllImagesUrls();
_logger.Information("Finishing to get the images urls list | Method: {method} | Class: {class}", nameof(GetAllUrl), nameof(SampleImageService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetAllUrl), nameof(SampleImageService));
return default;
}
}
public async Task<ImageUrlDto> GetFirstUrl()
{
try
{
_logger.Information("Starting to get the first image url | Method: {method} | Class: {class}", nameof(GetFirstUrl), nameof(SampleImageService));
var ret = await _sampleImageRepository.GetFirstImageUrl();
_logger.Information("Finishing to get the first image url | Method: {method} | Class: {class}", nameof(GetFirstUrl), nameof(SampleImageService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetFirstUrl), nameof(SampleImageService));
return default;
}
}
public async Task<ImageUrlDto> GetUploadUrl()
{
try
{
_logger.Information("Starting to get the upload image url | Method: {method} | Class: {class}", nameof(GetUploadUrl), nameof(SampleImageService));
var ret = await _sampleImageRepository.GetUploadUrl();
_logger.Information("Finishing to get the upload image url | Method: {method} | Class: {class}", nameof(GetUploadUrl), nameof(SampleImageService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetUploadUrl), nameof(SampleImageService));
return default;
}
}
}
}

View File

@ -0,0 +1,114 @@
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.DAL.Service.Contracts;
using Core.Blueprint.Domain.Entities;
using Serilog;
namespace Core.Blueprint.DAL.Service
{
//[LoggingAttribute]
public class SampleItemService : ISampleItemService
{
private readonly ILogger _logger;
private readonly IRepositoryIdentityBase<SampleItem> _repository;
public SampleItemService(ISampleItemRepository repository, ILogger logger)
{
_repository = repository;
_logger = logger;
}
//[LoggingAttribute] //Time of request, class name, class method... memory usage....
public virtual async ValueTask<SampleItem> CreateAsync(SampleItem entity)
{
try
{
_logger.Information("Starting to create the Sample item");
var ret = await _repository.CreateAsync(entity);
_logger.Information("Finishing to create the Sample item | Method: {method} | Class: {class}", nameof(CreateAsync), nameof(SampleItemService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(CreateAsync), nameof(SampleItemService));
return default;
}
}
public virtual async ValueTask<bool> DeleteAsync(string id)
{
try
{
_logger.Information("Starting to delete the Sample item | Method: {method} | Class: {class}", nameof(DeleteAsync), nameof(SampleItemService));
var ret = await _repository.DeleteAsync(id);
_logger.Information("Finishing to delete the Sample item | Method: {method} | Class: {class}", nameof(DeleteAsync), nameof(SampleItemService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(DeleteAsync), nameof(SampleItemService));
return default;
}
}
public virtual async ValueTask<IEnumerable<SampleItem>> GetAllAsync()
{
try
{
_logger.Information("Starting to get all Sample item | Method: {method} | Class: {class}", nameof(GetAllAsync), nameof(SampleItemService));
var ret = await _repository.GetAllAsync();
_logger.Information("Finishing to get all Sample item | Method: {method} | Class: {class}", nameof(GetAllAsync), nameof(SampleItemService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetAllAsync), nameof(SampleItemService));
return default;
}
}
public virtual async ValueTask<SampleItem> GetByIdAsync(string id)
{
try
{
_logger.Information("Starting to get Sample item by id | Method: {method} | Class: {class}", nameof(GetByIdAsync), nameof(SampleItemService));
var ret = await _repository.GetByIdAsync(id);
_logger.Information("Finishing to get all Sample item | Method: {method} | Class: {class}", nameof(GetByIdAsync), nameof(SampleItemService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetByIdAsync), nameof(SampleItemService));
return default;
}
}
public virtual async Task<bool> UpdateAsync(string id, SampleItem entity)
{
try
{
_logger.Information("Starting to update Sample item | Method: {method} | Class: {class}", nameof(UpdateAsync), nameof(SampleItemService));
var ret = await _repository.UpdateAsync(id, entity);
_logger.Information("Finishing to update Sample item | Method: {method} | Class: {class}", nameof(UpdateAsync), nameof(SampleItemService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(UpdateAsync), nameof(SampleItemService));
return default;
}
}
}
}

View File

@ -0,0 +1,76 @@
using Core.Blueprint.DAL.Infrastructure.Contracts;
using Core.Blueprint.DAL.Service.Contracts;
using Core.Blueprint.Domain.Entities;
using Serilog;
using SharpCompress.Common;
namespace Core.Blueprint.DAL.Service
{
public class SecretService : ISecretService
{
private readonly ISecretRepository _repository;
private readonly ILogger _logger;
public SecretService(ISecretRepository repository, ILogger logger)
{
_repository = repository;
_logger = logger;
}
public async Task<Secret> GetSecret(string secretName, CancellationToken cancellationToken)
{
try
{
_logger.Information("Starting to get the secret | Method: {method} | Class: {class}", nameof(GetSecret), nameof(SecretService));
var ret = await _repository.GetSecret(secretName, cancellationToken);
_logger.Information("Finishing to get the secret | Method: {method} | Class: {class}", nameof(GetSecret), nameof(SecretService));
return ret;
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(GetSecret), nameof(SecretService));
return default;
}
}
public async Task SetSecret(string secretName, string secretValue, CancellationToken cancellationToken)
{
try
{
_logger.Information("Starting to set the secret | Method: {method} | Class: {class}", nameof(SetSecret), nameof(SecretService));
await _repository.SetSecret(secretName, secretValue, cancellationToken);
_logger.Information("Finishing to set the secret | Method: {method} | Class: {class}", nameof(SetSecret), nameof(SecretService));
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(SetSecret), nameof(SecretService));
}
}
public async Task RemoveSecret(string secretName, CancellationToken cancellationToken)
{
try
{
_logger.Information("Starting to remove the secret | Method: {method} | Class: {class}", nameof(RemoveSecret), nameof(SecretService));
await _repository.RemoveSecret(secretName, cancellationToken);
_logger.Information("Finishing to remove the secret | Method: {method} | Class: {class}", nameof(RemoveSecret), nameof(SecretService));
}
catch (Exception ex)
{
_logger.Error(ex, "{error} | Method: {method} | Class: {class}", ex.Message, nameof(RemoveSecret), nameof(SecretService));
}
}
}
}

View File

@ -0,0 +1,16 @@
using Azure;
using Azure.Storage.Blobs.Models;
using Core.Blueprint.Storage;
using Core.Blueprint.Storage.Adapters;
namespace Core.Blueprint.DAL.Storage.Contracts
{
public interface IBlobStorageService
{
Task<IEnumerable<BlobFileAdapter>> GetBlobsListAsync(string? prefix);
Task<Response<BlobContentInfo>> UploadBlobAsync(string blobName, Stream content);
Task<BlobFileAdapter> UploadBlobAsync(BlobAddDto newBlob);
BlobDownloadUriAdapter DownloadBlobAsync(string blobName);
Task<BlobFileAdapter?> DeleteBlobAsync(string fileName);
}
}

View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Provider\BlobStorageService - Copy.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageReference Include="Core.Blueprint.Storage" Version="0.3.0-alpha0049" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.9.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,41 @@
using Azure;
using Azure.Storage.Blobs.Models;
using Core.Blueprint.DAL.Storage.Contracts;
using Core.Blueprint.Storage;
using Core.Blueprint.Storage.Adapters;
using Core.Blueprint.Storage.Contracts;
namespace Core.Blueprint.DAL.Storage.Service
{
public class BlobStorageService(IBlobStorageProvider blobStorageProvider) : IBlobStorageService
{
public async Task<Response<BlobContentInfo>> UploadBlobAsync(string blobName, Stream content)
{
var result = await blobStorageProvider.UploadBlobAsync(blobName, content);
return result;
}
public async Task<BlobFileAdapter> UploadBlobAsync(BlobAddDto newBlob)
{
var result = await blobStorageProvider.UploadBlobAsync(newBlob);
return result;
}
public async Task<IEnumerable<BlobFileAdapter>> GetBlobsListAsync(string? prefix)
{
return await blobStorageProvider.ListBlobsAsync(prefix);
}
public BlobDownloadUriAdapter DownloadBlobAsync(string blobName)
{
var result = blobStorageProvider.GenerateBlobDownloadUri(blobName);
return result;
}
public async Task<BlobFileAdapter?> DeleteBlobAsync(string blobName)
{
return await blobStorageProvider.DeleteBlobsAsync(blobName);
}
}
}

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.11.1" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>

81
Core.Blueprint.DAL.sln Normal file
View File

@ -0,0 +1,81 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34309.116
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.API", "Core.Blueprint.DAL.API\Core.Blueprint.DAL.API.csproj", "{D66611EE-2AE0-48B2-8D79-AF10A5E11C91}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{0DD43B65-17E6-4AA2-BE35-F9C7FCB5DD18}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{4D299A91-3EDD-4ABF-B134-CE4966E8C990}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.SQLServer", "Core.Blueprint.DAL.SQLServer\Core.Blueprint.DAL.SQLServer.csproj", "{546B418A-2DBD-499D-B7AA-57078231B950}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Storage", "Core.Blueprint.DAL.Storage\Core.Blueprint.DAL.Storage.csproj", "{B744C1BC-7EDA-47C5-BC04-91D0FB061985}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Hangfire", "Core.Blueprint.DAL.Hangfire\Core.Blueprint.DAL.Hangfire.csproj", "{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Mongo", "Core.Blueprint.DAL.Mongo\Core.Blueprint.DAL.Mongo.csproj", "{14F77CBD-952F-40F1-8568-A084EF7D2224}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Redis", "Core.Blueprint.DAL.Redis\Core.Blueprint.DAL.Redis.csproj", "{CD655B60-8C94-494A-87BA-F689CDD65F2B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.Logs", "Core.Blueprint.DAL.Logs\Core.Blueprint.DAL.Logs.csproj", "{B91E1D72-FB2E-4532-83E9-3E9EF2231740}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blueprint.DAL.KeyVault", "Core.Blueprint.DAL.KeyVault\Core.Blueprint.DAL.KeyVault.csproj", "{ACE11F5D-338D-4DF0-B2A1-D8886DEC4B1E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D66611EE-2AE0-48B2-8D79-AF10A5E11C91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D66611EE-2AE0-48B2-8D79-AF10A5E11C91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D66611EE-2AE0-48B2-8D79-AF10A5E11C91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D66611EE-2AE0-48B2-8D79-AF10A5E11C91}.Release|Any CPU.Build.0 = Release|Any CPU
{546B418A-2DBD-499D-B7AA-57078231B950}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{546B418A-2DBD-499D-B7AA-57078231B950}.Debug|Any CPU.Build.0 = Debug|Any CPU
{546B418A-2DBD-499D-B7AA-57078231B950}.Release|Any CPU.ActiveCfg = Release|Any CPU
{546B418A-2DBD-499D-B7AA-57078231B950}.Release|Any CPU.Build.0 = Release|Any CPU
{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B744C1BC-7EDA-47C5-BC04-91D0FB061985}.Release|Any CPU.Build.0 = Release|Any CPU
{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9}.Release|Any CPU.Build.0 = Release|Any CPU
{14F77CBD-952F-40F1-8568-A084EF7D2224}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14F77CBD-952F-40F1-8568-A084EF7D2224}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14F77CBD-952F-40F1-8568-A084EF7D2224}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14F77CBD-952F-40F1-8568-A084EF7D2224}.Release|Any CPU.Build.0 = Release|Any CPU
{CD655B60-8C94-494A-87BA-F689CDD65F2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD655B60-8C94-494A-87BA-F689CDD65F2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD655B60-8C94-494A-87BA-F689CDD65F2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD655B60-8C94-494A-87BA-F689CDD65F2B}.Release|Any CPU.Build.0 = Release|Any CPU
{B91E1D72-FB2E-4532-83E9-3E9EF2231740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B91E1D72-FB2E-4532-83E9-3E9EF2231740}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B91E1D72-FB2E-4532-83E9-3E9EF2231740}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B91E1D72-FB2E-4532-83E9-3E9EF2231740}.Release|Any CPU.Build.0 = Release|Any CPU
{ACE11F5D-338D-4DF0-B2A1-D8886DEC4B1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACE11F5D-338D-4DF0-B2A1-D8886DEC4B1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACE11F5D-338D-4DF0-B2A1-D8886DEC4B1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACE11F5D-338D-4DF0-B2A1-D8886DEC4B1E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D66611EE-2AE0-48B2-8D79-AF10A5E11C91} = {0DD43B65-17E6-4AA2-BE35-F9C7FCB5DD18}
{546B418A-2DBD-499D-B7AA-57078231B950} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990}
{B744C1BC-7EDA-47C5-BC04-91D0FB061985} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990}
{5D3F8418-7BFA-4EA7-ADE7-7285A91FB1D9} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990}
{14F77CBD-952F-40F1-8568-A084EF7D2224} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990}
{CD655B60-8C94-494A-87BA-F689CDD65F2B} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990}
{B91E1D72-FB2E-4532-83E9-3E9EF2231740} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990}
{ACE11F5D-338D-4DF0-B2A1-D8886DEC4B1E} = {4D299A91-3EDD-4ABF-B134-CE4966E8C990}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A74EEA93-F8F3-4607-92C8-D94D5E7F305C}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,18 @@
namespace Core.Blueprint.Domain.Contexts.SQLServer.BaseConfig
{
public abstract class BaseSQLEntity
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid TransactionalId { get; private set; }
public DateTime Created = DateTime.Now;
public DateTime Update { get; private set; }
public void IsUpdate()
{
TransactionalId = Guid.NewGuid();
Update = DateTime.Now;
}
}
}

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Bson" Version="3.0.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Contexts\Mongo\" />
<Folder Include="Contexts\KeyVault\" />
<Folder Include="Contexts\Storage\" />
<Folder Include="Contexts\Redis\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
namespace Core.Blueprint.Domain.Dtos
{
public class ImageUrlDto
{
public Uri 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.Domain.Dtos
{
public class KeyVaultSecretDto
{
public string Key { get; set; }
public string Value { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson;
namespace Core.Blueprint.Domain.Entities
{
public abstract class AbsEntity
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
[BsonElement("_id")]
public string? Id { get; set; }
public char StatusCode { get; set; } = 'P';
}
}

View File

@ -0,0 +1,7 @@
namespace Core.Blueprint.Domain.Entities
{
public abstract class AbsFileEntity : AbsEntity
{
public byte[] FileContent { get; set; } = [];
}
}

View File

@ -0,0 +1,15 @@
using Core.Blueprint.Domain.Shared;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace Core.Blueprint.Domain.Entities
{
[CollectionAttributeName("blueprint")]
public class BlueprintCollection : AbsEntity
{
public Guid CorrelationId { get; set; }
public DateTime Created { get; set; }
}
}

View File

@ -0,0 +1,7 @@
namespace Core.Blueprint.Domain.Entities
{
public class SampleImage : AbsFileEntity
{
}
}

View File

@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Core.Blueprint.Domain.Entities
{
[Table("Blueprint_Test01")]
public class SampleItem : AbsEntity
{
public Guid Id { get; set; } = Guid.NewGuid();
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;
}
}
//User - 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.Domain.Entities
{
public class Secret
{
public string? Value { get; set; }
}
}

View File

@ -0,0 +1,12 @@
namespace Core.Blueprint.Domain.Shared
{
[AttributeUsage(AttributeTargets.Class)]
public class CollectionAttributeName : Attribute
{
public string Name { get; set; }
public CollectionAttributeName(string name)
{
Name = name;
}
}
}

View File

@ -0,0 +1,48 @@
// ***********************************************************************
// <copyright file="Claims.cs">
// Heath
// </copyright>
// ***********************************************************************
namespace Lib.Common.LoggingAPI.Service.Constants
{
/// <summary>
/// Constants for claims used in JWT tokens.
/// </summary>
public class Claims
{
/// <summary>
/// Claim name for user's name.
/// </summary>
public const string Name = "name";
/// <summary>
/// Claim name for user's name.
/// </summary>
public const string Email = "email";
/// <summary>
/// Claim name for user's ID.
/// </summary>
public const string Id = "id";
/// <summary>
/// Claim name for user's role ID.
/// </summary>
public const string Rol = "rol";
/// <summary>
/// Claim name for user's companies.
/// </summary>
public const string Companies = "companies";
/// <summary>
/// Claim name for user's projects.
/// </summary>
public const string Projects = "projects";
/// <summary>
/// Claim name for user's surveys.
/// </summary>
public const string Surveys = "surveys";
}
}

View File

@ -0,0 +1,397 @@
// ***********************************************************************
// <copyright file="DisplayNames.cs">
// Heath
// </copyright>
// ***********************************************************************
namespace Lib.Common.LoggingAPI.Service.Constants
{
/// <summary>
/// Constants of the display names for this service.
/// </summary>
public static class DisplayNames
{
/// <summary>
/// The active patameter.
/// </summary>
public const string Active = "active";
/// <summary>
/// The client identifier parameter.
/// </summary>
public const string ClientId = "clientId";
/// <summary>
/// The client request parameter.
/// </summary>
public const string ClientRequest = "clientRequest";
/// <summary>
/// The client response parameter.
/// </summary>
public const string ClientResponse = "clientResponse";
/// <summary>
/// The creation date.
/// </summary>
public const string CreationDate = "creationDate";
/// <summary>
/// The content parameter.
/// </summary>
public const string Content = "content";
/// <summary>
/// The delete parameter.
/// </summary>
public const string Delete = "delete";
/// <summary>
/// The description parameter.
/// </summary>
public const string Description = "description";
/// <summary>
/// The detail parameter.
/// </summary>
public const string Detail = "detail";
/// <summary>
/// The environment parameter.
/// </summary>
public const string Environment = "environment";
/// <summary>
/// The error log severity level parameter.
/// </summary>
public const string Error = "error";
/// <summary>
/// The error code parameter.
/// </summary>
public const string ErrorCode = "errorCode";
/// <summary>
/// The external request parameter.
/// </summary>
public const string ExternalRequest = "externalRequest";
/// <summary>
/// The external response parameter.
/// </summary>
public const string ExternalResponse = "externalResponse";
/// <summary>
/// The fatal log severity level parameter.
/// </summary>
public const string Fatal = "fatal";
/// <summary>
/// The host parameter.
/// </summary>
public const string Host = "host";
/// <summary>
/// The identifier parameter.
/// </summary>
public const string Id = "id";
/// <summary>
/// The inactive parameter.
/// </summary>
public const string Inactive = "inactive";
/// <summary>
/// The info log severity level parameter.
/// </summary>
public const string Info = "info";
/// <summary>
/// The information log severity level parameter.
/// </summary>
public const string Information = "information";
/// <summary>
/// The media parameter.
/// </summary>
public const string Media = "media";
/// <summary>
/// The media type parameter.
/// </summary>
public const string MediaType = "mediaType";
/// <summary>
/// The media use type parameter.
/// </summary>
public const string MediaUseType = "mediaUseType";
/// <summary>
/// Th message parameter.
/// </summary>
public const string Message = "message";
/// <summary>
/// The method parameter.
/// </summary>
public const string Method = "method";
/// <summary>
/// The monday parameter.
/// </summary>
public const string Monday = "monday";
/// <summary>
/// The MXN parameter.
/// </summary>
public const string MXN = "MXN";
/// <summary>
/// The name parameter.
/// </summary>
public const string Name = "name";
/// <summary>
/// The next page parameter.
/// </summary>
public const string NextPage = "nextPage";
/// <summary>
/// The nick name parameter.
/// </summary>
public const string NickName = "nickName";
/// <summary>
/// The note parameter.
/// </summary>
public const string Note = "note";
/// <summary>
/// The not so affordable parameter.
/// </summary>
public const string NotSoAffordable = "notSoAffordable";
/// <summary>
/// The object status parameter.
/// </summary>
public const string ObjectStatus = "objectStatus";
/// <summary>
/// The opening time parameter.
/// </summary>
public const string OpeningTime = "openingTime";
/// <summary>
/// The operation days parameter.
/// </summary>
public const string OperationDays = "operationDays";
/// <summary>
/// The page parameter.
/// </summary>
public const string Page = "page";
/// <summary>
/// The page count parameter.
/// </summary>
public const string PageCount = "pageCount";
/// <summary>
/// The page metadata parameter.
/// </summary>
public const string PageMetadata = "pageMetadata";
/// <summary>
/// The page size parameter.
/// </summary>
public const string PageSize = "pageSize";
/// <summary>
/// The parent identifier parameter.
/// </summary>
public const string ParentId = "ParentId";
/// <summary>
/// The pet ticket price parameter.
/// </summary>
public const string PetTicketPrice = "petTicketPrice";
/// <summary>
/// The place parameter.
/// </summary>
public const string Place = "place";
/// <summary>
/// The place type parameter.
/// </summary>
public const string PlaceType = "placeType";
/// <summary>
/// The previous page parameter.
/// </summary>
public const string PreviousPage = "previousPage";
/// <summary>
/// The provider identifier parameter.
/// </summary>
public const string ProviderId = "providerId";
/// <summary>
/// The provider type identifier parameter.
/// </summary>
public const string ProviderTypeId = "providerTypeId";
/// <summary>
/// The request identifier parameter.
/// </summary>
public const string RequestId = "requestId";
/// <summary>
/// The RNT identifier parameter.
/// </summary>
public const string RntId = "rntId";
/// <summary>
/// The route parameter.
/// </summary>
public const string Route = "route";
/// <summary>
/// The operation parameter.
/// </summary>
public const string Operation = "operation";
/// <summary>
/// The other ticket price parameter.
/// </summary>
public const string OtherTicketPrice = "otherTicketPrice";
/// <summary>
/// The path parameter.
/// </summary>
public const string Path = "path";
/// <summary>
/// The saturday parameter.
/// </summary>
public const string Saturday = "saturday";
/// <summary>
/// The secondary parameter.
/// </summary>
public const string Secondary = "secondary";
/// <summary>
/// The service health parameter.
/// </summary>
public const string ServiceHealth = "serviceHealth";
/// <summary>
/// The service identifier parameter.
/// </summary>
public const string ServiceId = "serviceId";
/// <summary>
/// The severity parameter.
/// </summary>
public const string Severity = "severity";
/// <summary>
/// The state identifier parameter.
/// </summary>
public const string StateId = "stateId";
/// <summary>
/// The region identifier parameter.
/// </summary>
public const string StateProvinceRegionId = "regionId";
/// <summary>
/// The sunday parameter.
/// </summary>
public const string Sunday = "sunday";
/// <summary>
/// The tax identifier parameter.
/// </summary>
public const string TaxId = "taxId";
/// <summary>
/// The target parameter.
/// </summary>
public const string Target = "target";
/// <summary>
/// The thursday parameter.
/// </summary>
public const string Thursday = "thursday";
/// <summary>
/// The timestamp parameter.
/// </summary>
public const string Timestamp = "timestamp";
/// <summary>
/// The total items parameter.
/// </summary>
public const string TotalItems = "totalItems";
/// <summary>
/// Gets or sets the transaction identifier parameter.
/// </summary>
public const string TransactionId = "transactionId";
/// <summary>
/// The tuesday parameter.
/// </summary>
public const string Tuesday = "tuesday";
/// <summary>
/// The URI parameter.
/// </summary>
public const string Uri = "uri";
/// <summary>
/// The update parameter.
/// </summary>
public const string Update = "update";
/// <summary>
/// The x-forwarded-for header parameter.
/// </summary>
public const string XForwardedFor = "xForwardedFor";
/// <summary>
/// The x-forwarded-for header parameter.
/// </summary>
public const string XForwardedForHeader = "X-Forwarded-For";
/// <summary>
/// The final currency identifier parameter.
/// </summary>
public const string CurrencyId = "currencyId";
/// <summary>
/// The user identifier parameter.
/// </summary>
public const string UserId = "userId";
/// <summary>
/// The user parameter.
/// </summary>
public const string User = "user";
/// <summary>
/// The warning log severity level.
/// </summary>
public const string Warning = "warning";
/// <summary>
/// The email parameter.
/// </summary>
public const string Email = "email";
}
}

View File

@ -0,0 +1,21 @@
// ***********************************************************************
// <copyright file="EnvironmentVariables.cs">
// Heath
// </copyright>
// ***********************************************************************
namespace Lib.Common.LoggingAPI.Service.Constants
{
/// <summary>
/// Constants of the environment variables for this service.
/// </summary>
public static class EnvironmentVariables
{
/// <summary>
/// The stage environment vriable.
/// </summary>
public const string Stage = "ASPNETCORE_ENVIRONMENT";
}
}

View File

@ -0,0 +1,79 @@
// ***********************************************************************
// <copyright file="ErrorCodes.cs">
// Heath
// </copyright>
// ***********************************************************************
namespace Lib.Common.LoggingAPI.Service.Constants
{
/// <summary>
/// Constants for the error codes.
/// </summary>
public static class ErrorCodes
{
/// <summary>
/// The generic entities not found error code.
/// </summary>
public const string EntitiesNotFound = "{0}EntitiesNotFound";
/// <summary>
/// The entity already exsits error message.
/// </summary>
public const string EntityAlreadyExists = "{0}EntityAlreadyExists";
/// <summary>
/// The generic entity not found error code.
/// </summary>
public const string EntityNotFound = "{0}EntityNotFound";
/// <summary>
/// The generic not supported error code.
/// </summary>
public const string EntityNotSupported = "{0}NotSupported";
/// <summary>
/// The internal server error code.
/// </summary>
public const string InternalServerError = "InternalServerError";
/// <summary>
/// The invalid parameters in mapper error code.
/// </summary>
public const string InvalidParametersMapper = "InvalidParametersMapper";
/// <summary>
/// The page size invalid value error code.
/// </summary>
public const string PageSizeInvalidValue = "PageSizeInvalidValue";
/// <summary>
/// The page ot of range error code.
/// </summary>
public const string PageOutOfRange = "PageOutOfRange";
/// <summary>
/// The property does not match the regular expresion error code.
/// </summary>
public const string PropertyDoesNotMatchRegex = "{0}PropertyDoesNotMatchRegex";
/// <summary>
/// The property is required error code.
/// </summary>
public const string PropertyIsRequired = "{0}PropertyIsRequired";
/// <summary>
/// The property length invalid error code.
/// </summary>
public const string PropertyLengthInvalid = "{0}PropertyLengthInvalid";
/// <summary>
/// The property must be in range error code.
/// </summary>
public const string PropertyMustBeInRange = "{0}PropertyMustBeInRange";
/// <summary>
/// The route not found error code.
/// </summary>
public const string RouteNotFound = "RouteNotFound";
}
}

View File

@ -0,0 +1,10 @@
namespace Lib.Common.LoggingAPI.Service.Constants
{
public static class Headers
{
/// <summary>
/// The authorization header.
/// </summary>
public const string Authorization = "Authorization";
}
}

View File

@ -0,0 +1,148 @@
// ***********************************************************************
// <copyright file="MimeTypes.cs">
// Heath
// </copyright>
// ***********************************************************************
using System.Globalization;
namespace Lib.Common.LoggingAPI.Service.Constants
{
/// <summary>
/// Constants for the mime types.
/// </summary>
public static class MimeTypes
{
/// <summary>
/// The service application/json mime type.
/// </summary>
public const string ApplicationJson = "application/json";
/// <summary>
/// The application/pdf mime type.
/// </summary>
public const string ApplicationPdf = "application/pdf";
/// <summary>
/// The end index.
/// </summary>
public const int EndIndex = 5;
/// <summary>
/// The JPEG extension.
/// </summary>
public const string ExtensionGif = "gif";
/// <summary>
/// The JPEG extension.
/// </summary>
public const string ExtensionJpeg = "jpeg";
/// <summary>
/// The PNG extension.
/// </summary>
public const string ExtensionPng = "png";
/// <summary>
/// The SVG extension.
/// </summary>
public const string ExtensionSvg = "svg";
/// <summary>
/// The image/gif mime type.
/// </summary>
public const string ImageGif = "image/gif";
/// <summary>
/// The image/jpeg mime type.
/// </summary>
public const string ImageJpeg = "image/jpeg";
/// <summary>
/// The image/png mime type.
/// </summary>
public const string ImagePng = "image/png";
/// <summary>
/// The image/svg+xml mime type.
/// </summary>
public const string ImageSvg = "image/svg+xml";
/// <summary>
/// The identifier GIF.
/// </summary>
public const string IdentifierGif = "R0LGO";
/// <summary>
/// The identifier PNG.
/// </summary>
public const string IdentifierJpeg = "/9J/4";
/// <summary>
/// The identifier PDF.
/// </summary>
public const string IdentifierPdf = "JVBER";
/// <summary>
/// The identifier PNG.
/// </summary>
public const string IdentifierPng = "IVBOR";
/// <summary>
/// The identifier SVG.
/// </summary>
public const string IdentifierSvg = "PHN2Z";
/// <summary>
/// The parameter name.
/// </summary>
public const string ParameterName = "MimeType";
/// <summary>
/// The start index.
/// </summary>
public const int StartIndex = 0;
/// <summary>
/// The mime type dictionary.
/// </summary>
public static readonly Dictionary<string, string> Dictionary = new Dictionary<string, string>
{
{ IdentifierJpeg, ImageJpeg },
{ IdentifierPng, ImagePng },
{ IdentifierGif, ImageGif },
{ IdentifierSvg, ImageSvg },
};
/// <summary>
/// The mime type dictionary.
/// </summary>
public static readonly Dictionary<string, string> DictionaryExtension = new Dictionary<string, string>
{
{ IdentifierJpeg, ExtensionJpeg },
{ IdentifierPng, ExtensionPng },
{ IdentifierGif, ExtensionGif },
{ IdentifierSvg, ExtensionSvg },
};
/// <summary>
/// Gets the mime type.
/// </summary>
/// <param name="content">The cpntent with mime type identifier, substring 0, 5 from content.</param>
/// <returns>A <see cref="string"/> representing the value.</returns>
public static string GetMimeType(this string content)
{
return Dictionary.FirstOrDefault(_ => _.Key == content[..EndIndex].ToUpper(CultureInfo.InvariantCulture)).Value;
}
/// <summary>
/// Gets the extension.
/// </summary>
/// <param name="content">The mime type identifier, substring 0, 5 from content.</param>
/// <returns>A <see cref="string"/> representing the value.</returns>
public static string GetExtension(this string content)
{
return DictionaryExtension.FirstOrDefault(_ => _.Key == content[..EndIndex].ToUpper(CultureInfo.InvariantCulture)).Value;
}
}
}

View File

@ -0,0 +1,29 @@
// ***********************************************************************
// <copyright file="Responses.cs">
// Heath
// </copyright>
// ***********************************************************************
namespace Lib.Common.LoggingAPI.Service.Constants
{
/// <summary>
/// Constants of the responses for this service.
/// </summary>
public static class Responses
{
/// <summary>
/// The health response.
/// </summary>
public const string HealthyService = "healthy";
/// <summary>
/// The route does not exist response.
/// </summary>
public const string RouteDoesNotExist = "The specified route '{0}' does not exist for method '{1}' in this service.";
/// <summary>
/// The target response.
/// </summary>
public const string Target = "{0}|{1}://{2}{3}";
}
}

View File

@ -0,0 +1,44 @@
// ***********************************************************************
// <copyright file="ErrorDetailsDto.cs">
// Heath
// </copyright>
// ***********************************************************************
using Lib.Common.LoggingAPI.Service.Constants;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace Lib.Common.LoggingAPI.Service.DataTransferObjects.Error
{
/// <summary>
/// The service error details transfer object.
/// </summary>
public class ErrorDetailsDto
{
/// <summary>
/// Gets or sets the service error code.
/// </summary>
/// <example>healthy</example>
[DisplayName(DisplayNames.ErrorCode)]
[JsonPropertyName(DisplayNames.ErrorCode)]
public string? ErrorCode { get; set; }
/// <summary>
/// Gets or sets the service error message.
/// </summary>
/// <example>This is an example message.</example>
[DisplayName(DisplayNames.Message)]
[JsonPropertyName(DisplayNames.Message)]
public string? Message { get; set; }
/// <summary>
/// Gets or sets the service target.
/// </summary>
/// <example>healthy</example>
[DisplayName(DisplayNames.Target)]
[JsonPropertyName(DisplayNames.Target)]
public string? Target { get; set; }
}
}

View File

@ -0,0 +1,46 @@
// ***********************************************************************
// <copyright file="HttpErrorDto.cs">
// Heath
// </copyright>
// ***********************************************************************
using Lib.Common.LoggingAPI.Service.Constants;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace Lib.Common.LoggingAPI.Service.DataTransferObjects.Error
{
/// <summary>
/// The service HTTP error data transfer object.
/// </summary>
public class HttpErrorDto
{
/// <summary>
/// Gets or sets the error.
/// </summary>
[DisplayName(DisplayNames.Error)]
[JsonPropertyName(DisplayNames.Error)]
public ErrorDetailsDto Error { get; set; }
/// <summary>
/// Creates a new instance of <see cref="HttpErrorDto{TMessage}"/>
/// with custom parameters.
/// </summary>
/// <param name="message">The HTTP error message.</param>
/// <param name="errorCode">The HTTP error code.</param>
/// <param name="target">The HTTP error target.</param>
public HttpErrorDto(
string? message,
string? errorCode,
string? target)
{
this.Error = new ErrorDetailsDto
{
ErrorCode = errorCode,
Message = message,
Target = target,
};
}
}
}

View File

@ -0,0 +1,121 @@
// ***********************************************************************
// <copyright file="LogDetail.cs">
// Heath
// </copyright>
// ***********************************************************************
using Lib.Common.LoggingAPI.Service.Constants;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace Lib.Common.LoggingAPI.Service.DataTransferObjects.Logger
{
/// <summary>
/// The service logger detail object.
/// </summary>
/// <typeparam name="TMessage">The generic message type.</typeparam>
public class LogDetail<TMessage>
{
/// <summary>
/// Gets or sets the log severity.
/// </summary>
/// <example>info</example>
[DisplayName(DisplayNames.Severity)]
[JsonPropertyName(DisplayNames.Severity)]
public LogSeverity Severity { get; set; }
/// <summary>
/// Gets or sets the timestamp.
/// </summary>
[DisplayName(DisplayNames.Timestamp)]
[JsonPropertyName(DisplayNames.Timestamp)]
public DateTime Timestamp { get; set; }
/// <summary>
/// Gets or sets the environment.
/// </summary>
/// <example>Development</example>
[DisplayName(DisplayNames.Environment)]
[JsonPropertyName(DisplayNames.Environment)]
public string? Environment { get; set; }
/// <summary>
/// Gets or sets the target.
/// </summary>
[DisplayName(DisplayNames.Target)]
[JsonPropertyName(DisplayNames.Target)]
public LogTarget? Target { get; set; }
/// <summary>
/// Gets or sets the x-forwarded-for header.
/// </summary>
/// <example>localhost</example>
[DisplayName(DisplayNames.XForwardedFor)]
[JsonPropertyName(DisplayNames.XForwardedFor)]
public string? XForwardedFor { get; set; }
/// <summary>
/// Gets or sets the service identifier.
/// </summary>
/// <example><see cref="Guid.NewGuid()"/></example>
[DisplayName(DisplayNames.ServiceId)]
[JsonPropertyName(DisplayNames.ServiceId)]
public string? ServiceId { get; set; }
/// <summary>
/// Gets or sets the request identifier.
/// </summary>
/// <example><see cref="Guid.NewGuid()"/></example>
[DisplayName(DisplayNames.RequestId)]
[JsonPropertyName(DisplayNames.RequestId)]
public string? RequestId { get; set; }
/// <summary>
/// Gets or sets the client identifier.
/// </summary>
/// <example><see cref="Guid.NewGuid()"/></example>
[DisplayName(DisplayNames.ClientId)]
[JsonPropertyName(DisplayNames.ClientId)]
public string? ClientId { get; set; }
/// <summary>
/// Gets or sets the client identifier.
/// </summary>
/// <example>clientRequest</example>
[DisplayName(DisplayNames.Operation)]
[JsonPropertyName(DisplayNames.Operation)]
public LogOperation Operation { get; set; }
/// <summary>
/// Gets or sets the user name.
/// </summary>
/// <example>clientRequest</example>
[DisplayName(DisplayNames.User)]
[JsonPropertyName(DisplayNames.User)]
public string? User { get; set; }
/// <summary>
/// Gets or sets user's email.
/// </summary>
/// <example>clientRequest</example>
[DisplayName(DisplayNames.Email)]
[JsonPropertyName(DisplayNames.Email)]
public string? Email { get; set; }
/// <summary>
/// Gets or sets the user identifier.
/// </summary>
/// <example>clientRequest</example>
[DisplayName(DisplayNames.UserId)]
[JsonPropertyName(DisplayNames.UserId)]
public string? UserId { get; set; }
/// <summary>
/// Gets or sets the message.
/// </summary>
/// <example>A custom log message.</example>
[DisplayName(DisplayNames.Message)]
[JsonPropertyName(DisplayNames.Message)]
public TMessage? Message { get; set; }
}
}

View File

@ -0,0 +1,56 @@
// ***********************************************************************
// <copyright file="LogOperation.cs">
// Heath
// </copyright>
// ***********************************************************************
using Lib.Common.LoggingAPI.Service.Constants;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
namespace Lib.Common.LoggingAPI.Service.DataTransferObjects.Logger
{
/// <summary>
/// Represents all possible values for log operation.
/// </summary>
[DataContract]
public enum LogOperation
{
/// <summary>
/// The client request log operation type.
/// </summary>
[EnumMember(Value = DisplayNames.ClientRequest)]
[JsonPropertyName(DisplayNames.ClientRequest)]
ClientRequest = 0,
/// <summary>
/// The client response log operation type.
/// </summary>
[EnumMember(Value = DisplayNames.ClientResponse)]
ClientResponse = 1,
/// <summary>
/// The external request log operation type.
/// </summary>
[EnumMember(Value = DisplayNames.ExternalRequest)]
ExternalRequest = 2,
/// <summary>
/// The external response log operation type.
/// </summary>
[EnumMember(Value = DisplayNames.ExternalResponse)]
ExternalResponse = 3,
/// <summary>
/// The error log operation type.
/// </summary>
[EnumMember(Value = DisplayNames.Error)]
Error = 4,
/// <summary>
/// The info log operation type.
/// </summary>
[EnumMember(Value = DisplayNames.Info)]
Info = 5,
}
}

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