Files
AIclinicalresearch/backend/scripts/test-data/02_test_rvw_v4_api.ps1
HaHafeng 16179e16ca feat(rvw): deliver tenant portal v4 flow and config foundation
Implement RVW V4.0 tenant-aware backend/frontend flow with tenant routing, config APIs, and full portal UX updates. Sync system/RVW/deployment docs to capture verified upload-review-report workflow and next-step admin configuration work.

Made-with: Cursor
2026-03-14 22:29:40 +08:00

162 lines
7.6 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================
# RVW V4.0 多租户 API 测试脚本PowerShell
# 测试目标:验证 x-tenant-id 多租户隔离全链路
# 运行前提仅需启动后端npm run dev无需启动前端
# 运行方式:在项目根目录执行:.\backend\scripts\test-data\02_test_rvw_v4_api.ps1
# =============================================================
$BASE_URL = "http://localhost:3001"
$TENANT_SLUG = "jtim"
$TEST_USER_PHONE = "13900139001"
$TEST_USER_PASSWORD = "Test@1234"
# 输出工具函数
function Print-Step($step, $msg) { Write-Host "`n[$step] $msg" -ForegroundColor Cyan }
function Print-OK($msg) { Write-Host " [OK] $msg" -ForegroundColor Green }
function Print-FAIL($msg) { Write-Host " [FAIL] $msg" -ForegroundColor Red }
function Print-INFO($msg) { Write-Host " [INFO] $msg" -ForegroundColor Yellow }
# =====================================================================
# STEP 0检查后端是否已启动
# =====================================================================
Print-Step "0" "检查后端服务可用性 $BASE_URL/health"
try {
$health = Invoke-RestMethod -Uri "$BASE_URL/health" -Method GET -ErrorAction Stop
Print-OK "后端健康检查通过: $($health | ConvertTo-Json -Compress)"
} catch {
Print-FAIL "后端未启动或不可达请先运行cd backend && npm run dev"
Print-INFO "错误:$($_.Exception.Message)"
exit 1
}
# =====================================================================
# STEP 1登录获取 JWT Token
# =====================================================================
Print-Step "1" "登录测试账号 (phone: $TEST_USER_PHONE)"
$loginBody = @{
phone = $TEST_USER_PHONE
password = $TEST_USER_PASSWORD
} | ConvertTo-Json
try {
$loginResp = Invoke-RestMethod -Uri "$BASE_URL/api/v1/auth/login/password" `
-Method POST `
-ContentType "application/json" `
-Body $loginBody `
-ErrorAction Stop
# 响应结构data.tokens.accessToken
if ($loginResp.success -and $loginResp.data.tokens.accessToken) {
$TOKEN = $loginResp.data.tokens.accessToken
$USER_ID = $loginResp.data.user.id
Print-OK "登录成功userId=$USER_ID tenantCode=$($loginResp.data.user.tenantCode)"
Print-INFO "Token (前50字符): $($TOKEN.Substring(0, [Math]::Min(50, $TOKEN.Length)))..."
} else {
Print-FAIL "登录响应异常: $($loginResp | ConvertTo-Json)"
exit 1
}
} catch {
Print-FAIL "登录失败:$($_.Exception.Message)"
$errorBody = $_.ErrorDetails.Message
if ($errorBody) { Print-INFO "响应体:$errorBody" }
exit 1
}
# =====================================================================
# STEP 2不带 x-tenant-id获取任务列表主站单租户模式应正常返回
# =====================================================================
Print-Step "2" "不带 x-tenant-id Header - 获取任务列表(主站模式)"
try {
$listNoTenant = Invoke-RestMethod -Uri "$BASE_URL/api/v1/rvw/tasks" `
-Method GET `
-Headers @{ "Authorization" = "Bearer $TOKEN" } `
-ErrorAction Stop
$total1 = if ($listNoTenant.data.total) { $listNoTenant.data.total } else { 0 }
Print-OK "主站模式任务列表获取成功,共 $total1"
} catch {
$status = $_.Exception.Response.StatusCode.value__
Print-FAIL "请求失败HTTP $status$($_.ErrorDetails.Message)"
}
# =====================================================================
# STEP 3携带 x-tenant-id: jtim获取任务列表期刊租户模式
# =====================================================================
Print-Step "3" "携带 x-tenant-id: $TENANT_SLUG - 获取任务列表(期刊租户模式)"
try {
$listWithTenant = Invoke-RestMethod -Uri "$BASE_URL/api/v1/rvw/tasks" `
-Method GET `
-Headers @{
"Authorization" = "Bearer $TOKEN"
"x-tenant-id" = $TENANT_SLUG
} `
-ErrorAction Stop
$total2 = if ($listWithTenant.data.total) { $listWithTenant.data.total } else { 0 }
Print-OK "期刊租户模式任务列表获取成功,共 $total2"
} catch {
$status = $_.Exception.Response.StatusCode.value__
$body = $_.ErrorDetails.Message
Print-FAIL "请求失败HTTP $status$body"
if ($status -eq 401) { Print-INFO "401 说明 rvwTenantMiddleware 拦截成功(用户不在该租户,或中间件未注册)" }
if ($status -eq 403) { Print-INFO "403 说明用户无 RVW 模块权限" }
}
# =====================================================================
# STEP 4携带不存在的租户 slug应返回 404 或 401
# =====================================================================
Print-Step "4" "携带无效 x-tenant-id: nonexistent-journal - 应被拦截"
try {
$listBadTenant = Invoke-RestMethod -Uri "$BASE_URL/api/v1/rvw/tasks" `
-Method GET `
-Headers @{
"Authorization" = "Bearer $TOKEN"
"x-tenant-id" = "nonexistent-journal"
} `
-ErrorAction Stop
Print-FAIL "期望被拦截但未拦截!响应:$($listBadTenant | ConvertTo-Json -Compress)"
} catch {
$status = $_.Exception.Response.StatusCode.value__
if ($status -eq 404 -or $status -eq 401 -or $status -eq 403) {
Print-OK "已正确拦截无效租户HTTP $status(符合预期)"
} else {
Print-FAIL "拦截状态码异常HTTP $status,期望 401/403/404"
}
}
# =====================================================================
# STEP 5用另一个用户 Token 访问 jtim 租户(非成员),应被拦截
# =====================================================================
Print-Step "5" "用其他用户(非 jtim 成员)访问 jtim 租户 - 应返回 401/403"
Print-INFO "此步骤需手动提供另一个用户的 Token跳过自动化测试"
# =====================================================================
# STEP 6查询 DB 验证本地数据一致性
# =====================================================================
Print-Step "6" "数据库验证 - 查询 jtim 租户配置"
$sqlCheck = "SELECT t.code, rc.data_forensics_level, tm.role FROM platform_schema.tenants t JOIN platform_schema.tenant_rvw_configs rc ON rc.tenant_id = t.id JOIN platform_schema.tenant_members tm ON tm.tenant_id = t.id WHERE t.code = 'jtim';"
$dbResult = docker exec -i ai-clinical-postgres psql -U postgres -d ai_clinical_research -c $sqlCheck 2>&1
Print-INFO "DB 查询结果:`n$dbResult"
# =====================================================================
# 测试总结
# =====================================================================
Write-Host "`n" -NoNewline
Write-Host "======================================================" -ForegroundColor Magenta
Write-Host " RVW V4.0 多租户 API 测试完成" -ForegroundColor Magenta
Write-Host "======================================================" -ForegroundColor Magenta
Write-Host ""
Write-Host "测试账号信息(用于前端手动验证):" -ForegroundColor White
Write-Host " 手机号:$TEST_USER_PHONE"
Write-Host " 密码: $TEST_USER_PASSWORD"
Write-Host " 租户: $TENANT_SLUG → http://localhost:5173/$TENANT_SLUG"
Write-Host ""
Write-Host "全流程前端测试步骤:" -ForegroundColor White
Write-Host " 1. 启动后端cd backend && npm run dev"
Write-Host " 2. 启动前端cd frontend-v2 && npm run dev"
Write-Host " 3. 浏览器访问http://localhost:5173/$TENANT_SLUG"
Write-Host " 4. 期望重定向到http://localhost:5173/t/$TENANT_SLUG/login"
Write-Host " 5. 用上方账号登录,登录后应进入期刊审稿页面"
Write-Host ""