using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; 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.Configuration.Core.BackgroundTasks; using Mirea.Api.Endpoint.Configuration.Core.Middleware; using Mirea.Api.Endpoint.Configuration.Core.Startup; using Mirea.Api.Endpoint.Configuration.Model; using Mirea.Api.Endpoint.Configuration.Validation; using Mirea.Api.Endpoint.Configuration.Validation.Validators; using Mirea.Api.Security.Services; using System; using System.IO; namespace Mirea.Api.Endpoint; public class Program { public static IServiceCollection AddDatabase(IServiceCollection services, IConfiguration configuration, IHealthChecksBuilder? healthCheckBuilder = null) { var dbSettings = configuration.Get()?.DbSettings; services.AddApplication(); services.AddPersistence( dbSettings?.DatabaseProvider ?? DatabaseProvider.Sqlite, dbSettings?.ConnectionStringSql ?? string.Empty); healthCheckBuilder?.AddDatabaseHealthCheck( dbSettings?.DatabaseProvider ?? DatabaseProvider.Sqlite, dbSettings?.ConnectionStringSql ?? string.Empty); return services; } public static void Main(string[] args) { Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); var builder = WebApplication.CreateBuilder(args); builder.Configuration.AddConfiguration(EnvironmentConfiguration.GetEnvironment()); var healthCheckBuilder = builder.Services.AddHealthChecks(); builder.Configuration.AddJsonFile(GeneralConfig.FilePath, optional: true, reloadOnChange: true); builder.Services.Configure(builder.Configuration); healthCheckBuilder.AddFile(x => x.AddFile(GeneralConfig.FilePath), name: nameof(GeneralConfig)); builder.Configuration.AddJsonFile(Admin.FilePath, optional: true, reloadOnChange: true); builder.Services.Configure(builder.Configuration); healthCheckBuilder.AddFile(x => x.AddFile(Admin.FilePath), name: nameof(Admin)); builder.Host.AddCustomSerilog(); AddDatabase(builder.Services, builder.Configuration, healthCheckBuilder); builder.Services.AddControllers(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddHostedService(); builder.Services.AddMemoryCache(); builder.Services.AddCustomRedis(builder.Configuration, healthCheckBuilder); builder.Services.AddCors(options => { options.AddPolicy("AllowAll", policy => { policy.AllowAnyMethod(); policy.AllowAnyHeader(); policy.AllowCredentials(); #if DEBUG policy.WithOrigins("http://localhost:4200"); #endif }); }); builder.WebHost.ConfigureKestrel(options => { options.ListenAnyIP( int.Parse(builder.Configuration.GetValue("INTERNAL_PORT") ?? "8080")); }); builder.Services.Configure(options => { var secretForward = builder.Configuration.Get(); if (string.IsNullOrEmpty(secretForward!.SecretForwardToken)) { secretForward.SecretForwardToken = GeneratorKey.GenerateAlphaNumeric(16); secretForward.SaveSetting(); Console.WriteLine($"For the reverse proxy server to work correctly, use the header: '{secretForward.SecretForwardToken}-X-Forwarded-For'"); } options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; options.ForwardedForHeaderName = secretForward.SecretForwardToken + "-X-Forwarded-For"; options.KnownNetworks.Clear(); options.KnownProxies.Clear(); }); builder.Services.AddCustomApiVersioning(); builder.Services.AddCustomSwagger(); builder.Services.AddJwtToken(builder.Configuration); builder.Services.AddSecurity(builder.Configuration); builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(PathBuilder.Combine("DataProtection"))); var app = builder.Build(); app.UseForwardedHeaders(); app.UseStaticFiles(UrlHelper.GetSubPath.TrimEnd('/')); app.UseCors("AllowAll"); app.UseCustomSerilog(); app.MapHealthChecks("/health"); using (var scope = app.Services.CreateScope()) { var serviceProvider = scope.ServiceProvider; var optionsSnapshot = serviceProvider.GetRequiredService>(); var settingsValidator = new SettingsRequiredValidator(optionsSnapshot); var isDoneConfig = settingsValidator.AreSettingsValid(); if (isDoneConfig) { var uberDbContext = serviceProvider.GetRequiredService(); var maintenanceModeService = serviceProvider.GetRequiredService(); maintenanceModeService.DisableMaintenanceMode(); DbInitializer.Initialize(uberDbContext); } } app.UseCustomSwagger(app.Services); app.UseHttpsRedirection(); app.UseMiddleware(); app.UseMiddleware(); app.UseMiddleware(); app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware(); app.UseMiddleware(); app.MapControllers(); app.Run(); } }