Refactor runtime bootstrap and ship control flows

This commit is contained in:
2026-04-03 01:12:26 -04:00
parent 0bb72bee35
commit 706e1cda8f
129 changed files with 9588 additions and 3548 deletions

View File

@@ -1,11 +1,14 @@
using System.Text;
using FastEndpoints;
using FastEndpoints.Swagger;
using SpaceGame.Api.Universe.Scenario;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Npgsql;
using SpaceGame.Api.Universe.Bootstrap;
using SpaceGame.Api.Universe.Simulation;
const string StartupScenarioPath = "scenarios/empty.json";
var builder = WebApplication.CreateBuilder(args);
const string StartupScenarioPath = "scenarios/empty.json";
builder.Services.AddCors((options) =>
{
@@ -46,10 +49,67 @@ builder.Services
})
.ValidateOnStart();
builder.Services.Configure<BalanceOptions>(builder.Configuration.GetSection("Balance"));
builder.Services.Configure<WorldGenerationOptions>(builder.Configuration.GetSection("WorldGeneration"));
builder.Services.Configure<OrbitalSimulationOptions>(builder.Configuration.GetSection("OrbitalSimulation"));
builder.Services
.AddOptions<AuthOptions>()
.Bind(builder.Configuration.GetSection("Auth"))
.Validate(options => !string.IsNullOrWhiteSpace(options.ConnectionString), "Auth:ConnectionString must be configured.")
.ValidateOnStart();
builder.Services
.AddOptions<JwtOptions>()
.Bind(builder.Configuration.GetSection("Jwt"))
.Validate(options => !string.IsNullOrWhiteSpace(options.SigningKey), "Jwt:SigningKey must be configured.")
.ValidateOnStart();
var jwtOptions = builder.Configuration.GetSection("Jwt").Get<JwtOptions>() ?? new JwtOptions();
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SigningKey));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidIssuer = jwtOptions.Issuer,
ValidAudience = jwtOptions.Audience,
IssuerSigningKey = signingKey,
ClockSkew = TimeSpan.FromSeconds(30),
};
});
builder.Services
.AddAuthorizationBuilder()
.AddPolicy(AuthPolicyNames.AdminAccess, policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireRole(AuthRoleNames.Admin);
})
.AddPolicy(AuthPolicyNames.GmAccess, policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireRole(AuthRoleNames.Gm);
});
builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<IBalanceService, BalanceService>();
builder.Services.AddSingleton<AppVersionService>();
builder.Services.AddSingleton<IPlayerStateStore, PlayerStateStore>();
builder.Services.AddSingleton<PlayerFactionProjectionService>();
builder.Services.AddSingleton<LocalPasswordHasher>();
builder.Services.AddSingleton<RefreshTokenFactory>();
builder.Services.AddSingleton<ITokenService, JwtTokenService>();
builder.Services.AddSingleton<IPasswordResetDelivery, DevPasswordResetDelivery>();
builder.Services.AddSingleton<IPlayerIdentityResolver, HttpContextPlayerIdentityResolver>();
builder.Services.AddSingleton((serviceProvider) =>
{
var authOptions = serviceProvider.GetRequiredService<Microsoft.Extensions.Options.IOptions<AuthOptions>>();
return new NpgsqlDataSourceBuilder(authOptions.Value.ConnectionString).Build();
});
builder.Services.AddSingleton<IAuthRepository, PostgresAuthRepository>();
builder.Services.AddSingleton<AuthService>();
builder.Services.AddSingleton<AuthSchemaInitializer>();
builder.Services.AddSingleton<DevAuthSeeder>();
builder.Services.AddTransient<SystemGenerationService>();
builder.Services.AddTransient<SpatialBuilder>();
builder.Services.AddTransient<WorldSeedingService>();
@@ -68,9 +128,16 @@ builder.Services.AddFastEndpoints();
builder.Services.SwaggerDocument();
var app = builder.Build();
app.Services.GetRequiredService<WorldService>().LoadFromScenario(StartupScenarioPath);
await app.Services.GetRequiredService<AuthSchemaInitializer>().EnsureSchemaAsync(CancellationToken.None);
if (builder.Environment.IsDevelopment())
{
await app.Services.GetRequiredService<DevAuthSeeder>().SeedAsync(CancellationToken.None);
app.Services.GetRequiredService<WorldService>().LoadFromScenario(StartupScenarioPath);
}
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseFastEndpoints();
app.UseSwaggerGen();