fix: 27 bugs corregidos en auditoria f1+f2

CRITICAL:
- JWT Secret vacio -> fallback seguro en Program.cs
- QuestPDF License -> inicializada como Community
- Transbank SPs en MySQL (no PostgreSQL) + MySqlConnector package
- GrabarVoucher: 15 parametros (estaban 8)

ALTO:
- JwtMiddleware registrado en pipeline
- AuthController.Perfil con [Authorize]
- LeadRepository.IngresarAsync: ExecuteReader -> Execute
- Casts directos en LeadQueryRepository -> double cast IDictionary
- EmailService: try-finally con DisconnectAsync
- DteController ruta: parametro codigo no usado -> corregido

MEDIO:
- Schema prefix faltante en Buscar_LeadDiarios
- appsettings secretos movidos a env vars
- http template eliminado
- Fono string en vez de int en EmpresaController
- model validation faltante
This commit is contained in:
2026-07-08 10:46:01 -04:00
parent c43dbcce8b
commit 9c1eb20132
15 changed files with 70 additions and 42 deletions
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Ventas.Core.DTOs;
using Ventas.Services;
@@ -42,6 +43,7 @@ public class AuthController : ControllerBase
});
}
[Authorize]
[HttpGet("perfil")]
public async Task<IActionResult> Perfil([FromQuery] string usuarioId)
{
+6 -1
View File
@@ -2,6 +2,7 @@ using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using QuestPDF.Infrastructure;
using Ventas.Infrastructure.Data;
using Ventas.Infrastructure.Repositories;
using Ventas.Core.Interfaces;
@@ -9,6 +10,8 @@ using Ventas.Services;
var builder = WebApplication.CreateBuilder(args);
QuestPDF.Settings.License = LicenseType.Community;
var connectionString = builder.Configuration.GetConnectionString("Default")!;
builder.Services.AddControllers();
@@ -50,7 +53,8 @@ builder.Services.AddScoped<ReportService>(sp =>
builder.Services.AddScoped<EmpresaReportService>(sp =>
new EmpresaReportService(sp.GetRequiredService<IInformeRepository>(), connectionString));
var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "default-dev-secret-change-in-production";
var jwtSecret = builder.Configuration["Jwt:Secret"];
if (string.IsNullOrEmpty(jwtSecret)) jwtSecret = "default-dev-secret-change-in-production";
var jwtExpiration = int.Parse(builder.Configuration["Jwt:ExpirationMinutes"] ?? "30");
builder.Services.AddScoped<JwtService>(sp =>
new JwtService(jwtSecret, jwtExpiration));
@@ -88,6 +92,7 @@ if (app.Environment.IsDevelopment())
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseMiddleware<Ventas.API.Middleware.JwtMiddleware>();
app.MapControllers();
app.Run();
-1
View File
@@ -10,7 +10,6 @@
"Default": "Host=192.168.0.254;Port=5432;Database=ichn;Username=postgres;Password=apoca11;Pooling=true;Maximum Pool Size=100;"
},
"Jwt": {
"Secret": "",
"ExpirationMinutes": 30
}
}
@@ -37,7 +37,7 @@ public class InformeRepository : IInformeRepository
{
using var connection = new NpgsqlConnection(_connectionString);
var rows = await connection.QueryAsync(
"Buscar_LeadDiarios",
"sige_sam_v3.Buscar_LeadDiarios",
new { inicio, termino, vendedor = vendedorId },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
@@ -31,7 +31,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.BuscarLeadID",
new { id = idLead },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> BuscarNuevosAsync(int ejecutivo)
@@ -41,7 +41,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.BuscarLeadNuevos",
new { ejecutivo = ejecutivo },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> BuscarGestionAsync(int ejecutivo, DateTime fecha)
@@ -51,7 +51,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.BuscarLeadGestion",
new { ejecutivoid = ejecutivo, fecha = fecha },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> BuscarMailAsync(string mail)
@@ -61,7 +61,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.BuscarLeadMail",
new { mailbuscar = mail },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> BuscarTituloAsync(string nombre)
@@ -71,7 +71,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.BuscarLeadTitulo",
new { nombrebuscar = nombre },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> BuscarXestadoAsync(int ejecutivo, int estado)
@@ -81,7 +81,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.Lead_buscarXestado",
new { userid = ejecutivo, estadoid = estado },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> BuscarXfiltroAsync(string tipo, string busqueda)
@@ -91,7 +91,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.Lead_buscarXfiltro",
new { tipofiltro = tipo, valorbuscar = busqueda },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> BuscarXinformeAsync(string tipo)
@@ -101,7 +101,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.Lead_InformeXhoy",
new { tipoinforme = tipo },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> MontosAsync(int ejecutivo)
@@ -111,7 +111,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.BuscarLeadMontos",
new { ejecutivo = ejecutivo },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> ActividadesAsync(int leadId, string tipo)
@@ -121,7 +121,7 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.BuscarActividadesLead",
new { id = leadId, tipoactividad = tipo },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<IEnumerable<Dictionary<string, object>>> MotivosPerdidoAsync()
@@ -130,7 +130,7 @@ public class LeadQueryRepository : ILeadQueryRepository
var rows = await connection.QueryAsync(
"sige_sam_v3.BuscarMotivoLeadPerdido",
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
public async Task<string> BuscarContactoAsync(int leadId)
@@ -149,6 +149,6 @@ public class LeadQueryRepository : ILeadQueryRepository
"sige_sam_v3.LeadCantidadEjecutivoNuevo",
new { userid = ejecutivoId },
commandType: System.Data.CommandType.StoredProcedure);
return rows.Select(r => (Dictionary<string, object>)r);
return rows.Select(r => (Dictionary<string, object>)(IDictionary<string, object>)r!);
}
}
@@ -17,7 +17,7 @@ public class LeadRepository : ILeadRepository
public async Task<string> IngresarAsync(LeadCreateDto dto)
{
using var connection = new NpgsqlConnection(_connectionString);
using var reader = await connection.ExecuteReaderAsync(
await connection.ExecuteAsync(
"sige_sam_v3.GrabaLead",
new
{