Files
tiku-backend.net/Tiku.DbMigrator/Program.cs
xiong 603bc24c26
Some checks are pending
ci / release-gate (push) Waiting to run
feat(cache): adopt FusionCache for business caching
2026-08-05 09:30:48 +08:00

76 lines
3.7 KiB
C#

using Microsoft.AspNetCore.DataProtection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Tiku.Application;
using Tiku.Application.Security;
using Tiku.Infrastructure;
using Tiku.Infrastructure.Bootstrap;
using Tiku.Infrastructure.Caching;
using Tiku.Infrastructure.Persistence;
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);
var skipDevelopmentSeed = args.Contains("--skip-development-seed", 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.AddAuthentication();
builder.Services.AddInfrastructure(
connectionString,
isDevelopment && !bootstrapPlatformAdmin && !skipDevelopmentSeed
? DevelopmentPlatformAdminSeeder.Configure
: null);
builder.Services.AddBusinessCaching(builder.Environment.EnvironmentName, false);
// Resolving UserManager<User> 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();
scope.ServiceProvider.GetRequiredService<ITenantContextInitializer>()
.InitializeSystem(null, "Database migration and bootstrap");
var dbContext = scope.ServiceProvider.GetRequiredService<TikuDbContext>();
await dbContext.Database.MigrateAsync();
var catalogSeeder = ActivatorUtilities.CreateInstance<BuiltinBackofficeCatalogSeeder>(scope.ServiceProvider);
await catalogSeeder.SeedAsync();
var starterOfferingSeeder = ActivatorUtilities.CreateInstance<BuiltinStarterOfferingSeeder>(scope.ServiceProvider);
await starterOfferingSeeder.SeedAsync();
if (bootstrapOptions is not null)
{
var bootstrapper = ActivatorUtilities.CreateInstance<PlatformAdminBootstrapper>(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.");
}