using Elecciones.Database; using Microsoft.EntityFrameworkCore; using Serilog; using Elecciones.Core.Services; using Elecciones.Infrastructure.Services; using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using Elecciones.Database.Entities; using System.Text.Json.Serialization; // Esta es la estructura estándar y recomendada. var builder = WebApplication.CreateBuilder(args); // 1. Configurar Serilog. Esta es la forma correcta de integrarlo. builder.Host.UseSerilog((context, services, configuration) => configuration .ReadFrom.Configuration(context.Configuration) .ReadFrom.Services(services) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.File("logs/api-.log", rollingInterval: RollingInterval.Day)); // 2. Añadir servicios al contenedor. var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext(options => options.UseSqlServer(connectionString)); builder.Services.AddScoped(); builder.Services.AddControllers().AddJsonOptions(options => { // Esto le dice al serializador que maneje las referencias circulares options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; }); var MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; builder.Services.AddCors(options => { options.AddPolicy(name: MyAllowSpecificOrigins, policy => { policy.WithOrigins( "http://localhost:5173", // Para widgets "http://localhost:5174" // Para admin ) .AllowAnyHeader() .AllowAnyMethod(); }); }); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)) }; }); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // 3. Construir la aplicación. var app = builder.Build(); // Seeder para el usuario admin using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; try { var context = services.GetRequiredService(); var hasher = services.GetRequiredService(); if (!context.AdminUsers.Any()) { var (hash, salt) = hasher.HashPassword("PTP847elec"); context.AdminUsers.Add(new Elecciones.Database.Entities.AdminUser { Username = "admin", PasswordHash = hash, PasswordSalt = salt }); context.SaveChanges(); Console.WriteLine("--> Admin user seeded."); } } catch (Exception ex) { var logger = services.GetRequiredService>(); logger.LogError(ex, "An error occurred while seeding the database."); } } // Seeder para las bancas vacías using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; var context = services.GetRequiredService(); if (!context.Bancadas.Any()) { var bancas = new List(); // 92 bancas de diputados for (int i = 1; i <= 92; i++) // Bucle de 1 a 92 { bancas.Add(new Bancada { Camara = Elecciones.Core.Enums.TipoCamara.Diputados, NumeroBanca = i // Asignamos el número de banca }); } // 46 bancas de senadores for (int i = 1; i <= 46; i++) // Bucle de 1 a 46 { bancas.Add(new Bancada { Camara = Elecciones.Core.Enums.TipoCamara.Senadores, NumeroBanca = i // Asignamos el número de banca }); } context.Bancadas.AddRange(bancas); context.SaveChanges(); Console.WriteLine("--> Seeded 138 bancas físicas."); } } // Seeder para las configuraciones por defecto using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; var context = services.GetRequiredService(); if (!context.Configuraciones.Any(c => c.Clave == "MostrarOcupantes")) { context.Configuraciones.Add(new Configuracion { Clave = "MostrarOcupantes", Valor = "true" }); context.SaveChanges(); Console.WriteLine("--> Seeded default configuration 'MostrarOcupantes'."); } } // Configurar el pipeline de peticiones HTTP. // Añadimos el logging de peticiones de Serilog aquí. app.UseSerilogRequestLogging(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } // 1. Redirección a HTTPS (si se usa) //app.UseHttpsRedirection(); // 2. Middleware de Enrutamiento. ¡CLAVE! // Determina a qué endpoint irá la petición. app.UseRouting(); // 3. Middleware de CORS. // Ahora se ejecuta sabiendo a qué endpoint se dirige la petición. app.UseCors(MyAllowSpecificOrigins); // 4. Middleware de Autenticación. // Identifica quién es el usuario a partir del token. app.UseAuthentication(); // 5. Middleware de Autorización. // Verifica si el usuario identificado tiene permiso para acceder al endpoint. app.UseAuthorization(); // 6. Mapea los controladores a los endpoints que el enrutador descubrió. app.MapControllers(); // 5. Ejecutar la aplicación. app.Run();