using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Reflection; using System.Text; using DiunaBI.Core.Database.Context; using DiunaBI.Core.Services; using Google.Apis.Sheets.v4; using Serilog; using DiunaBI.Core.Interfaces; var builder = WebApplication.CreateBuilder(args); if (builder.Environment.IsProduction()) { builder.Host.UseSerilog((context, configuration) => { configuration .ReadFrom.Configuration(context.Configuration) .Enrich.FromLogContext() .Enrich.WithProperty("Application", "DiunaBI") .Enrich.WithProperty("Version", Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown") .Enrich.WithEnvironmentName() .Enrich.WithMachineName(); }); } var connectionString = builder.Configuration.GetConnectionString("SQLDatabase"); builder.Services.AddDbContext(x => { x.UseSqlServer(connectionString); x.EnableSensitiveDataLogging(); }); builder.Services.AddCors(options => { options.AddPolicy("CORSPolicy", corsPolicyBuilder => { corsPolicyBuilder.WithOrigins("http://localhost:4200") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); corsPolicyBuilder.WithOrigins("https://diuna.bim-it.pl") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); }); builder.Services.AddControllers(); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Secret"]!)) }; }); // Queue services builder.Services.AddScoped(); builder.Services.AddHostedService(); // ✅ GOOD - with proper scope factory // Google Sheets dependencies Console.WriteLine("Adding Google Sheets dependencies..."); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(provider => { var googleSheetsHelper = provider.GetRequiredService(); var valuesResource = googleSheetsHelper.Service?.Spreadsheets.Values; if (valuesResource == null) { throw new InvalidOperationException("Google Sheets Service is not initialized properly"); } return valuesResource; }); builder.Services.AddSingleton(); var app = builder.Build(); if (app.Environment.IsProduction()) { app.UseSerilogRequestLogging(options => { options.MessageTemplate = "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms"; options.EnrichDiagnosticContext = (diagnosticContext, httpContext) => { diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value); diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme); var userAgent = httpContext.Request.Headers.UserAgent.FirstOrDefault(); if (!string.IsNullOrEmpty(userAgent)) { diagnosticContext.Set("UserAgent", userAgent); } diagnosticContext.Set("RemoteIP", httpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown"); diagnosticContext.Set("RequestContentType", httpContext.Request.ContentType ?? "none"); }; }); } // Plugin initialization var pluginManager = app.Services.GetRequiredService(); var executablePath = Assembly.GetExecutingAssembly().Location; var executableDir = Path.GetDirectoryName(executablePath)!; var pluginsPath = Path.Combine(executableDir, "Plugins"); if (app.Environment.IsProduction()) { Log.Information("Starting DiunaBI application"); Log.Information("Loading plugins from: {PluginsPath}", pluginsPath); } else { var logger = app.Services.GetRequiredService>(); logger.LogInformation("Starting DiunaBI application (Development)"); logger.LogInformation("Loading plugins from: {PluginsPath}", pluginsPath); } pluginManager.LoadPluginsFromDirectory(pluginsPath); app.Use(async (context, next) => { var token = context.Request.Headers.Authorization.ToString(); if (token.Length > 0 && !context.Request.Path.ToString().Contains("getForPowerBI") && !context.Request.Path.ToString().Contains("getConfiguration") && !context.Request.Path.ToString().Contains("DataInbox/Add") && !context.Request.Path.ToString().Contains("AddPluginName") // TODO: Remove this && !context.Request.Path.ToString().Contains("GetImportWorkers")) { var handler = new JwtSecurityTokenHandler(); var data = handler.ReadJwtToken(token.Split(' ')[1]); context.Request.Headers.Append("UserId", new Microsoft.Extensions.Primitives.StringValues(data.Subject)); } await next(context); }); app.UseCors("CORSPolicy"); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run(); if (app.Environment.IsProduction()) { Log.CloseAndFlush(); }