using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Tiku.Infrastructure; using Tiku.Infrastructure.Persistence; using Tiku.Infrastructure.Bootstrap; using Tiku.Application; var builder = Host.CreateApplicationBuilder(args); builder.Logging.AddFilter("Microsoft.EntityFrameworkCore", LogLevel.Warning); var isDevelopment = builder.Environment.IsDevelopment() || string.Equals( Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), Environments.Development, StringComparison.OrdinalIgnoreCase); var bootstrapPlatformAdmin = args.Contains("--bootstrap-platform-admin", StringComparer.Ordinal); PlatformAdminBootstrapOptions? bootstrapOptions = null; if (bootstrapPlatformAdmin) { bootstrapOptions = new PlatformAdminBootstrapOptions( RequiredBootstrapSetting(builder.Configuration, "TIKU_BOOTSTRAP_PLATFORM_ADMIN_EMAIL"), RequiredBootstrapSetting(builder.Configuration, "TIKU_BOOTSTRAP_PLATFORM_ADMIN_PASSWORD"), builder.Configuration["TIKU_BOOTSTRAP_PLATFORM_ADMIN_NAME"]); } var connectionString = builder.Configuration.GetConnectionString("Database") ?? Environment.GetEnvironmentVariable("DATABASE_URL") ?? (isDevelopment ? $"Host=localhost;Database=tiku;Username={Environment.UserName}" : throw new InvalidOperationException( "Database connection is required outside Development. Configure ConnectionStrings:Database or DATABASE_URL.")); builder.Services.AddApplication(); builder.Services.AddInfrastructure( connectionString, isDevelopment && !bootstrapPlatformAdmin ? DevelopmentPlatformAdminSeeder.Configure : null); // Resolving UserManager also activates Identity's default token providers. // Bootstrap never issues a reset token, so the migrator uses a process-local provider; // the API remains the sole owner of the persisted, certificate-protected key ring. builder.Services.AddDataProtection().UseEphemeralDataProtectionProvider(); using var host = builder.Build(); await using var scope = host.Services.CreateAsyncScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); await dbContext.Database.MigrateAsync(); if (bootstrapOptions is not null) { var bootstrapper = ActivatorUtilities.CreateInstance(scope.ServiceProvider); var result = await bootstrapper.BootstrapAsync(bootstrapOptions); Console.WriteLine($"Platform administrator '{result.Email}' was created and must change the temporary password at first sign-in."); } static string RequiredBootstrapSetting(IConfiguration configuration, string key) { return configuration[key] is { } value && !string.IsNullOrWhiteSpace(value) ? value : throw new InvalidOperationException($"{key} is required with --bootstrap-platform-admin."); }