原生志愿、录取、计划余量、指标资格和通知查询:[CandidateService.Admissions.cs (line 29)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Infrastructure/Candidate/CandidateService.Admissions.cs:29)
志愿提交、资格校验、补录限制、次数上限与自动锁定:[CandidateService.Admissions.cs (line 152)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Infrastructure/Candidate/CandidateService.Admissions.cs:152) 通用招生记录读取及事务写入:[CandidateAdmissionRepository.cs (line 25)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Infrastructure/Candidate/CandidateAdmissionRepository.cs:25) 原生路由已接入:[NativeCandidateEndpoints.cs (line 70)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Web/Candidate/NativeCandidateEndpoints.cs:70) 迁移状态现在会把 Candidate 标记为原生:[MigrationFeatureCatalog.cs (line 12)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Infrastructure/Migration/MigrationFeatureCatalog.cs:12)
This commit is contained in:
1 parent
4417d6d674
commit
4b0dae6d71
13 files changed
+859
-7
No files matched your search
+1
-1
@@ -47,7 +47,7 @@ $env:AUTH_NATIVE_ENABLED = 'true'
|
||||
|
||||
开发环境未配置 Redis 时可以使用进程内状态独立验证原生认证。生产环境以及仍需访问 Node 受保护接口的联调环境必须配置 `REDIS_URL` 或 `REDIS_SESSION_URL`;两个运行时会复用相同逻辑库和 `exam-information:auth` 键前缀,从而共享登录会话。`GET /health/migration` 会报告 `authentication.nativeEnabled`、状态后端和跨运行时会话共享能力。
|
||||
|
||||
考生域核心端点(首页、通知、个人资料读取与提交、可报名考试、我的报名读取与提交、成绩与总分排名、成绩单防伪码、成绩复议、准考证下载)可通过以下开关原生运行;该开关必须与原生认证及共享 Redis 同时启用。志愿填报与录取查询仍会继续转发给 Node:
|
||||
考生域全部端点(首页、通知、个人资料读取与提交、可报名考试、我的报名读取与提交、成绩与总分排名、成绩单防伪码、成绩复议、准考证下载、志愿填报与录取查询)可通过以下开关原生运行;该开关必须与原生认证及共享 Redis 同时启用:
|
||||
|
||||
```powershell
|
||||
$env:AUTH_NATIVE_ENABLED = 'true'
|
||||
|
||||
@@ -126,6 +126,28 @@ function Assert-CandidateResultsEquivalent {
|
||||
}
|
||||
}
|
||||
|
||||
function Assert-CandidateAdmissionsEquivalent {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string] $Expected,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[string] $Actual
|
||||
)
|
||||
|
||||
$expectedNode = [System.Text.Json.Nodes.JsonNode]::Parse($Expected)
|
||||
$actualNode = [System.Text.Json.Nodes.JsonNode]::Parse($Actual)
|
||||
foreach ($node in @($expectedNode, $actualNode)) {
|
||||
foreach ($admission in $node['admissions'].AsArray()) {
|
||||
$admission.AsObject().Remove('noticeVerificationQr') | Out-Null
|
||||
}
|
||||
}
|
||||
if (-not [System.Text.Json.Nodes.JsonNode]::DeepEquals($expectedNode, $actualNode)) {
|
||||
$difference = Find-JsonDifference -Expected $expectedNode -Actual $actualNode -Path '$'
|
||||
throw "Candidate route 'admissions' JSON payload differs from the legacy API at $difference"
|
||||
}
|
||||
}
|
||||
|
||||
function Find-JsonDifference {
|
||||
param(
|
||||
[AllowNull()]
|
||||
@@ -439,6 +461,58 @@ try {
|
||||
if (@($nativeCandidateResults.summaries | Where-Object { $_.verificationQr -match '^data:image/png;base64,' }).Count -eq 0) {
|
||||
throw 'Native candidate results did not include a local PNG verification QR code'
|
||||
}
|
||||
$legacyCandidateAdmissionsResponse = Invoke-WebRequest -Uri "$legacyBaseUrl/api/candidate/admissions" -WebSession $candidateSession
|
||||
$nativeCandidateAdmissionsResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/admissions" -WebSession $nativeCandidateSession
|
||||
if ($nativeCandidateAdmissionsResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
throw "Candidate route 'admissions' did not use the native ASP.NET Core endpoint"
|
||||
}
|
||||
Assert-CandidateAdmissionsEquivalent -Expected $legacyCandidateAdmissionsResponse.Content -Actual $nativeCandidateAdmissionsResponse.Content
|
||||
$admissionWriteProcess = Start-TestProcess -FileName $nodeExecutable -ArgumentList @(
|
||||
'tests/helpers/prepare-candidate-admission-write-smoke.mjs', $smokeDatabasePath
|
||||
) -Environment $nodeEnvironment
|
||||
if (-not $admissionWriteProcess.WaitForExit(10000)) {
|
||||
$admissionWriteProcess.Kill($true)
|
||||
throw 'Timed out while preparing the candidate admission preference smoke data'
|
||||
}
|
||||
$admissionWriteError = $admissionWriteProcess.StandardError.ReadToEnd()
|
||||
if ($admissionWriteProcess.ExitCode -ne 0) {
|
||||
throw "Could not prepare the candidate admission preference smoke data`n$admissionWriteError"
|
||||
}
|
||||
$admissionWriteProcess.Dispose()
|
||||
$admissionContext = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/candidate/admissions" -WebSession $nativeCandidateSession
|
||||
$admissionSetting = @($admissionContext.admissions | Where-Object { $_.status -eq 'filling' } | Select-Object -First 1)[0]
|
||||
$admissionPlan = @($admissionSetting.plans | Select-Object -First 1)[0]
|
||||
$admissionCategory = @($admissionPlan.categories | Where-Object { $_.preferenceTypes -contains 'general' } | Select-Object -First 1)[0]
|
||||
if ($null -eq $admissionSetting -or $null -eq $admissionPlan -or $null -eq $admissionCategory) {
|
||||
throw 'Native candidate admissions did not expose an eligible plan for preference submission'
|
||||
}
|
||||
$emptyPreference = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/admissions/$($admissionSetting.examId)/preferences" -Method Put -ContentType 'application/json' -Body '{"choices":[]}' -WebSession $nativeCandidateSession -SkipHttpErrorCheck
|
||||
if ($emptyPreference.StatusCode -ne 400) {
|
||||
throw 'Native admission preference API accepted an empty preference list'
|
||||
}
|
||||
$preferenceBody = @{
|
||||
choices = @(@{
|
||||
schoolId = $admissionPlan.schoolId
|
||||
categoryCode = $admissionCategory.code
|
||||
preferenceType = 'general'
|
||||
})
|
||||
} | ConvertTo-Json -Depth 5 -Compress
|
||||
$firstPreferenceResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/admissions/$($admissionSetting.examId)/preferences" -Method Put -ContentType 'application/json' -Body $preferenceBody -WebSession $nativeCandidateSession
|
||||
$firstPreference = $firstPreferenceResponse.Content | ConvertFrom-Json
|
||||
if ($firstPreferenceResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core' -or $firstPreference.remainingSubmissions -ne 1 -or $firstPreference.locked -ne $false) {
|
||||
throw 'Native admission preference API did not persist the first submission count'
|
||||
}
|
||||
$secondPreference = Invoke-RestMethod -Uri "$nativeAuthBaseUrl/api/candidate/admissions/$($admissionSetting.examId)/preferences" -Method Put -ContentType 'application/json' -Body $preferenceBody -WebSession $nativeCandidateSession
|
||||
if ($secondPreference.remainingSubmissions -ne 0 -or $secondPreference.locked -ne $true) {
|
||||
throw 'Native admission preference API did not lock at the configured submission limit'
|
||||
}
|
||||
$lockedPreference = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/admissions/$($admissionSetting.examId)/preferences" -Method Put -ContentType 'application/json' -Body $preferenceBody -WebSession $nativeCandidateSession -SkipHttpErrorCheck
|
||||
if ($lockedPreference.StatusCode -ne 409) {
|
||||
throw 'Native admission preference API accepted a submission after automatic locking'
|
||||
}
|
||||
$legacyAdmissionsAfterWrite = Invoke-WebRequest -Uri "$legacyBaseUrl/api/candidate/admissions" -WebSession $candidateSession
|
||||
$nativeAdmissionsAfterWrite = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/admissions" -WebSession $nativeCandidateSession
|
||||
Assert-CandidateAdmissionsEquivalent -Expected $legacyAdmissionsAfterWrite.Content -Actual $nativeAdmissionsAfterWrite.Content
|
||||
$appealableResult = @($nativeCandidateResults.results | Where-Object { $null -eq $_.appeal } | Select-Object -First 1)[0]
|
||||
if ($null -ne $appealableResult) {
|
||||
$shortAppeal = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/results/$($appealableResult.id)/appeals" -Method Post -ContentType 'application/json' -Body '{"reason":"短"}' -WebSession $nativeCandidateSession -SkipHttpErrorCheck
|
||||
@@ -699,6 +773,7 @@ try {
|
||||
NativeCandidateReads = 'passed'
|
||||
NativeCandidateWrites = 'passed'
|
||||
NativeCandidateDocuments = 'passed'
|
||||
NativeCandidateAdmissions = 'passed'
|
||||
} | Format-List
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -27,6 +27,11 @@ public interface ICandidateService
|
||||
string verificationBaseUrl,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task<CandidateEndpointResult> GetAdmissionsAsync(
|
||||
string sessionToken,
|
||||
string verificationBaseUrl,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task<CandidateEndpointResult> UpdateProfileAsync(
|
||||
string sessionToken,
|
||||
JsonObject body,
|
||||
@@ -47,4 +52,10 @@ public interface ICandidateService
|
||||
string sessionToken,
|
||||
string registrationId,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task<CandidateEndpointResult> UpdateAdmissionPreferencesAsync(
|
||||
string sessionToken,
|
||||
string examId,
|
||||
JsonObject body,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
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