Fix 1807
This commit is contained in:
		| @@ -0,0 +1,83 @@ | |||||||
|  | using Elecciones.Core.DTOs; | ||||||
|  | using Microsoft.Extensions.Configuration; | ||||||
|  | using Microsoft.Extensions.Logging; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Diagnostics; | ||||||
|  | using System.Text.Json; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using static Elecciones.Core.DTOs.BancaDto; | ||||||
|  |  | ||||||
|  | namespace Elecciones.Infrastructure.Services; | ||||||
|  |  | ||||||
|  | // Implementación de emergencia que usa el comando 'curl' del sistema operativo | ||||||
|  | public class CurlElectoralApiService : IElectoralApiService | ||||||
|  | { | ||||||
|  |     private readonly ILogger<CurlElectoralApiService> _logger; | ||||||
|  |     private readonly IConfiguration _configuration; | ||||||
|  |     private readonly string _baseUrl; | ||||||
|  |  | ||||||
|  |     public CurlElectoralApiService(ILogger<CurlElectoralApiService> logger, IConfiguration configuration) | ||||||
|  |     { | ||||||
|  |         _logger = logger; | ||||||
|  |         _configuration = configuration; | ||||||
|  |         _baseUrl = _configuration["ElectoralApi:BaseUrl"] ?? ""; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private async Task<(int, string)> ExecuteCurlCommand(string arguments) | ||||||
|  |     { | ||||||
|  |         var process = new Process | ||||||
|  |         { | ||||||
|  |             StartInfo = new ProcessStartInfo | ||||||
|  |             { | ||||||
|  |                 FileName = "curl", | ||||||
|  |                 Arguments = arguments, | ||||||
|  |                 RedirectStandardOutput = true, | ||||||
|  |                 RedirectStandardError = true, | ||||||
|  |                 UseShellExecute = false, | ||||||
|  |                 CreateNoWindow = true, | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         process.Start(); | ||||||
|  |         string output = await process.StandardOutput.ReadToEndAsync(); | ||||||
|  |         string error = await process.StandardError.ReadToEndAsync(); | ||||||
|  |         await process.WaitForExitAsync(); | ||||||
|  |  | ||||||
|  |         if (process.ExitCode != 0) | ||||||
|  |         { | ||||||
|  |             _logger.LogError("Error al ejecutar curl. Exit Code: {ExitCode}. Error: {Error}", process.ExitCode, error); | ||||||
|  |             return (-1, error); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Extraemos el código de estado HTTP del final del stderr si usamos -w | ||||||
|  |         // (Simplificación: asumimos 200 si el ExitCode es 0) | ||||||
|  |         return (200, output); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public async Task<string?> GetAuthTokenAsync() | ||||||
|  |     { | ||||||
|  |         var username = _configuration["ElectoralApi:Username"]; | ||||||
|  |         var password = _configuration["ElectoralApi:Password"]; | ||||||
|  |         var arguments = $"-s -H \"username: {username}\" -H \"password: {password}\" \"{_baseUrl}/api/createtoken\""; | ||||||
|  |          | ||||||
|  |         var (status, output) = await ExecuteCurlCommand(arguments); | ||||||
|  |         if (status != 200) return null; | ||||||
|  |  | ||||||
|  |         var tokenResponse = JsonSerializer.Deserialize<TokenResponse>(output); | ||||||
|  |         return tokenResponse?.Data?.AccessToken; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Implementa los demás métodos de la interfaz usando el mismo patrón | ||||||
|  |     // ... | ||||||
|  |     // Por ahora, solo necesitamos GetAuthTokenAsync para validar la conexión. | ||||||
|  |     public Task<List<CategoriaDto>?> GetCategoriasAsync(string authToken) => Task.FromResult<List<CategoriaDto>?>(null); | ||||||
|  |     public Task<List<CatalogoDto>?> GetCatalogoCompletoAsync(string authToken) => Task.FromResult<List<CatalogoDto>?>(null); | ||||||
|  |     public Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId) => Task.FromResult<List<AgrupacionDto>?>(null); | ||||||
|  |     public Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId) => Task.FromResult<ResultadosDto?>(null); | ||||||
|  |     public Task<RepartoBancasDto?> GetBancasAsync(string authToken, string distritoId, string seccionId) => Task.FromResult<RepartoBancasDto?>(null); | ||||||
|  |     public Task<List<string[]>?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId) => Task.FromResult<List<string[]>?>(null); | ||||||
|  |     public Task<TelegramaFileDto?> GetTelegramaFileAsync(string authToken, string mesaId) => Task.FromResult<TelegramaFileDto?>(null); | ||||||
|  |     public Task<ResumenDto?> GetResumenAsync(string authToken, string distritoId) => Task.FromResult<ResumenDto?>(null); | ||||||
|  |     public Task<EstadoRecuentoGeneralDto?> GetEstadoRecuentoGeneralAsync(string authToken, string distritoId) => Task.FromResult<EstadoRecuentoGeneralDto?>(null); | ||||||
|  | } | ||||||
| @@ -13,7 +13,7 @@ using System.Reflection; | |||||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] | [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] | ||||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+39b1e9707275ed59ac4a7d32e26b951186a346bb")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+75ff9d5593b957c5ae0d08223a689a95181172d5")] | ||||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] | [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] | ||||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] | [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] | ||||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||||
|   | |||||||
| @@ -19,6 +19,12 @@ RUN dotnet publish "Elecciones.Worker.csproj" -c Release -o /app/publish | |||||||
| # --- Etapa 2: Final --- | # --- Etapa 2: Final --- | ||||||
| # Usamos la imagen de runtime genérica de .NET, ya que no necesita ASP.NET | # Usamos la imagen de runtime genérica de .NET, ya que no necesita ASP.NET | ||||||
| FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final | FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final | ||||||
|  | # Instalamos curl y ca-certificates para las peticiones HTTP | ||||||
|  | USER root | ||||||
|  | RUN apt-get update && apt-get install -y curl ca-certificates | ||||||
|  | USER app | ||||||
|  | # --- FIN DE LA SECCIÓN --- | ||||||
|  |  | ||||||
| WORKDIR /app | WORKDIR /app | ||||||
| COPY --from=build /app/publish . | COPY --from=build /app/publish . | ||||||
| ENTRYPOINT ["dotnet", "Elecciones.Worker.dll"] | ENTRYPOINT ["dotnet", "Elecciones.Worker.dll"] | ||||||
| @@ -32,38 +32,7 @@ builder.Services.AddDbContext<EleccionesDbContext>(options => | |||||||
| #if DEBUG | #if DEBUG | ||||||
| builder.Services.AddSingleton<IElectoralApiService, FakeElectoralApiService>(); | builder.Services.AddSingleton<IElectoralApiService, FakeElectoralApiService>(); | ||||||
| #else | #else | ||||||
| // --- SECCIÓN MODIFICADA (FINAL) --- | builder.Services.AddSingleton<IElectoralApiService, CurlElectoralApiService>(); | ||||||
| builder.Services.AddHttpClient("ElectoralApiClient", client => |  | ||||||
| { |  | ||||||
|     var baseUrl = builder.Configuration["ElectoralApi:BaseUrl"]; |  | ||||||
|     if (!string.IsNullOrEmpty(baseUrl)) |  | ||||||
|     { |  | ||||||
|         client.BaseAddress = new Uri(baseUrl); |  | ||||||
|     } |  | ||||||
| }) |  | ||||||
| .ConfigurePrimaryHttpMessageHandler(() => |  | ||||||
| { |  | ||||||
|     return new SocketsHttpHandler |  | ||||||
|     { |  | ||||||
|         SslOptions = new SslClientAuthenticationOptions |  | ||||||
|         { |  | ||||||
|             // Forzamos el protocolo TLS 1.3 |  | ||||||
|             EnabledSslProtocols = SslProtocols.Tls13, |  | ||||||
|  |  | ||||||
|             // --- ¡¡¡LA LÍNEA CLAVE CORREGIDA!!! --- |  | ||||||
|             // Forzamos explícitamente los únicos 3 cipher suites que el servidor acepta. |  | ||||||
|             CipherSuitesPolicy = new CipherSuitesPolicy(new[] |  | ||||||
|             { |  | ||||||
|                 TlsCipherSuite.TLS_AES_128_GCM_SHA256, |  | ||||||
|                 TlsCipherSuite.TLS_AES_256_GCM_SHA384, |  | ||||||
|                 TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256 |  | ||||||
|             }) |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| builder.Services.AddSingleton<IElectoralApiService, ElectoralApiService>(); |  | ||||||
| // --- FIN DE LA SECCIÓN MODIFICADA --- |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| builder.Services.AddHostedService<Worker>(); | builder.Services.AddHostedService<Worker>(); | ||||||
|   | |||||||
| @@ -4,5 +4,10 @@ | |||||||
|       "Default": "Information", |       "Default": "Information", | ||||||
|       "Microsoft.Hosting.Lifetime": "Information" |       "Microsoft.Hosting.Lifetime": "Information" | ||||||
|     } |     } | ||||||
|  |   }, | ||||||
|  |   "ElectoralApi": { | ||||||
|  |     "BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar", | ||||||
|  |     "Username": "30500094156@elecciones2025.onmicrosoft.com", | ||||||
|  |     "Password": "PTP847elec" | ||||||
|   } |   } | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user