using System; using System.IO; using System.Text.Json.Serialization; using DysonNetwork.Drive.Data; using DysonNetwork.Drive.Extensions; using DysonNetwork.Drive.Interfaces; using DysonNetwork.Drive.Models; using DysonNetwork.Drive.Services; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using NodaTime; using Npgsql; var builder = WebApplication.CreateBuilder(args); // Add configuration var configuration = builder.Configuration; // Add services to the container. builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }); // Add NodaTime builder.Services.AddSingleton(SystemClock.Instance); // Add database context builder.Services.AddDbContext((serviceProvider, options) => { var connectionString = configuration.GetConnectionString("DefaultConnection"); if (string.IsNullOrEmpty(connectionString)) { throw new InvalidOperationException("Database connection string 'DefaultConnection' not found."); } options.UseNpgsql( connectionString, npgsqlOptions => { npgsqlOptions.UseNodaTime(); npgsqlOptions.MigrationsAssembly(typeof(Program).Assembly.FullName); }); options.UseSnakeCaseNamingConvention(); }); // Register services builder.Services.AddScoped(); builder.Services.AddScoped(); // Configure CORS builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => { policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); // Configure JWT Authentication builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = configuration["Jwt:Authority"]; options.Audience = configuration["Jwt:Audience"]; options.RequireHttpsMetadata = !builder.Environment.IsDevelopment(); }); // Configure Swagger builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "DysonNetwork.Drive API", Version = "v1", Description = "API for managing files and file references in the Dyson Network", Contact = new OpenApiContact { Name = "Dyson Network Team", Email = "support@dyson.network" } }); // Include XML comments for API documentation var xmlFile = $"{typeof(Program).Assembly.GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); if (File.Exists(xmlPath)) { c.IncludeXmlComments(xmlPath); } // Configure JWT Bearer Authentication for Swagger c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, Scheme = "oauth2", Name = "Bearer", In = ParameterLocation.Header, }, Array.Empty() } }); }); // Configure HTTP client for external services builder.Services.AddHttpClient(); // Add health checks builder.Services.AddHealthChecks() .AddDbContextCheck(); // Add logging builder.Services.AddLogging(configure => configure.AddConsole().AddDebug()); // Build the application var app = builder.Build(); // Configure the HTTP request pipeline if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "DysonNetwork.Drive API v1"); c.RoutePrefix = "swagger"; }); } // Apply database migrations using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; try { var dbContext = services.GetRequiredService(); if (dbContext.Database.IsNpgsql()) { await dbContext.Database.MigrateAsync(); app.Logger.LogInformation("Database migrations applied successfully."); } } catch (Exception ex) { var logger = services.GetRequiredService>(); logger.LogError(ex, "An error occurred while applying database migrations."); throw; } } app.UseHttpsRedirection(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapHealthChecks("/health"); app.Logger.LogInformation("Starting DysonNetwork.Drive application..."); await app.RunAsync();