using Microsoft.EntityFrameworkCore; using Nexus.Api.Data; using Nexus.Api.Helpers; using Nexus.Api.Middleware; using Nexus.Api.Services; namespace Nexus.Api.Extensions; /// /// Extension methods for configuring the Nexus application pipeline and startup. /// public static class ApplicationBuilderExtensions { /// /// Applies pending EF Core migrations and seeds the initial owner account if none exist. /// public static async Task EnsureDatabaseAsync(this WebApplication app) { var configuration = app.Configuration; await using (var scope = app.Services.CreateAsyncScope()) { var db = scope.ServiceProvider.GetRequiredService(); await db.Database.MigrateAsync(); var ownerEmail = configuration["Owner:Email"]?.Trim().ToLowerInvariant(); var ownerPassword = configuration["Owner:Password"]; var ownerDisplayName = configuration["Owner:DisplayName"]?.Trim(); var hasUsers = await db.Users.AnyAsync(); if (!hasUsers) { if (string.IsNullOrWhiteSpace(ownerEmail)) throw new InvalidOperationException("Owner:Email is required for initial setup."); var initialDisplayName = string.IsNullOrWhiteSpace(ownerDisplayName) ? PasswordHelper.BuildOwnerDisplayName(ownerEmail) : ownerDisplayName; var initialPassword = string.IsNullOrWhiteSpace(ownerPassword) ? PasswordHelper.GenerateTemporaryPassword() : ownerPassword; if (!string.IsNullOrWhiteSpace(ownerPassword) && ownerPassword.Length < 10) throw new InvalidOperationException("Owner:Password must be at least 10 characters when provided explicitly."); db.Users.Add(new NexusUser { Email = ownerEmail, NormalizedEmail = AuthService.NormalizeEmail(ownerEmail), DisplayName = initialDisplayName, PasswordHash = PasswordSecurity.Hash(initialPassword), Role = "owner" }); await db.SaveChangesAsync(); if (string.IsNullOrWhiteSpace(ownerPassword)) { Console.Error.WriteLine($"[nexus] Initial owner credentials generated: displayName={initialDisplayName}, password={initialPassword}"); } } } } /// /// Configures the HTTP middleware pipeline: forwarded headers, rate limiting, auth, security headers, and Swagger in development. /// public static IApplicationBuilder UseNexusPipeline(this IApplicationBuilder app, IWebHostEnvironment env) { app.UseForwardedHeaders(); app.UseRateLimiter(); app.UseAuthentication(); app.UseAuthorization(); app.UseSecurityHeaders(); if (env.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } return app; } }