Trabajo de ajuste en widgets y db para frontend

This commit is contained in:
2025-08-29 09:54:22 -03:00
parent 55954e18a7
commit 1ed9a49a53
93 changed files with 10259 additions and 609 deletions

View File

@@ -1,6 +1,13 @@
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);
@@ -18,22 +25,44 @@ var connectionString = builder.Configuration.GetConnectionString("DefaultConnect
builder.Services.AddDbContext<EleccionesDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddControllers();
builder.Services.AddScoped<IPasswordHasher, PasswordHasher>();
var allowedOrigins = builder.Configuration["AllowedOrigins"]?.Split(',') ?? Array.Empty<string>();
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.AddDefaultPolicy(policy =>
{
if (allowedOrigins.Any())
{
policy.WithOrigins(allowedOrigins)
.AllowAnyHeader()
.AllowAnyMethod();
}
});
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();
@@ -41,7 +70,72 @@ builder.Services.AddSwaggerGen();
// 3. Construir la aplicación.
var app = builder.Build();
// 4. Configurar el pipeline de peticiones HTTP.
// Seeder para el usuario admin
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<EleccionesDbContext>();
var hasher = services.GetRequiredService<IPasswordHasher>();
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<ILogger<Program>>();
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<EleccionesDbContext>();
if (!context.Bancadas.Any())
{
var bancas = new List<Bancada>();
// 92 bancas de diputados
for (int i = 0; i < 92; i++)
{
bancas.Add(new Bancada { Camara = Elecciones.Core.Enums.TipoCamara.Diputados });
}
// 46 bancas de senadores
for (int i = 0; i < 46; i++)
{
bancas.Add(new Bancada { Camara = Elecciones.Core.Enums.TipoCamara.Senadores });
}
context.Bancadas.AddRange(bancas);
context.SaveChanges();
Console.WriteLine("--> Seeded 138 empty bancas.");
}
}
// Seeder para las configuraciones por defecto
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
var context = services.GetRequiredService<EleccionesDbContext>();
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();
@@ -51,11 +145,27 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseCors();
// 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.
// El try/catch/finally se puede omitir; el logging de Serilog ya se encarga de los errores fatales.
app.Run();