using Core.Interfaces; using Core.Interfaces.Stock; using Core.Services; using Core.Services.Stock; using Documents.Interfaces; using Documents.Services; using Google.Authenticator; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Models.Interfaces; using Models.Models; using Models.Repositories; using Models.Repositories.Stock; using phronCare.API.Models; using phronCare.API.Models.Security; using Services.Interfaces; using Services.Models; using Services.Services; using System.Text; using Transversal.Interfaces; using Transversal.Services; var builder = WebApplication.CreateBuilder(args); #region AppSetting configuration // Asegurar que el archivo appsettings.json se cargue correctamente builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); #endregion #region DbContext Identity Configuration and Operational var configuration = builder.Configuration; builder.Services.AddDbContext(options => options.UseSqlServer(configuration.GetConnectionString("phronCareDB"))); // DB Seguridad builder.Services.AddDbContext(options => options.UseSqlServer(configuration.GetConnectionString("PhronCareOperationsHubConnection"))); // DB Operacional #endregion #region Repositorios y Servicios RepositorysAndServices(builder); #endregion #region Require Confirmed Email builder.Services.Configure(opts => opts.SignIn.RequireConfirmedEmail = true); #endregion #region Security Identity EF Configuration builder.Services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); builder.Services.Configure(opts => opts.TokenLifespan = TimeSpan.FromHours(10)); builder.Services.AddSingleton(); #endregion #region Authentication Service builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => { options.Audience = configuration["JWT:ValidAudience"]; options.RequireHttpsMetadata = false; options.SaveToken = true; options.IncludeErrorDetails = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateIssuerSigningKey = true, ValidateLifetime = true, ValidIssuer = configuration["JWT:ValidIssuer"], ValidAudience = configuration["JWT:ValidAudience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["JWT:Secret"])), ClockSkew = TimeSpan.Zero }; options.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { var logger = context.HttpContext.RequestServices.GetRequiredService().CreateLogger("JWTDebug"); logger.LogError(context.Exception, "Error de autenticación JWT"); return Task.CompletedTask; } }; }); #endregion #region Email Configuration var emailConfig = configuration.GetSection("EmailConfiguration").Get(); if (emailConfig == null) { throw new InvalidOperationException("La configuración del correo electrónico no se encontró o es inválida."); } builder.Services.AddSingleton(emailConfig); builder.Services.AddScoped(); #endregion #region Swagger Configuration builder.Services.AddSwaggerGen(option => { option.SwaggerDoc("v1", new OpenApiInfo { Title = "phronCARE API - SaludLAB", Version = "v1" }); option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Por favor, ingrese un token valido", Name = "Authorization", Type = SecuritySchemeType.Http, BearerFormat = "JWT", Scheme = "Bearer" }); option.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type=ReferenceType.SecurityScheme, Id="Bearer" } }, new string[]{} } }); }); #endregion #region CORS sin cambios builder.Services.AddCors(options => { options.AddPolicy("CORS", policy => { /* Version para despliegue */ // policy // .WithOrigins("http://dev.biodec.saludlab.com.ar", "http://phroncareUI:80", "http://192.168.10.110:9002") // .AllowAnyMethod() // .AllowAnyHeader() // .AllowCredentials(); /* Version para desarrollo */ policy.WithOrigins("*").AllowAnyHeader().AllowAnyMethod(); }); }); #endregion builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); var logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger("JWT Debug"); logger.LogInformation("JWT Issuer: {Issuer}", configuration["JWT:ValidIssuer"]); logger.LogInformation("JWT Audience: {Audience}", configuration["JWT:ValidAudience"]); logger.LogInformation("JWT Audience: {Audience}", configuration["JWT:Secret"]); var app = builder.Build(); //if (app.Environment.IsDevelopment()) //{ app.UseSwagger(); app.UseSwaggerUI(); //} app.UseCors("CORS"); app.UseAuthentication(); app.UseAuthorization(); app.UseHttpsRedirection(); app.MapControllers(); app.Run(); static void RepositorysAndServices(WebApplicationBuilder builder) { // Registro servicio PDF transversal builder.Services.AddScoped(); // RazorLight + PDF rendering builder.Services.AddScoped(); builder.Services.AddScoped(); // DocumentTemplateService (si lo usás para orquestar) builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); //builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); // Registrar el service de lookup builder.Services.AddScoped(); builder.Services.AddScoped(); // Repositorio de histórico de cotizaciones builder.Services.AddScoped(); // Dominio/servicio con HttpClient para BCRA builder.Services.AddHttpClient(client => { client.BaseAddress = new Uri("https://api.bcra.gob.ar/"); }); //Core de Divisiones de Productos builder.Services.AddScoped(); builder.Services.AddScoped(); }