本批“考生账号维护”迁移完成:
POST /api/admin/candidate-accounts/archive
POST /api/admin/candidates/{profileId}/reset-password
PATCH /api/admin/candidates/{profileId}
实现了校级按班级/年级归档与恢复、超级管理员密码重置、多级资料审批、事务审计和会话失效。核心代码见
This commit is contained in:
@@ -443,6 +443,7 @@ try {
|
||||
ADMIN_NATIVE_NOTICE_MANAGEMENT_ENABLED = 'true'
|
||||
ADMIN_NATIVE_CENTERS_ENABLED = 'true'
|
||||
ADMIN_NATIVE_OPERATIONAL_READS_ENABLED = 'true'
|
||||
ADMIN_NATIVE_CANDIDATE_MANAGEMENT_ENABLED = 'true'
|
||||
ADMIN_NATIVE_ALLOW_MEMORY = 'true'
|
||||
LegacyNode__Enabled = 'true'
|
||||
LegacyNode__BaseUrl = $legacyBaseUrl
|
||||
@@ -819,6 +820,92 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
$archiveBody = @{
|
||||
scopeType = 'class'
|
||||
scopeValue = $profileUpdate.profile.classId
|
||||
archived = $true
|
||||
} | ConvertTo-Json -Compress
|
||||
$superArchiveForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidate-accounts/archive" -Method Post -ContentType 'application/json' -Body $archiveBody -WebSession $nativeSession -SkipHttpErrorCheck
|
||||
if ($superArchiveForbidden.StatusCode -ne 403 -or $superArchiveForbidden.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
throw 'Native candidate archive did not preserve the school-admin boundary'
|
||||
}
|
||||
$classArchiveForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidate-accounts/archive" -Method Post -ContentType 'application/json' -Body $archiveBody -WebSession $nativeClassSession -SkipHttpErrorCheck
|
||||
if ($classArchiveForbidden.StatusCode -ne 403) {
|
||||
throw 'Native candidate archive accepted a class administrator'
|
||||
}
|
||||
$archiveResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidate-accounts/archive" -Method Post -ContentType 'application/json' -Body $archiveBody -WebSession $nativeSchoolSession
|
||||
$archiveResult = $archiveResponse.Content | ConvertFrom-Json
|
||||
if ($archiveResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core' -or $archiveResult.archived -ne $true -or $archiveResult.count -lt 1) {
|
||||
throw 'Native candidate archive did not freeze the selected class accounts'
|
||||
}
|
||||
$archivedState = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/admin/candidates" -WebSession $nativeSession
|
||||
$archivedCandidate = @($archivedState.candidates | Where-Object id -eq $profileUpdate.profile.id)[0]
|
||||
if ($null -eq $archivedCandidate -or $archivedCandidate.accountArchived -ne $true) {
|
||||
throw 'Native candidate archive was not reflected by the candidate read model'
|
||||
}
|
||||
|
||||
$restoreBody = @{
|
||||
scopeType = 'class'
|
||||
scopeValue = $profileUpdate.profile.classId
|
||||
archived = $false
|
||||
} | ConvertTo-Json -Compress
|
||||
$restoreResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidate-accounts/archive" -Method Post -ContentType 'application/json' -Body $restoreBody -WebSession $nativeSchoolSession
|
||||
$restoreResult = $restoreResponse.Content | ConvertFrom-Json
|
||||
if ($restoreResult.archived -ne $false -or $restoreResult.count -ne $archiveResult.count) {
|
||||
throw 'Native candidate archive could not restore the same class accounts'
|
||||
}
|
||||
|
||||
$preResetSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||
Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $registeredLoginBody -WebSession $preResetSession | Out-Null
|
||||
$schoolResetForbidden = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidates/$($profileUpdate.profile.id)/reset-password" -Method Post -WebSession $nativeSchoolSession -SkipHttpErrorCheck
|
||||
if ($schoolResetForbidden.StatusCode -ne 403 -or $schoolResetForbidden.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
throw 'Native candidate password reset did not preserve the super-admin boundary'
|
||||
}
|
||||
$resetCandidateResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidates/$($profileUpdate.profile.id)/reset-password" -Method Post -WebSession $nativeSession
|
||||
$resetCandidate = $resetCandidateResponse.Content | ConvertFrom-Json
|
||||
if ($resetCandidateResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core' -or $resetCandidate.candidateNumber -ne $registration.registrationNumber -or $resetCandidate.temporaryPassword -notmatch '^Reset-[A-Za-z0-9_-]+$') {
|
||||
throw 'Native candidate password reset did not return compatible temporary credentials'
|
||||
}
|
||||
$invalidatedCandidateSession = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/auth/me" -WebSession $preResetSession
|
||||
if ($null -ne $invalidatedCandidateSession.user) {
|
||||
throw 'Native candidate password reset did not invalidate existing sessions'
|
||||
}
|
||||
$resetCandidateLoginBody = @{ username = $registration.registrationNumber; password = $resetCandidate.temporaryPassword } | ConvertTo-Json -Compress
|
||||
$resetCandidateSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||
$resetCandidateLogin = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $resetCandidateLoginBody -WebSession $resetCandidateSession
|
||||
if ($resetCandidateLogin.user.mustChangePassword -ne $true) {
|
||||
throw 'Native candidate temporary password did not require a password change'
|
||||
}
|
||||
|
||||
$invalidProfileReview = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidates/$($profileUpdate.profile.id)" -Method Patch -ContentType 'application/json' -Body '{"status":"invalid"}' -WebSession $nativeSession -SkipHttpErrorCheck
|
||||
if ($invalidProfileReview.StatusCode -ne 400 -or $invalidProfileReview.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
throw 'Native candidate profile review accepted an invalid status'
|
||||
}
|
||||
$candidateManagementState = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/admin/candidates" -WebSession $nativeSession
|
||||
$managedCandidate = @($candidateManagementState.candidates | Where-Object id -eq $profileUpdate.profile.id)[0]
|
||||
if ($null -eq $managedCandidate -or $managedCandidate.workflow.status -ne 'pending') {
|
||||
throw 'Candidate profile smoke data did not retain a pending review workflow'
|
||||
}
|
||||
$reviewIterations = 0
|
||||
do {
|
||||
$reviewIterations += 1
|
||||
if ($reviewIterations -gt 10) {
|
||||
throw 'Native candidate profile workflow did not reach a terminal state'
|
||||
}
|
||||
$profileReviewBody = @{ status = 'approved'; reviewNote = "原生资料审核第 $reviewIterations 步" } | ConvertTo-Json -Compress
|
||||
$profileReviewResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidates/$($profileUpdate.profile.id)" -Method Patch -ContentType 'application/json' -Body $profileReviewBody -WebSession $nativeSession
|
||||
if ($profileReviewResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
throw 'Candidate profile review did not use ASP.NET Core'
|
||||
}
|
||||
$profileReview = $profileReviewResponse.Content | ConvertFrom-Json
|
||||
} while ($profileReview.workflow.status -eq 'pending')
|
||||
if ($profileReview.profile.status -ne 'approved' -or $profileReview.workflow.status -ne 'approved' -or $profileReview.workflow.actions.Count -lt 2) {
|
||||
throw 'Native candidate profile review did not complete its configured workflow'
|
||||
}
|
||||
$legacyCandidatesAfterManagement = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/candidates" -WebSession $session
|
||||
$nativeCandidatesAfterManagement = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/candidates" -WebSession $nativeSession
|
||||
Assert-JsonEquivalent -Expected $legacyCandidatesAfterManagement.Content -Actual $nativeCandidatesAfterManagement.Content -Label 'Candidate management follow-up'
|
||||
|
||||
$legacyCenters = Invoke-WebRequest -Uri "$legacyBaseUrl/api/admin/centers" -WebSession $session
|
||||
$nativeCenters = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/admin/centers" -WebSession $nativeSession
|
||||
if ($nativeCenters.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
@@ -1288,6 +1375,7 @@ try {
|
||||
NativeAdminNoticeManagement = 'passed'
|
||||
NativeAdminCenters = 'passed'
|
||||
NativeAdminOperationalReads = 'passed'
|
||||
NativeAdminCandidateManagement = 'passed'
|
||||
} | Format-List
|
||||
}
|
||||
finally {
|
||||
|
||||
Reference in New Issue
Block a user