已完成管理后台第一批只读功能的 ASP.NET Core 10 迁移:
原生接口:context、dashboard、schools、school-organization、admins、exams 保持超级、校级、班级管理员的数据范围及权限隔离 其余管理写入、审批流和考务编排仍由 Node 转发 新增 ADMIN_NATIVE_READS_ENABLED=true 开关,并强制要求原生认证和共享 Redis
This commit is contained in:
1 parent
4b0dae6d71
commit
712bd1a3a2
12 files changed
+894
-5
No files matched your search
@@ -25,6 +25,8 @@ PORT=4173
|
|||||||
AUTH_NATIVE_ENABLED=false
|
AUTH_NATIVE_ENABLED=false
|
||||||
# 第一批考生只读接口切换;必须与 AUTH_NATIVE_ENABLED=true 同时使用。
|
# 第一批考生只读接口切换;必须与 AUTH_NATIVE_ENABLED=true 同时使用。
|
||||||
CANDIDATE_NATIVE_ENABLED=false
|
CANDIDATE_NATIVE_ENABLED=false
|
||||||
|
# 第一批管理端只读接口切换;必须与 AUTH_NATIVE_ENABLED=true 及共享 Redis 同时使用。
|
||||||
|
ADMIN_NATIVE_READS_ENABLED=false
|
||||||
|
|
||||||
# 仅在首次创建空数据库时使用。部署前务必修改初始密码。
|
# 仅在首次创建空数据库时使用。部署前务必修改初始密码。
|
||||||
INITIAL_ADMIN_USERNAME=admin
|
INITIAL_ADMIN_USERNAME=admin
|
||||||
|
|||||||
+12
-3
@@ -11,9 +11,9 @@
|
|||||||
- [x] 公开首页与已发布通知(原生 SQLite / MySQL 读取)
|
- [x] 公开首页与已发布通知(原生 SQLite / MySQL 读取)
|
||||||
- [x] 招生公示与 HMAC 文书验真公开接口
|
- [x] 招生公示与 HMAC 文书验真公开接口
|
||||||
- [x] 登录、自主注册、Session 与 TOTP(兼容开关默认关闭)
|
- [x] 登录、自主注册、Session 与 TOTP(兼容开关默认关闭)
|
||||||
- [ ] 考生业务
|
- [x] 考生业务
|
||||||
- [ ] 管理后台、审批流和考务编排
|
- [ ] 管理后台、审批流和考务编排(第一批管理端只读接口已原生化)
|
||||||
- [ ] 招生录取
|
- [x] 考生志愿填报与招生录取查询
|
||||||
- [ ] Excel、文书和缓存
|
- [ ] Excel、文书和缓存
|
||||||
- [ ] 容器入口切换及 Node.js 后端移除
|
- [ ] 容器入口切换及 Node.js 后端移除
|
||||||
|
|
||||||
@@ -54,6 +54,15 @@ $env:AUTH_NATIVE_ENABLED = 'true'
|
|||||||
$env:CANDIDATE_NATIVE_ENABLED = 'true'
|
$env:CANDIDATE_NATIVE_ENABLED = 'true'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
管理后台第一批只读接口(管理上下文、仪表盘、学校、学校组织、管理员和考试列表)已经原生化,并保留超级、校级、班级管理员的权限与数据作用域。其余管理端写入、审批流和考务编排接口仍转发给 Node,因此该开关同样要求原生认证和共享 Redis:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$env:AUTH_NATIVE_ENABLED = 'true'
|
||||||
|
$env:ADMIN_NATIVE_READS_ENABLED = 'true'
|
||||||
|
```
|
||||||
|
|
||||||
|
`GET /health/migration` 的 `administration.nativeReadsEnabled` 和 `administration.routes` 会报告这一批端点是否已切换。
|
||||||
|
|
||||||
完整的宿主、静态资源、JSON 转发和 Session Cookie 冒烟测试:
|
完整的宿主、静态资源、JSON 转发和 Session Cookie 冒烟测试:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
|
|||||||
@@ -422,6 +422,8 @@ try {
|
|||||||
AUTH_NATIVE_ENABLED = 'true'
|
AUTH_NATIVE_ENABLED = 'true'
|
||||||
CANDIDATE_NATIVE_ENABLED = 'true'
|
CANDIDATE_NATIVE_ENABLED = 'true'
|
||||||
CANDIDATE_NATIVE_ALLOW_MEMORY = 'true'
|
CANDIDATE_NATIVE_ALLOW_MEMORY = 'true'
|
||||||
|
ADMIN_NATIVE_READS_ENABLED = 'true'
|
||||||
|
ADMIN_NATIVE_ALLOW_MEMORY = 'true'
|
||||||
LegacyNode__Enabled = 'true'
|
LegacyNode__Enabled = 'true'
|
||||||
LegacyNode__BaseUrl = $legacyBaseUrl
|
LegacyNode__BaseUrl = $legacyBaseUrl
|
||||||
DATABASE_CLIENT = 'sqlite'
|
DATABASE_CLIENT = 'sqlite'
|
||||||
@@ -692,6 +694,48 @@ try {
|
|||||||
if ($nativeLogin.ok -ne $true -or $nativeLogin.user.username -ne 'admin') {
|
if ($nativeLogin.ok -ne $true -or $nativeLogin.user.username -ne 'admin') {
|
||||||
throw 'Native authentication could not verify the existing Node PBKDF2 account'
|
throw 'Native authentication could not verify the existing Node PBKDF2 account'
|
||||||
}
|
}
|
||||||
|
foreach ($adminReadRoute in @('context', 'dashboard', 'schools', 'admins', 'exams')) {
|
||||||
|
$legacyAdminRead = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/$adminReadRoute" -WebSession $session
|
||||||
|
$nativeAdminRead = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/$adminReadRoute" -WebSession $nativeSession
|
||||||
|
if ($nativeAdminRead.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||||
|
throw "Admin read route '$adminReadRoute' did not use the native ASP.NET Core endpoint"
|
||||||
|
}
|
||||||
|
Assert-JsonEquivalent -Expected $legacyAdminRead.Content -Actual $nativeAdminRead.Content -Label "Admin read route '$adminReadRoute'"
|
||||||
|
}
|
||||||
|
$superSchoolOrganization = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/school-organization" -WebSession $nativeSession -SkipHttpErrorCheck
|
||||||
|
if ($superSchoolOrganization.StatusCode -ne 403 -or $superSchoolOrganization.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||||
|
throw 'Native school-organization route did not preserve the school-level authorization boundary'
|
||||||
|
}
|
||||||
|
$schoolLoginBody = @{ username = 'school_admin'; password = '12345678' } | ConvertTo-Json -Compress
|
||||||
|
$legacySchoolSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||||
|
$nativeSchoolSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||||
|
Invoke-RestMethod -Uri "$legacyBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $schoolLoginBody -WebSession $legacySchoolSession | Out-Null
|
||||||
|
Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $schoolLoginBody -WebSession $nativeSchoolSession | Out-Null
|
||||||
|
foreach ($schoolAdminRoute in @('context', 'dashboard', 'school-organization', 'admins')) {
|
||||||
|
$legacySchoolRead = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/$schoolAdminRoute" -WebSession $legacySchoolSession
|
||||||
|
$nativeSchoolRead = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/$schoolAdminRoute" -WebSession $nativeSchoolSession
|
||||||
|
Assert-JsonEquivalent -Expected $legacySchoolRead.Content -Actual $nativeSchoolRead.Content -Label "School admin read route '$schoolAdminRoute'"
|
||||||
|
}
|
||||||
|
foreach ($superOnlyRoute in @('schools', 'exams')) {
|
||||||
|
$schoolForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/$superOnlyRoute" -WebSession $nativeSchoolSession -SkipHttpErrorCheck
|
||||||
|
if ($schoolForbidden.StatusCode -ne 403 -or $schoolForbidden.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||||
|
throw "Native admin route '$superOnlyRoute' did not preserve the super-admin boundary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$classLoginBody = @{ username = 'class_admin'; password = '12345678' } | ConvertTo-Json -Compress
|
||||||
|
$legacyClassSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||||
|
$nativeClassSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||||
|
Invoke-RestMethod -Uri "$legacyBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $classLoginBody -WebSession $legacyClassSession | Out-Null
|
||||||
|
Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $classLoginBody -WebSession $nativeClassSession | Out-Null
|
||||||
|
foreach ($classAdminRoute in @('context', 'dashboard')) {
|
||||||
|
$legacyClassRead = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/$classAdminRoute" -WebSession $legacyClassSession
|
||||||
|
$nativeClassRead = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/$classAdminRoute" -WebSession $nativeClassSession
|
||||||
|
Assert-JsonEquivalent -Expected $legacyClassRead.Content -Actual $nativeClassRead.Content -Label "Class admin read route '$classAdminRoute'"
|
||||||
|
}
|
||||||
|
$classAdminsForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/admins" -WebSession $nativeClassSession -SkipHttpErrorCheck
|
||||||
|
if ($classAdminsForbidden.StatusCode -ne 403) {
|
||||||
|
throw 'Native admins route did not preserve the class-admin boundary'
|
||||||
|
}
|
||||||
$adminCandidateRoute = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/profile" -WebSession $nativeSession -SkipHttpErrorCheck
|
$adminCandidateRoute = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/profile" -WebSession $nativeSession -SkipHttpErrorCheck
|
||||||
if ($adminCandidateRoute.StatusCode -ne 403) {
|
if ($adminCandidateRoute.StatusCode -ne 403) {
|
||||||
throw 'Native candidate API did not enforce the candidate role boundary'
|
throw 'Native candidate API did not enforce the candidate role boundary'
|
||||||
@@ -774,6 +818,7 @@ try {
|
|||||||
NativeCandidateWrites = 'passed'
|
NativeCandidateWrites = 'passed'
|
||||||
NativeCandidateDocuments = 'passed'
|
NativeCandidateDocuments = 'passed'
|
||||||
NativeCandidateAdmissions = 'passed'
|
NativeCandidateAdmissions = 'passed'
|
||||||
|
NativeAdminReads = 'passed'
|
||||||
} | Format-List
|
} | Format-List
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|||||||
Loaded 3 of 12 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user