using BMA.EHR.Recruit.Service; using BMA.EHR.Recruit.Service.Core; using BMA.EHR.Recruit.Service.Data; using BMA.EHR.Recruit.Service.Services; using BMA.EHR.Recurit.Service.Data; 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 MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; 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.BackchannelHttpHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }; opt.TokenValidationParameters = new() { ValidateIssuer = true, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = issuer, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)) }; }); builder.Services.AddAuthorization(); // Register Services builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); // Configure HttpClient with timeout builder.Services.AddHttpClient("default", client => { client.Timeout = TimeSpan.FromSeconds(30); }); // use serilog //ConfigureLogs(); //builder.Host.UseSerilog(); BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String)); BsonSerializer.RegisterSerializer(new DateTimeSerializer(BsonType.String)); // Register DbContext var recruitConnection = builder.Configuration.GetConnectionString("RecruitConnection"); builder.Services.AddDbContext(options => options.UseMySql(recruitConnection, ServerVersion.AutoDetect(recruitConnection)), ServiceLifetime.Transient); var orgConnection = builder.Configuration.GetConnectionString("OrgConnection"); builder.Services.AddDbContext(options => options.UseMySql(orgConnection, ServerVersion.AutoDetect(orgConnection)), ServiceLifetime.Transient); var defaultConnection = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(options => options.UseMySql(defaultConnection, ServerVersion.AutoDetect(defaultConnection)), ServiceLifetime.Transient); // Add config CORS builder.Services.AddCors(options => options.AddDefaultPolicy(builder => { builder .AllowAnyOrigin() //.WithOrigins("http://localhost:8000") .AllowAnyMethod() .AllowAnyHeader() .SetIsOriginAllowedToAllowWildcardSubdomains(); })); // 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.UseMiddleware(); 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 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(".", "-")}" }; }