PUT /api/candidate/profile
行政区划、学校班级、特长类别校验 证件号码唯一性 自动创建资料审核工作流 资料和用户显示名称原子更新 POST /api/candidate/registrations 资料审核状态、报名时间和科目校验 重复报名防护 自动选择负载最低的审批管理员 报名、科目和审批流原子写入
This commit is contained in:
1 parent
07efa6813b
commit
aecb0a04e7
16 files changed
+987
-28
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 同时启用。成绩、准考证、复议和志愿填报仍会继续转发给 Node:
|
||||
|
||||
```powershell
|
||||
$env:AUTH_NATIVE_ENABLED = 'true'
|
||||
|
||||
@@ -440,6 +440,108 @@ try {
|
||||
throw 'Native candidate profile route was not available during onboarding'
|
||||
}
|
||||
|
||||
$invalidSpecialtyBody = @{
|
||||
name = '原生迁移注册考生'
|
||||
gender = '女'
|
||||
idNumber = 'SMOKE-INVALID-SPECIALTY'
|
||||
phone = '13800000000'
|
||||
email = 'candidate@example.test'
|
||||
nativePlace = '江苏连云港'
|
||||
address = '迁移测试路 1 号'
|
||||
schoolId = $registrationSchool.id
|
||||
classId = $registrationClass.id
|
||||
provinceCode = '320000'
|
||||
cityCode = '320700'
|
||||
districtCode = '320706'
|
||||
specialtyCategory = 'arts'
|
||||
specialtyType = 'track_field'
|
||||
} | ConvertTo-Json -Compress
|
||||
$invalidSpecialty = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/profile" -Method Put -ContentType 'application/json' -Body $invalidSpecialtyBody -WebSession $registeredSession -SkipHttpErrorCheck
|
||||
if ($invalidSpecialty.StatusCode -ne 400) {
|
||||
throw 'Native candidate profile API accepted a mismatched specialty category and type'
|
||||
}
|
||||
|
||||
$profileIdNumber = "SMOKE-NATIVE-$([guid]::NewGuid().ToString('N'))"
|
||||
$profileBody = @{
|
||||
name = '原生迁移注册考生'
|
||||
gender = '女'
|
||||
idNumber = $profileIdNumber
|
||||
phone = '13800000000'
|
||||
email = 'candidate@example.test'
|
||||
address = '迁移测试路 1 号'
|
||||
emergencyContact = '测试联系人'
|
||||
emergencyPhone = '13900000000'
|
||||
nativePlace = '江苏连云港'
|
||||
birthDate = '2010-01-02'
|
||||
ethnicity = '汉族'
|
||||
postalCode = '222000'
|
||||
guardianName = '测试监护人'
|
||||
guardianPhone = '13700000000'
|
||||
schoolId = $registrationSchool.id
|
||||
classId = $registrationClass.id
|
||||
provinceCode = '320000'
|
||||
cityCode = '320700'
|
||||
districtCode = '320706'
|
||||
specialtyCategory = ''
|
||||
specialtyType = ''
|
||||
specialtyCertificate = ''
|
||||
policyEligibility = ''
|
||||
} | ConvertTo-Json -Compress
|
||||
$profileUpdateResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/profile" -Method Put -ContentType 'application/json' -Body $profileBody -WebSession $registeredSession
|
||||
if ($profileUpdateResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
throw 'Candidate profile update did not use the native ASP.NET Core endpoint'
|
||||
}
|
||||
$profileUpdate = $profileUpdateResponse.Content | ConvertFrom-Json
|
||||
if ($profileUpdate.profile.profileCompleted -ne $true -or $profileUpdate.profile.districtName -ne '海州区' -or $profileUpdate.profile.status -ne 'pending') {
|
||||
throw 'Native candidate profile update did not resolve the region or persist onboarding state'
|
||||
}
|
||||
|
||||
$prematureRegistrationBody = @{ examId = 'not-approved-yet'; subjectIds = @('none') } | ConvertTo-Json -Compress
|
||||
$prematureRegistration = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/registrations" -Method Post -ContentType 'application/json' -Body $prematureRegistrationBody -WebSession $registeredSession -SkipHttpErrorCheck
|
||||
if ($prematureRegistration.StatusCode -ne 403) {
|
||||
throw 'Native registration API did not require an approved candidate profile'
|
||||
}
|
||||
|
||||
$candidateWriteSetup = Start-TestProcess -FileName $nodeExecutable -ArgumentList @(
|
||||
'tests/helpers/prepare-candidate-write-smoke.mjs', $smokeDatabasePath, $registration.registrationNumber
|
||||
) -Environment $nodeEnvironment
|
||||
if (-not $candidateWriteSetup.WaitForExit(10000)) {
|
||||
$candidateWriteSetup.Kill($true)
|
||||
throw 'Timed out while preparing the native candidate write smoke test'
|
||||
}
|
||||
$candidateWriteSetupOutput = $candidateWriteSetup.StandardOutput.ReadToEnd().Trim()
|
||||
$candidateWriteSetupError = $candidateWriteSetup.StandardError.ReadToEnd()
|
||||
if ($candidateWriteSetup.ExitCode -ne 0) {
|
||||
throw "Could not prepare the native candidate write smoke test`n$candidateWriteSetupError"
|
||||
}
|
||||
$candidateWriteSetup.Dispose()
|
||||
$candidateWriteTarget = $candidateWriteSetupOutput | ConvertFrom-Json
|
||||
|
||||
$nativeRegistrationBody = @{
|
||||
examId = $candidateWriteTarget.examId
|
||||
subjectIds = @($candidateWriteTarget.subjectId)
|
||||
} | ConvertTo-Json -Compress
|
||||
$nativeRegistrationResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/registrations" -Method Post -ContentType 'application/json' -Body $nativeRegistrationBody -WebSession $registeredSession
|
||||
if ($nativeRegistrationResponse.StatusCode -ne 201 -or $nativeRegistrationResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
throw 'Exam registration submission did not use the native ASP.NET Core endpoint'
|
||||
}
|
||||
$nativeRegistration = $nativeRegistrationResponse.Content | ConvertFrom-Json
|
||||
if ($nativeRegistration.registration.status -ne 'pending' -or $nativeRegistration.registration.subjectIds.Count -ne 1) {
|
||||
throw 'Native exam registration did not persist the selected subject and pending state'
|
||||
}
|
||||
$duplicateRegistration = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/registrations" -Method Post -ContentType 'application/json' -Body $nativeRegistrationBody -WebSession $registeredSession -SkipHttpErrorCheck
|
||||
if ($duplicateRegistration.StatusCode -ne 409) {
|
||||
throw 'Native exam registration did not reject a duplicate submission'
|
||||
}
|
||||
|
||||
$legacyRegisteredSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||
Invoke-RestMethod -Uri "$legacyBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $registeredLoginBody -WebSession $legacyRegisteredSession | Out-Null
|
||||
foreach ($candidateWriteReadRoute in @('profile', 'registrations')) {
|
||||
$legacyWriteRead = Invoke-WebRequest -Uri "$legacyBaseUrl/api/candidate/$candidateWriteReadRoute" -WebSession $legacyRegisteredSession
|
||||
$nativeWriteRead = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/$candidateWriteReadRoute" -WebSession $registeredSession
|
||||
Assert-JsonEquivalent -Expected $legacyWriteRead.Content -Actual $nativeWriteRead.Content -Label "Candidate write follow-up '$candidateWriteReadRoute'"
|
||||
}
|
||||
|
||||
$nativeSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
|
||||
$nativeLoginResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $loginBody -WebSession $nativeSession
|
||||
if ($nativeLoginResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
|
||||
@@ -528,6 +630,7 @@ try {
|
||||
DocumentCodes = 'passed'
|
||||
NativeAuthentication = 'passed'
|
||||
NativeCandidateReads = 'passed'
|
||||
NativeCandidateWrites = 'passed'
|
||||
} | Format-List
|
||||
}
|
||||
finally {
|
||||
|
||||
+11
-1
@@ -4,7 +4,7 @@ namespace Eis.Application.Candidate;
|
||||
|
||||
public sealed record CandidateEndpointResult(int StatusCode, JsonObject Body);
|
||||
|
||||
public interface ICandidateQueryService
|
||||
public interface ICandidateService
|
||||
{
|
||||
Task<CandidateEndpointResult> GetDashboardAsync(string sessionToken, CancellationToken cancellationToken);
|
||||
|
||||
@@ -15,4 +15,14 @@ public interface ICandidateQueryService
|
||||
Task<CandidateEndpointResult> GetExamsAsync(string sessionToken, CancellationToken cancellationToken);
|
||||
|
||||
Task<CandidateEndpointResult> GetRegistrationsAsync(string sessionToken, CancellationToken cancellationToken);
|
||||
|
||||
Task<CandidateEndpointResult> UpdateProfileAsync(
|
||||
string sessionToken,
|
||||
JsonObject body,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
Task<CandidateEndpointResult> CreateRegistrationAsync(
|
||||
string sessionToken,
|
||||
JsonObject body,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
Loaded 3 of 16 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user