using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using TafsirQuran.Api.Auth; using TafsirQuran.Api.Endpoints; using TafsirQuran.Infrastructure; using TafsirQuran.Infrastructure.Persistence; var builder = WebApplication.CreateBuilder(args); builder.Services.AddInfrastructure(builder.Configuration); builder.Services.Configure(builder.Configuration.GetSection(JwtOptions.SectionName)); builder.Services.AddSingleton(); var jwt = builder.Configuration.GetSection(JwtOptions.SectionName).Get() ?? new JwtOptions(); builder.Services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwt.Issuer, ValidAudience = jwt.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwt.Key)) }; }); builder.Services.AddAuthorization(); builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()); }); builder.Services.AddOpenApi(); var app = builder.Build(); { var audioRoot = app.Configuration["AudioRoot"] ?? "/data/audio"; for (var attempt = 1; ; attempt++) { try { // Fresh scope each attempt so a failed seed cannot leave tracked entities. using var scope = app.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); await DbSeeder.SeedAsync(db, audioRoot); break; } catch (Exception ex) when (attempt < 30) { app.Logger.LogWarning(ex, "DB not ready (attempt {Attempt}); retry in 2s", attempt); await Task.Delay(TimeSpan.FromSeconds(2)); } } } if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.UseCors(); app.UseDefaultFiles(); app.UseStaticFiles(); app.UseAuthentication(); app.UseAuthorization(); app.MapTafsirEndpoints(); app.MapProgressEndpoints(); app.MapFavoriteEndpoints(); app.MapBookmarkEndpoints(); app.MapAuthEndpoints(); app.MapGet("/", () => Results.Ok(new { name = "TafsirQuran API", status = "ok" })); app.Run();