using BMA.EHR.Recurit.Exam.Service; using BMA.EHR.Recurit.Exam.Service.Data; using BMA.EHR.Recurit.Exam.Service.Services; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Versioning; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using Serilog; using Serilog.Exceptions; using Serilog.Sinks.Elasticsearch; using System.Reflection; using System.Text; var builder = WebApplication.CreateBuilder(args); var issuer = builder.Configuration["Jwt:Issuer"]; var key = builder.Configuration["Jwt:Key"]; IdentityModelEventSource.ShowPII = true; builder.Services.AddHttpContextAccessor(); builder.Services.AddApiVersioning(opt => { opt.DefaultApiVersion = new ApiVersion(1, 0); opt.AssumeDefaultVersionWhenUnspecified = true; opt.ReportApiVersions = true; opt.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(), new HeaderApiVersionReader("x-api-version"), new MediaTypeApiVersionReader("x-api-version")); }); builder.Services.AddVersionedApiExplorer(setup => { setup.GroupNameFormat = "'v'VVV"; setup.SubstituteApiVersionInUrl = true; }); builder.Services.AddEndpointsApiExplorer(); // Authorization builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt => { opt.RequireHttpsMetadata = false; //false for dev opt.Authority = issuer; opt.TokenValidationParameters = new() { ValidateIssuer = true, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = issuer, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)) }; }); builder.Services.AddAuthorization(); // use serilog ConfigureLogs(); builder.Host.UseSerilog(); // Register DbContext var defaultConnection = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(options => options.UseMySql(defaultConnection, ServerVersion.AutoDetect(defaultConnection))); var metadataConnection = builder.Configuration.GetConnectionString("MetadataConnection"); builder.Services.AddDbContext(options => options.UseMySql(metadataConnection, ServerVersion.AutoDetect(metadataConnection))); // Add config CORS builder.Services.AddCors(options => options.AddDefaultPolicy(builder => { builder .AllowAnyOrigin() //.WithOrigins("http://localhost:8000") .AllowAnyMethod() .AllowAnyHeader() .SetIsOriginAllowedToAllowWildcardSubdomains(); })); // Register Service builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); // Add services to the container. builder.Services.AddControllers(options => { options.SuppressAsyncSuffixInActionNames = false; }) .AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); builder.Services.AddSwaggerGen(); builder.Services.ConfigureOptions(); builder.Services.AddHealthChecks(); var app = builder.Build(); var apiVersionDescriptionProvider = app.Services.GetRequiredService(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(options => { foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions) { options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant()); } }); } app.MapHealthChecks("/health"); app.UseHttpsRedirection(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseDefaultFiles(); app.UseStaticFiles(); app.MapControllers(); // apply migrations await using var scope = app.Services.CreateAsyncScope(); await using var db = scope.ServiceProvider.GetRequiredService(); await db.Database.MigrateAsync(); // seed default data await DatabaseSeeder.SeedPeriodExamAsync(app); app.Run(); void ConfigureLogs() { var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile( $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true) .Build(); Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() // .WriteTo.Debug() .MinimumLevel.Error() .WriteTo.Console() .Enrich.WithExceptionDetails() // .Enrich.WithEnvironmentUserName() .WriteTo.Elasticsearch(ConfigureElasticSink(configuration, environment ?? "")) .Enrich.WithProperty("Environment", environment) .ReadFrom.Configuration(configuration) .CreateLogger(); } ElasticsearchSinkOptions ConfigureElasticSink(IConfigurationRoot configuration, string environment) { return new ElasticsearchSinkOptions(new Uri(configuration["ElasticConfiguration:Uri"] ?? "")) { AutoRegisterTemplate = true, IndexFormat = $"{Assembly.GetExecutingAssembly()?.GetName()?.Name?.ToLower().Replace(".", "-")}-{environment?.ToLower().Replace(".", "-")}" }; }