Files
EIS-dotnet/src/Eis.Web/Program.cs
T
biss 875e59b6ce 已完成管理后台第二批 ASP.NET Core 10 迁移:
学校创建、修改
班级创建、修改
管理员创建、修改
管理员密码重置
自主注册开关
写入与审计日志保持同一事务
停用或重置管理员后自动清除其会话
2026-07-23 08:08:26 +08:00

143 lines
5.7 KiB
C#

using System.Net;
using Eis.Infrastructure.Authentication;
using Eis.Infrastructure.Administration;
using Eis.Infrastructure.Candidate;
using Eis.Application.Public;
using Eis.Infrastructure;
using Eis.Infrastructure.Data;
using Eis.Infrastructure.Migration;
using Eis.Infrastructure.Security;
using Eis.Web.Configuration;
using Eis.Web.Authentication;
using Eis.Web.Administration;
using Eis.Web.Candidate;
using Eis.Web.Frontend;
using Eis.Web.Legacy;
using Eis.Web.Public;
var applicationRoot = ApplicationPaths.FindApplicationRoot();
EnvironmentFile.Load(applicationRoot);
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options => options.AddServerHeader = false);
builder.Services.Configure<LegacyNodeOptions>(builder.Configuration.GetSection(LegacyNodeOptions.SectionName));
builder.Services.AddHttpClient<LegacyApiProxy>((services, client) =>
{
var options = services.GetRequiredService<Microsoft.Extensions.Options.IOptions<LegacyNodeOptions>>().Value;
client.BaseAddress = options.BaseUrl;
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.UserAgent.ParseAdd("Eis.AspNetCore.Migration/1.0");
}).ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
UseCookies = false
});
builder.Services.AddProblemDetails();
builder.Services.AddSingleton<IPublicSiteConfiguration, PublicSiteConfiguration>();
var authenticationOptions = AuthenticationOptions.FromEnvironment(
builder.Environment.IsProduction(),
builder.Configuration.GetValue<bool>("AuthenticationMigration:NativeEnabled"));
var candidateMigrationOptions = CandidateMigrationOptions.FromEnvironment(
builder.Configuration.GetValue<bool>("CandidateMigration:NativeEnabled"),
authenticationOptions.NativeEnabled,
authenticationOptions.SharesLegacySessions);
var adminMigrationOptions = AdminMigrationOptions.FromEnvironment(
builder.Configuration.GetValue<bool>("AdminMigration:NativeReadsEnabled"),
authenticationOptions.NativeEnabled,
authenticationOptions.SharesLegacySessions,
builder.Configuration.GetValue<bool>("AdminMigration:NativeOrganizationWritesEnabled"));
builder.Services.AddEisInfrastructure(
DatabaseOptions.FromEnvironment(applicationRoot, builder.Environment.IsProduction()),
DocumentVerificationOptions.FromEnvironment(builder.Environment.IsProduction()),
authenticationOptions,
candidateMigrationOptions,
adminMigrationOptions);
var app = builder.Build();
app.Services.EnsureNativeAuthenticationReady(authenticationOptions);
app.UseExceptionHandler();
app.Use(async (context, next) =>
{
context.Response.Headers.XContentTypeOptions = "nosniff";
context.Response.Headers.XFrameOptions = "DENY";
context.Response.Headers["Referrer-Policy"] = "same-origin";
await next();
});
app.MapGet("/health/live", () => Results.Json(new
{
status = "healthy",
service = "Eis.Web",
framework = ".NET 10"
}));
app.MapGet("/health/migration", async (LegacyApiProxy proxy, CancellationToken cancellationToken) =>
{
var legacyAvailable = await proxy.IsAvailableAsync(cancellationToken);
var statusCode = legacyAvailable ? StatusCodes.Status200OK : StatusCodes.Status503ServiceUnavailable;
return Results.Json(new
{
status = legacyAvailable ? "healthy" : "degraded",
legacyApiAvailable = legacyAvailable,
authentication = new
{
nativeEnabled = authenticationOptions.NativeEnabled,
stateBackend = authenticationOptions.UsesRedis ? "redis" : "memory",
sharesLegacySessions = authenticationOptions.SharesLegacySessions
},
candidate = new
{
nativeEnabled = candidateMigrationOptions.NativeEnabled,
nativeRoutes = candidateMigrationOptions.NativeEnabled
? new[]
{
"GET dashboard", "GET notices", "GET/PUT profile", "GET exams", "GET/POST registrations",
"GET results", "POST result appeals", "GET admit cards", "GET admissions", "PUT admission preferences"
}
: []
},
administration = new
{
nativeReadsEnabled = adminMigrationOptions.NativeReadsEnabled,
nativeOrganizationWritesEnabled = adminMigrationOptions.NativeOrganizationWritesEnabled,
nativeRoutes = (adminMigrationOptions.NativeReadsEnabled
? new[] { "GET context", "GET dashboard", "GET schools", "GET school-organization", "GET admins", "GET exams" }
: [])
.Concat(adminMigrationOptions.NativeOrganizationWritesEnabled
? new[]
{
"POST/PATCH schools", "POST/PATCH classes", "POST/PATCH admins",
"POST admin password reset", "PUT self-registration setting"
}
: [])
.ToArray()
},
features = MigrationFeatureCatalog.Current(authenticationOptions.NativeEnabled, candidateMigrationOptions.NativeEnabled)
}, statusCode: statusCode);
});
app.MapNativePublicEndpoints();
app.MapNativeAuthenticationEndpoints(authenticationOptions);
app.MapNativeCandidateEndpoints(candidateMigrationOptions);
app.MapNativeAdminReadEndpoints(adminMigrationOptions);
string[] methods =
[
HttpMethods.Get,
HttpMethods.Head,
HttpMethods.Post,
HttpMethods.Put,
HttpMethods.Patch,
HttpMethods.Delete,
HttpMethods.Options
];
app.MapMethods("/api/{**path}", methods, (HttpContext context, LegacyApiProxy proxy) => proxy.ForwardAsync(context));
app.MapFrontendAssets();
app.Run();
public partial class Program;