招生计划、资格、录取、分数线及报到公示

成绩单 HMAC 防伪验真
录取通知书 HMAC 防伪验真
防伪码常量时间比较
生产环境文书密钥强度检查
旧文书防伪码完全兼容
This commit is contained in:
2026-07-22 19:12:38 +08:00 Unverified
parent 38e42ad734
commit 017cacc6f9
14 changed files with 824 additions and 6 deletions
+76
View File
@@ -137,6 +137,7 @@ try {
LegacyNode__BaseUrl = $legacyBaseUrl
DATABASE_CLIENT = 'sqlite'
SQLITE_PATH = $smokeDatabasePath
DOCUMENT_VERIFICATION_SECRET = 'migration-smoke-document-key-32-characters-minimum'
}
Wait-ForUrl -Uri "$webBaseUrl/health/live" -Processes @($nodeProcess, $dotnetProcess)
@@ -177,6 +178,25 @@ try {
}
}
$announcementResponse = Invoke-WebRequest -Uri "$webBaseUrl/api/public/announcements"
if ($announcementResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
throw 'Public announcements request did not use the native ASP.NET Core endpoint'
}
$nativeAnnouncements = $announcementResponse.Content | ConvertFrom-Json
$legacyAnnouncements = Invoke-RestMethod -Uri "$legacyBaseUrl/api/public/announcements"
foreach ($section in @('plans', 'qualifications', 'admissions', 'cutoffs', 'reports')) {
$nativeIds = @($nativeAnnouncements.$section | ForEach-Object id)
$legacyIds = @($legacyAnnouncements.$section | ForEach-Object id)
if (($nativeIds -join "`0") -ne ($legacyIds -join "`0")) {
throw "Native public announcement section '$section' does not match the legacy API"
}
$nativeSectionJson = $nativeAnnouncements.$section | ConvertTo-Json -Depth 100 -Compress
$legacySectionJson = $legacyAnnouncements.$section | ConvertTo-Json -Depth 100 -Compress
if ($nativeSectionJson -ne $legacySectionJson) {
throw "Native public announcement payload '$section' differs from the legacy API"
}
}
$session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
$loginBody = @{ username = 'admin'; password = '12345678' } | ConvertTo-Json -Compress
$login = Invoke-RestMethod -Uri "$webBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $loginBody -WebSession $session
@@ -206,12 +226,68 @@ try {
throw 'Native public notice endpoint did not preserve data or sanitize unsafe content'
}
$candidateSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
$candidateLoginBody = @{ username = '2026-HZ01-F-0001'; password = '12345678' } | ConvertTo-Json -Compress
$candidateLogin = Invoke-RestMethod -Uri "$webBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $candidateLoginBody -WebSession $candidateSession
if ($candidateLogin.user.username -ne '2026-HZ01-F-0001') {
throw 'Could not sign in as the migration verification candidate'
}
$candidateResults = Invoke-RestMethod -Uri "$webBaseUrl/api/candidate/results" -WebSession $candidateSession
$scoreCode = @($candidateResults.summaries | Where-Object verificationCode | Select-Object -First 1).verificationCode
if (-not $scoreCode) {
throw 'Seed data did not provide a score-report verification code'
}
$scoreVerificationResponse = Invoke-WebRequest -Uri "$webBaseUrl/api/public/verifications/$scoreCode"
if ($scoreVerificationResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
throw 'Document verification request did not use the native ASP.NET Core endpoint'
}
$nativeScoreVerification = $scoreVerificationResponse.Content | ConvertFrom-Json
$legacyScoreVerification = Invoke-RestMethod -Uri "$legacyBaseUrl/api/public/verifications/$scoreCode"
if ($nativeScoreVerification.document.type -ne 'score-report' -or
$nativeScoreVerification.document.examName -ne $legacyScoreVerification.document.examName -or
$nativeScoreVerification.document.totalScore -ne $legacyScoreVerification.document.totalScore -or
$nativeScoreVerification.document.subjectCount -ne $legacyScoreVerification.document.subjectCount) {
throw 'Native score-report verification does not match the legacy API'
}
$admissionCodeProcess = Start-TestProcess -FileName $nodeExecutable -ArgumentList @(
'tests/helpers/create-admission-verification.mjs', $smokeDatabasePath
) -Environment $nodeEnvironment
if (-not $admissionCodeProcess.WaitForExit(10000)) {
$admissionCodeProcess.Kill($true)
throw 'Timed out while reading an admission-notice verification code'
}
$noticeCode = $admissionCodeProcess.StandardOutput.ReadToEnd().Trim()
$admissionCodeError = $admissionCodeProcess.StandardError.ReadToEnd()
if ($admissionCodeProcess.ExitCode -ne 0) {
throw "Could not read an admission-notice verification code`n$admissionCodeError"
}
$admissionCodeProcess.Dispose()
if (-not $noticeCode) {
throw "Seed data did not provide an admission-notice verification code`n$admissionCodeError"
}
$nativeNoticeVerification = Invoke-RestMethod -Uri "$webBaseUrl/api/public/verifications/$noticeCode"
$legacyNoticeVerification = Invoke-RestMethod -Uri "$legacyBaseUrl/api/public/verifications/$noticeCode"
if ($nativeNoticeVerification.document.type -ne 'admission-notice' -or
$nativeNoticeVerification.document.noticeNumber -ne $legacyNoticeVerification.document.noticeNumber -or
$nativeNoticeVerification.document.schoolName -ne $legacyNoticeVerification.document.schoolName) {
throw 'Native admission-notice verification does not match the legacy API'
}
$invalidVerification = Invoke-WebRequest -Uri "$webBaseUrl/api/public/verifications/SR-000000000000000000000000" -SkipHttpErrorCheck
if ($invalidVerification.StatusCode -ne 404 -or $invalidVerification.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
throw 'Native document verification did not reject an invalid code'
}
[pscustomobject]@{
AspNetCoreHost = 'passed'
StaticAssets = 'passed'
JsonProxy = 'passed'
SessionCookie = 'passed'
NativePublicApi = 'passed'
PublicParity = 'passed'
DocumentCodes = 'passed'
} | Format-List
}
finally {