refactor: distribute configurations by classes

This commit is contained in:
2024-06-01 10:57:52 +03:00
parent ca02509b97
commit 78f589bb18
8 changed files with 275 additions and 173 deletions

View File

@ -1,173 +1,77 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Mirea.Api.DataAccess.Application;
using Mirea.Api.DataAccess.Persistence;
using Mirea.Api.DataAccess.Persistence.Common;
using Mirea.Api.Endpoint.Common.Interfaces;
using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Endpoint.Common.Services.Security;
using Mirea.Api.Endpoint.Configuration;
using Mirea.Api.Endpoint.Configuration.AppConfig;
using Mirea.Api.Endpoint.Configuration.General;
using Mirea.Api.Endpoint.Configuration.General.Settings;
using Mirea.Api.Endpoint.Configuration.General.Validators;
using Mirea.Api.Endpoint.Configuration.Swagger;
using Mirea.Api.Endpoint.Middleware;
using Mirea.Api.Security.Common.Interfaces;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Text;
namespace Mirea.Api.Endpoint;
public class Program
{
private static IConfigurationRoot ConfigureEnvironment()
public static IServiceCollection AddDatabase(IServiceCollection services, IConfiguration configuration)
{
EnvironmentManager.LoadEnvironment(".env");
var environmentVariables = Environment.GetEnvironmentVariables()
.OfType<DictionaryEntry>()
.ToDictionary(
entry => entry.Key.ToString() ?? string.Empty,
entry => entry.Value?.ToString() ?? string.Empty
);
var result = new ConfigurationBuilder().AddInMemoryCollection(environmentVariables!);
return result.Build();
}
private static IServiceCollection ConfigureJwtToken(IServiceCollection services, IConfiguration configuration)
{
var lifeTimeJwt = TimeSpan.FromMinutes(int.Parse(configuration["SECURITY_LIFE_TIME_JWT"]!));
var jwtDecrypt = Encoding.UTF8.GetBytes(configuration["SECURITY_ENCRYPTION_TOKEN"] ?? string.Empty);
if (jwtDecrypt.Length != 32)
throw new InvalidOperationException("The secret token \"SECURITY_ENCRYPTION_TOKEN\" cannot be less than 32 characters long. Now the size is equal is " + jwtDecrypt.Length);
var jwtKey = Encoding.UTF8.GetBytes(configuration["SECURITY_SIGNING_TOKEN"] ?? string.Empty);
if (jwtKey.Length != 64)
throw new InvalidOperationException("The signature token \"SECURITY_SIGNING_TOKEN\" cannot be less than 64 characters. Now the size is " + jwtKey.Length);
var jwtIssuer = configuration["SECURITY_JWT_ISSUER"];
var jwtAudience = configuration["SECURITY_JWT_AUDIENCE"];
if (string.IsNullOrEmpty(jwtAudience) || string.IsNullOrEmpty(jwtIssuer))
throw new InvalidOperationException("The \"SECURITY_JWT_ISSUER\" and \"SECURITY_JWT_AUDIENCE\" are not specified");
services.AddSingleton<IAccessToken, JwtTokenService>(_ => new JwtTokenService
{
Audience = jwtAudience,
Issuer = jwtIssuer,
Lifetime = lifeTimeJwt,
EncryptionKey = jwtDecrypt,
SigningKey = jwtKey
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtIssuer,
ValidateAudience = true,
ValidAudience = jwtAudience,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(jwtKey),
TokenDecryptionKey = new SymmetricSecurityKey(jwtDecrypt)
};
});
var dbSettings = configuration.Get<DbSettings>();
services.AddApplication();
services.AddPersistence(
dbSettings?.DatabaseProvider ?? DatabaseProvider.Sqlite,
dbSettings?.ConnectionStringSql ?? string.Empty);
return services;
}
private static IServiceCollection ConfigureSecurity(IServiceCollection services)
{
services.AddSingleton<IAccessToken, JwtTokenService>();
services.AddSingleton<IRevokedToken, MemoryRevokedTokenService>();
return services;
}
public static void Main(string[] args)
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddConfiguration(ConfigureEnvironment());
builder.Configuration.AddConfiguration(EnvironmentConfiguration.GetEnvironment());
builder.Configuration.AddJsonFile(PathBuilder.Combine(GeneralConfig.FilePath), optional: true, reloadOnChange: true);
builder.Services.Configure<GeneralConfig>(builder.Configuration);
var generalConfig = builder.Configuration.Get<GeneralConfig>();
builder.Services.AddApplication();
builder.Services.AddPersistence(generalConfig?.DbSettings?.DatabaseProvider ?? DatabaseProvider.Sqlite, generalConfig?.DbSettings?.ConnectionStringSql ?? string.Empty);
builder.Host.AddCustomSerilog();
AddDatabase(builder.Services, builder.Configuration);
builder.Services.AddControllers();
builder.Services.AddSingleton<IMaintenanceModeNotConfigureService, MaintenanceModeNotConfigureService>();
builder.Services.AddSingleton<IMaintenanceModeService, MaintenanceModeService>();
builder.Services.AddSingleton<ISetupToken, SetupTokenService>();
builder.Services.AddMemoryCache();
builder.Services.AddCustomRedis(builder.Configuration);
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyHeader();
policy.AllowAnyMethod();
policy.AllowAnyOrigin();
policy.WithOrigins("http://localhost:4200");
policy.AllowCredentials();
});
});
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ReportApiVersions = true;
options.ApiVersionReader = new UrlSegmentApiVersionReader();
});
builder.Services.AddCustomApiVersioning();
builder.Services.AddCustomSwagger();
builder.Services.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.OperationFilter<SwaggerDefaultValues>();
var basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
var xmlPath = Path.Combine(basePath, "docs.xml");
options.IncludeXmlComments(xmlPath);
});
builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
builder.Services.AddJwtToken(builder.Configuration);
builder.Services.AddSecurity(builder.Configuration);
var app = builder.Build();
#if DEBUG
// Write configurations
foreach (var item in app.Configuration.AsEnumerable())
Console.WriteLine($"{item.Key}:{item.Value}");
#endif
app.UseCors("AllowAll");
app.UseCustomSerilog();
using (var scope = app.Services.CreateScope())
{
@ -184,27 +88,11 @@ public class Program
maintenanceModeService.DisableMaintenanceMode();
DbInitializer.Initialize(uberDbContext);
// todo: if admin not found
}
}
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
var provider = app.Services.GetService<IApiVersionDescriptionProvider>();
app.UseCustomSwagger(app.Services);
foreach (var description in provider!.ApiVersionDescriptions)
{
var url = $"/swagger/{description.GroupName}/swagger.json";
var name = description.GroupName.ToUpperInvariant();
options.SwaggerEndpoint(url, name);
}
});
}
app.UseMiddleware<MaintenanceModeMiddleware>();
app.UseMiddleware<CustomExceptionHandlerMiddleware>();
@ -212,7 +100,6 @@ public class Program
app.UseAuthorization();
app.MapControllers();
app.Run();