新增 POST /api/admin/notices、PATCH /api/admin/notices/{id}

保留超级管理员权限边界
支持草稿、发布、置顶、自动摘要
HTML 净化,拦截脚本和危险链接
公告更新与审计日志同事务提交
新增开关 ADMIN_NATIVE_NOTICE_WRITES_ENABLED=false
管理端公告列表和系统自动公告暂时仍由 Node 处理
This commit is contained in:
2026-07-23 08:41:53 +08:00 Unverified
parent 3665aa3aa9
commit 9e21a277f0
14 changed files with 350 additions and 21 deletions
@@ -55,15 +55,23 @@ public static class NativeAdminReadEndpoints
Execute(context, service.ReviewAsync(Token(context), batchId, body, cancellationToken)));
}
if (!options.NativeConfigurationEnabled) return endpoints;
endpoints.MapGet("/api/admin/number-rules", (HttpContext context, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.GetNumberRulesAsync(Token(context), cancellationToken)));
endpoints.MapPost("/api/admin/number-rules", (HttpContext context, JsonObject body, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.SaveNumberRuleAsync(Token(context), body, cancellationToken)));
endpoints.MapGet("/api/admin/workflows", (HttpContext context, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.GetWorkflowsAsync(Token(context), cancellationToken)));
endpoints.MapPut("/api/admin/workflows/{businessType}", (HttpContext context, string businessType, JsonObject body, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.SaveWorkflowAsync(Token(context), businessType, body, cancellationToken)));
if (options.NativeConfigurationEnabled)
{
endpoints.MapGet("/api/admin/number-rules", (HttpContext context, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.GetNumberRulesAsync(Token(context), cancellationToken)));
endpoints.MapPost("/api/admin/number-rules", (HttpContext context, JsonObject body, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.SaveNumberRuleAsync(Token(context), body, cancellationToken)));
endpoints.MapGet("/api/admin/workflows", (HttpContext context, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.GetWorkflowsAsync(Token(context), cancellationToken)));
endpoints.MapPut("/api/admin/workflows/{businessType}", (HttpContext context, string businessType, JsonObject body, IAdminConfigurationService service, CancellationToken cancellationToken) =>
Execute(context, service.SaveWorkflowAsync(Token(context), businessType, body, cancellationToken)));
}
if (!options.NativeNoticeWritesEnabled) return endpoints;
endpoints.MapPost("/api/admin/notices", (HttpContext context, JsonObject body, IAdminNoticeService service, CancellationToken cancellationToken) =>
Execute(context, service.CreateAsync(Token(context), body, cancellationToken)));
endpoints.MapPatch("/api/admin/notices/{noticeId}", (HttpContext context, string noticeId, JsonObject body, IAdminNoticeService service, CancellationToken cancellationToken) =>
Execute(context, service.UpdateAsync(Token(context), noticeId, body, cancellationToken)));
return endpoints;
}
+6 -1
View File
@@ -48,7 +48,8 @@ var adminMigrationOptions = AdminMigrationOptions.FromEnvironment(
authenticationOptions.SharesLegacySessions,
builder.Configuration.GetValue<bool>("AdminMigration:NativeOrganizationWritesEnabled"),
builder.Configuration.GetValue<bool>("AdminMigration:NativeAccountBatchesEnabled"),
builder.Configuration.GetValue<bool>("AdminMigration:NativeConfigurationEnabled"));
builder.Configuration.GetValue<bool>("AdminMigration:NativeConfigurationEnabled"),
builder.Configuration.GetValue<bool>("AdminMigration:NativeNoticeWritesEnabled"));
builder.Services.AddEisInfrastructure(
DatabaseOptions.FromEnvironment(applicationRoot, builder.Environment.IsProduction()),
DocumentVerificationOptions.FromEnvironment(builder.Environment.IsProduction()),
@@ -106,6 +107,7 @@ app.MapGet("/health/migration", async (LegacyApiProxy proxy, CancellationToken c
nativeOrganizationWritesEnabled = adminMigrationOptions.NativeOrganizationWritesEnabled,
nativeAccountBatchesEnabled = adminMigrationOptions.NativeAccountBatchesEnabled,
nativeConfigurationEnabled = adminMigrationOptions.NativeConfigurationEnabled,
nativeNoticeWritesEnabled = adminMigrationOptions.NativeNoticeWritesEnabled,
nativeRoutes = (adminMigrationOptions.NativeReadsEnabled
? new[] { "GET context", "GET dashboard", "GET schools", "GET school-organization", "GET admins", "GET exams" }
: [])
@@ -122,6 +124,9 @@ app.MapGet("/health/migration", async (LegacyApiProxy proxy, CancellationToken c
.Concat(adminMigrationOptions.NativeConfigurationEnabled
? new[] { "GET/POST number-rules", "GET/PUT workflows" }
: [])
.Concat(adminMigrationOptions.NativeNoticeWritesEnabled
? new[] { "POST/PATCH notices" }
: [])
.ToArray()
},
features = MigrationFeatureCatalog.Current(authenticationOptions.NativeEnabled, candidateMigrationOptions.NativeEnabled)
+2 -1
View File
@@ -13,7 +13,8 @@
"NativeReadsEnabled": false,
"NativeOrganizationWritesEnabled": false,
"NativeAccountBatchesEnabled": false,
"NativeConfigurationEnabled": false
"NativeConfigurationEnabled": false,
"NativeNoticeWritesEnabled": false
},
"Logging": {
"LogLevel": {