本轮完成了完整的通知公告管理迁移:
原生 GET /api/admin/notices
原生五类系统公示聚合:计划、资格、录取、分数线、报到
原生 PATCH /api/admin/publications/{type}/{id} 显隐控制
权限、事务审计和 Node 返回结构保持一致
开关升级为 ADMIN_NATIVE_NOTICE_MANAGEMENT_ENABLED
兼容旧变量 ADMIN_NATIVE_NOTICE_WRITES_ENABLED
冒烟脚本现在会自动构建 Web,避免使用过期程序集
This commit is contained in:
1 parent
9e21a277f0
commit
e845ba8d3a
13 files changed
+597
-37
No files matched your search
+2
-2
@@ -33,8 +33,8 @@ ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED=false
|
|||||||
ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED=false
|
ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED=false
|
||||||
# 报名号规则与审批流程定义维护;必须同时启用管理端只读接口。
|
# 报名号规则与审批流程定义维护;必须同时启用管理端只读接口。
|
||||||
ADMIN_NATIVE_CONFIGURATION_ENABLED=false
|
ADMIN_NATIVE_CONFIGURATION_ENABLED=false
|
||||||
# 手工通知公告创建和修改;公告列表及系统公示暂时仍由 Node 提供。
|
# 通知公告列表、手工公告创建修改及系统公示显隐控制;必须同时启用管理端只读接口。
|
||||||
ADMIN_NATIVE_NOTICE_WRITES_ENABLED=false
|
ADMIN_NATIVE_NOTICE_MANAGEMENT_ENABLED=false
|
||||||
|
|
||||||
# 仅在首次创建空数据库时使用。部署前务必修改初始密码。
|
# 仅在首次创建空数据库时使用。部署前务必修改初始密码。
|
||||||
INITIAL_ADMIN_USERNAME=admin
|
INITIAL_ADMIN_USERNAME=admin
|
||||||
|
|||||||
+4
-4
@@ -12,7 +12,7 @@
|
|||||||
- [x] 招生公示与 HMAC 文书验真公开接口
|
- [x] 招生公示与 HMAC 文书验真公开接口
|
||||||
- [x] 登录、自主注册、Session 与 TOTP(兼容开关默认关闭)
|
- [x] 登录、自主注册、Session 与 TOTP(兼容开关默认关闭)
|
||||||
- [x] 考生业务
|
- [x] 考生业务
|
||||||
- [ ] 管理后台、审批流和考务编排(管理端读取、组织维护、批量报名号审批、流程配置及手工公告写入已原生化)
|
- [ ] 管理后台、审批流和考务编排(管理端读取、组织维护、批量报名号审批、流程配置及通知公告管理已原生化)
|
||||||
- [x] 考生志愿填报与招生录取查询
|
- [x] 考生志愿填报与招生录取查询
|
||||||
- [ ] Excel、文书和缓存
|
- [ ] Excel、文书和缓存
|
||||||
- [ ] 容器入口切换及 Node.js 后端移除
|
- [ ] 容器入口切换及 Node.js 后端移除
|
||||||
@@ -54,7 +54,7 @@ $env:AUTH_NATIVE_ENABLED = 'true'
|
|||||||
$env:CANDIDATE_NATIVE_ENABLED = 'true'
|
$env:CANDIDATE_NATIVE_ENABLED = 'true'
|
||||||
```
|
```
|
||||||
|
|
||||||
管理后台第一批只读接口(管理上下文、仪表盘、学校、学校组织、管理员和考试列表)已经原生化,并保留超级、校级、班级管理员的权限与数据作用域。第二批覆盖学校、班级和管理员的创建与维护、管理员密码重置及自主注册开关;更新操作与审计日志在同一事务中提交,停用或重置管理员会同步失效其会话。第三批覆盖批量报名号申领的读取、提交和审批,终审会按照当前号码规则原子生成考生账号、初始密码和待补录资料。第四批覆盖报名号规则及审批流程定义的读取与维护,并保留流程层级和批量申领终审约束。第五批覆盖超级管理员创建和编辑手工公告,包含 HTML 净化、草稿发布状态及事务内审计;管理端公告列表与系统自动发布内容暂时仍由 Node 处理。
|
管理后台第一批只读接口(管理上下文、仪表盘、学校、学校组织、管理员和考试列表)已经原生化,并保留超级、校级、班级管理员的权限与数据作用域。第二批覆盖学校、班级和管理员的创建与维护、管理员密码重置及自主注册开关;更新操作与审计日志在同一事务中提交,停用或重置管理员会同步失效其会话。第三批覆盖批量报名号申领的读取、提交和审批,终审会按照当前号码规则原子生成考生账号、初始密码和待补录资料。第四批覆盖报名号规则及审批流程定义的读取与维护,并保留流程层级和批量申领终审约束。第五批覆盖完整通知公告管理:超级管理员可读取手工公告与五类系统公示、创建和编辑手工公告,并控制系统公示是否公开显示;HTML 净化、显隐更新和审计日志均由 ASP.NET Core 原生处理。
|
||||||
|
|
||||||
其余审批流和考务编排接口仍转发给 Node,因此管理端开关都要求原生认证和共享 Redis;各写入子功能还必须与只读开关一起启用:
|
其余审批流和考务编排接口仍转发给 Node,因此管理端开关都要求原生认证和共享 Redis;各写入子功能还必须与只读开关一起启用:
|
||||||
|
|
||||||
@@ -64,10 +64,10 @@ $env:ADMIN_NATIVE_READS_ENABLED = 'true'
|
|||||||
$env:ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED = 'true'
|
$env:ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED = 'true'
|
||||||
$env:ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED = 'true'
|
$env:ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED = 'true'
|
||||||
$env:ADMIN_NATIVE_CONFIGURATION_ENABLED = 'true'
|
$env:ADMIN_NATIVE_CONFIGURATION_ENABLED = 'true'
|
||||||
$env:ADMIN_NATIVE_NOTICE_WRITES_ENABLED = 'true'
|
$env:ADMIN_NATIVE_NOTICE_MANAGEMENT_ENABLED = 'true'
|
||||||
```
|
```
|
||||||
|
|
||||||
`GET /health/migration` 的 `administration.nativeReadsEnabled`、`administration.nativeOrganizationWritesEnabled`、`administration.nativeAccountBatchesEnabled`、`administration.nativeConfigurationEnabled`、`administration.nativeNoticeWritesEnabled` 和 `administration.nativeRoutes` 会报告这些端点是否已切换。
|
旧版 `ADMIN_NATIVE_NOTICE_WRITES_ENABLED` 仍可作为兼容别名使用。`GET /health/migration` 的 `administration.nativeReadsEnabled`、`administration.nativeOrganizationWritesEnabled`、`administration.nativeAccountBatchesEnabled`、`administration.nativeConfigurationEnabled`、`administration.nativeNoticeManagementEnabled` 和 `administration.nativeRoutes` 会报告这些端点是否已切换。
|
||||||
|
|
||||||
完整的宿主、静态资源、JSON 转发和 Session Cookie 冒烟测试:
|
完整的宿主、静态资源、JSON 转发和 Session Cookie 冒烟测试:
|
||||||
|
|
||||||
|
|||||||
@@ -249,9 +249,23 @@ try {
|
|||||||
}
|
}
|
||||||
$registrationSwitchProcess.Dispose()
|
$registrationSwitchProcess.Dispose()
|
||||||
|
|
||||||
$nodeProcess = Start-TestProcess -FileName $nodeExecutable -ArgumentList @('server.mjs') -Environment $nodeEnvironment
|
|
||||||
|
|
||||||
$projectPath = Join-Path $repositoryRoot 'src\Eis.Web\Eis.Web.csproj'
|
$projectPath = Join-Path $repositoryRoot 'src\Eis.Web\Eis.Web.csproj'
|
||||||
|
$buildProcess = Start-TestProcess -FileName $dotnetExecutable -ArgumentList @(
|
||||||
|
'build', $projectPath,
|
||||||
|
'--configuration', 'Release'
|
||||||
|
) -Environment @{}
|
||||||
|
if (-not $buildProcess.WaitForExit(60000)) {
|
||||||
|
$buildProcess.Kill($true)
|
||||||
|
throw 'Timed out while building the ASP.NET Core migration host'
|
||||||
|
}
|
||||||
|
$buildOutput = $buildProcess.StandardOutput.ReadToEnd()
|
||||||
|
$buildError = $buildProcess.StandardError.ReadToEnd()
|
||||||
|
if ($buildProcess.ExitCode -ne 0) {
|
||||||
|
throw "Failed to build the ASP.NET Core migration host`n$buildOutput`n$buildError"
|
||||||
|
}
|
||||||
|
$buildProcess.Dispose()
|
||||||
|
|
||||||
|
$nodeProcess = Start-TestProcess -FileName $nodeExecutable -ArgumentList @('server.mjs') -Environment $nodeEnvironment
|
||||||
$dotnetProcess = Start-TestProcess -FileName $dotnetExecutable -ArgumentList @(
|
$dotnetProcess = Start-TestProcess -FileName $dotnetExecutable -ArgumentList @(
|
||||||
'run',
|
'run',
|
||||||
'--project', $projectPath,
|
'--project', $projectPath,
|
||||||
@@ -426,7 +440,7 @@ try {
|
|||||||
ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED = 'true'
|
ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED = 'true'
|
||||||
ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED = 'true'
|
ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED = 'true'
|
||||||
ADMIN_NATIVE_CONFIGURATION_ENABLED = 'true'
|
ADMIN_NATIVE_CONFIGURATION_ENABLED = 'true'
|
||||||
ADMIN_NATIVE_NOTICE_WRITES_ENABLED = 'true'
|
ADMIN_NATIVE_NOTICE_MANAGEMENT_ENABLED = 'true'
|
||||||
ADMIN_NATIVE_ALLOW_MEMORY = 'true'
|
ADMIN_NATIVE_ALLOW_MEMORY = 'true'
|
||||||
LegacyNode__Enabled = 'true'
|
LegacyNode__Enabled = 'true'
|
||||||
LegacyNode__BaseUrl = $legacyBaseUrl
|
LegacyNode__BaseUrl = $legacyBaseUrl
|
||||||
@@ -726,6 +740,52 @@ try {
|
|||||||
throw "Native admin route '$superOnlyRoute' did not preserve the super-admin boundary"
|
throw "Native admin route '$superOnlyRoute' did not preserve the super-admin boundary"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$legacyNoticeManagement = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/notices" -WebSession $session
|
||||||
|
$nativeNoticeManagement = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/notices" -WebSession $nativeSession
|
||||||
|
if ($nativeNoticeManagement.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||||
|
throw 'Native notice management list did not use ASP.NET Core'
|
||||||
|
}
|
||||||
|
Assert-JsonEquivalent -Expected $legacyNoticeManagement.Content -Actual $nativeNoticeManagement.Content -Label 'Admin notice management list'
|
||||||
|
$schoolNoticeManagementForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/notices" -WebSession $nativeSchoolSession -SkipHttpErrorCheck
|
||||||
|
if ($schoolNoticeManagementForbidden.StatusCode -ne 403 -or $schoolNoticeManagementForbidden.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||||
|
throw 'Native notice management list did not preserve the super-admin boundary'
|
||||||
|
}
|
||||||
|
|
||||||
|
$noticeManagementState = $nativeNoticeManagement.Content | ConvertFrom-Json
|
||||||
|
$managedPlan = @($noticeManagementState.publications | Where-Object { $_.sourceType -eq 'plan' })[0]
|
||||||
|
if ($null -eq $managedPlan) {
|
||||||
|
throw 'Seed data did not provide a system plan publication for notice-management smoke testing'
|
||||||
|
}
|
||||||
|
$invalidPublicationVisibility = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/publications/plan/$($managedPlan.id)" -Method Patch -ContentType 'application/json' -Body (@{ visible = 'false' } | ConvertTo-Json -Compress) -WebSession $nativeSession -SkipHttpErrorCheck
|
||||||
|
if ($invalidPublicationVisibility.StatusCode -ne 400 -or $invalidPublicationVisibility.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||||
|
throw 'Native system-publication update accepted a non-boolean visibility value'
|
||||||
|
}
|
||||||
|
$missingPublication = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/publications/plan/missing-publication" -Method Patch -ContentType 'application/json' -Body (@{ visible = $false } | ConvertTo-Json -Compress) -WebSession $nativeSession -SkipHttpErrorCheck
|
||||||
|
if ($missingPublication.StatusCode -ne 404) {
|
||||||
|
throw 'Native system-publication update did not return 404 for a missing record'
|
||||||
|
}
|
||||||
|
$schoolPublicationForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/publications/plan/$($managedPlan.id)" -Method Patch -ContentType 'application/json' -Body (@{ visible = $false } | ConvertTo-Json -Compress) -WebSession $nativeSchoolSession -SkipHttpErrorCheck
|
||||||
|
if ($schoolPublicationForbidden.StatusCode -ne 403) {
|
||||||
|
throw 'Native system-publication update did not preserve the super-admin boundary'
|
||||||
|
}
|
||||||
|
$hiddenPublicationResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/publications/plan/$($managedPlan.id)" -Method Patch -ContentType 'application/json' -Body (@{ visible = $false } | ConvertTo-Json -Compress) -WebSession $nativeSession
|
||||||
|
$hiddenPublication = ($hiddenPublicationResponse.Content | ConvertFrom-Json).publication
|
||||||
|
if ($hiddenPublicationResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core' -or $hiddenPublication.visible -ne $false -or $hiddenPublication.status -ne 'hidden') {
|
||||||
|
throw 'Native system-publication update did not hide the requested publication'
|
||||||
|
}
|
||||||
|
$hiddenAnnouncements = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/public/announcements"
|
||||||
|
if (@($hiddenAnnouncements.plans | Where-Object { $_.id -eq $managedPlan.id }).Count -ne 0) {
|
||||||
|
throw 'Native public announcements still exposed a hidden system publication'
|
||||||
|
}
|
||||||
|
$restoredPublicationResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/publications/plan/$($managedPlan.id)" -Method Patch -ContentType 'application/json' -Body (@{ visible = $true } | ConvertTo-Json -Compress) -WebSession $nativeSession
|
||||||
|
$restoredPublication = ($restoredPublicationResponse.Content | ConvertFrom-Json).publication
|
||||||
|
if ($restoredPublication.visible -ne $true -or $restoredPublication.status -ne 'visible') {
|
||||||
|
throw 'Native system-publication update did not restore the requested publication'
|
||||||
|
}
|
||||||
|
$restoredAnnouncements = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/public/announcements"
|
||||||
|
if (@($restoredAnnouncements.plans | Where-Object { $_.id -eq $managedPlan.id }).Count -ne 1) {
|
||||||
|
throw 'Native public announcements did not restore a visible system publication'
|
||||||
|
}
|
||||||
$classLoginBody = @{ username = 'class_admin'; password = '12345678' } | ConvertTo-Json -Compress
|
$classLoginBody = @{ username = 'class_admin'; password = '12345678' } | ConvertTo-Json -Compress
|
||||||
$legacyClassSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
$legacyClassSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||||
$nativeClassSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
$nativeClassSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||||
@@ -1082,7 +1142,7 @@ try {
|
|||||||
NativeAdminOrganizationWrites = 'passed'
|
NativeAdminOrganizationWrites = 'passed'
|
||||||
NativeAdminAccountBatches = 'passed'
|
NativeAdminAccountBatches = 'passed'
|
||||||
NativeAdminConfiguration = 'passed'
|
NativeAdminConfiguration = 'passed'
|
||||||
NativeAdminNoticeWrites = 'passed'
|
NativeAdminNoticeManagement = 'passed'
|
||||||
} | Format-List
|
} | Format-List
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|||||||
Loaded 3 of 13 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user