fix: v6 code review P0 auth/IDOR fixes + frontend regression patches
Backend fixes: - auth_handler: P0 认证逻辑修复 - ratelimit: 限速中间件增强 + 新增单元测试 - auth_service: 认证服务逻辑完善 + 新增测试 - server: server 配置增强 + 新增测试 - handler_test: 新增 handler 层集成测试 - auth_bootstrap_test: bootstrap 路径测试 Frontend patches: - LoginPage/RegisterPage: CSRF + 表单交互修复 - BootstrapAdminPage: 引导流程修复 - DevicesPage: 设备管理页修复 - auth/social-accounts/users/webhooks services: 类型修正 - csrf.ts: CSRF token 处理修正 - E2E 脚本: CDP smoke + auth e2e 增强 Docs: - FULL_CODE_REVIEW_REPORT_2026-04-20 - report-v6 执行计划 - REAL_PROJECT_STATUS 更新 - .gitignore: 新增 .gocache-*/config.yaml 排除 验证: go build/vet 0错误, go test 42/42 PASS, 0 FAIL
This commit is contained in:
@@ -9,19 +9,58 @@ param(
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..\..')).Path
|
||||
$frontendRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
|
||||
$tempCacheRoot = Join-Path $env:TEMP 'ums-e2e-cache'
|
||||
$goCacheDir = Join-Path $tempCacheRoot 'go-build'
|
||||
$goModCacheDir = Join-Path $tempCacheRoot 'gomod'
|
||||
$goPathDir = Join-Path $tempCacheRoot 'gopath'
|
||||
function Resolve-E2ERoots {
|
||||
$scriptFrontendRoot = Resolve-Path (Join-Path $PSScriptRoot '..') -ErrorAction SilentlyContinue
|
||||
$scriptProjectRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..\..') -ErrorAction SilentlyContinue
|
||||
$cwdFrontendRoot = Resolve-Path (Get-Location).Path
|
||||
$cwdProjectRoot = Resolve-Path (Join-Path $cwdFrontendRoot '..\..') -ErrorAction SilentlyContinue
|
||||
|
||||
if (
|
||||
$scriptFrontendRoot -and
|
||||
$scriptProjectRoot -and
|
||||
(Test-Path (Join-Path $scriptFrontendRoot 'package.json')) -and
|
||||
(Test-Path (Join-Path $scriptProjectRoot 'go.mod'))
|
||||
) {
|
||||
return [pscustomobject]@{
|
||||
FrontendRoot = $scriptFrontendRoot.Path
|
||||
ProjectRoot = $scriptProjectRoot.Path
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$cwdProjectRoot -and
|
||||
(Test-Path (Join-Path $cwdFrontendRoot 'package.json')) -and
|
||||
(Test-Path (Join-Path $cwdProjectRoot 'go.mod'))
|
||||
) {
|
||||
return [pscustomobject]@{
|
||||
FrontendRoot = $cwdFrontendRoot
|
||||
ProjectRoot = $cwdProjectRoot.Path
|
||||
}
|
||||
}
|
||||
|
||||
throw 'failed to resolve frontend/project roots for playwright e2e'
|
||||
}
|
||||
|
||||
$resolvedRoots = Resolve-E2ERoots
|
||||
$projectRoot = $resolvedRoots.ProjectRoot
|
||||
$frontendRoot = $resolvedRoots.FrontendRoot
|
||||
$serverExePath = Join-Path $env:TEMP ("ums-server-playwright-e2e-" + [guid]::NewGuid().ToString('N') + '.exe')
|
||||
$e2eRunRoot = Join-Path $env:TEMP ("ums-playwright-e2e-" + [guid]::NewGuid().ToString('N'))
|
||||
$goCacheDir = Join-Path $e2eRunRoot 'go-build'
|
||||
$goModCacheDir = Join-Path $e2eRunRoot 'gomod'
|
||||
$goPathDir = Join-Path $e2eRunRoot 'gopath'
|
||||
$e2eDataRoot = Join-Path $e2eRunRoot 'data'
|
||||
$e2eDbPath = Join-Path $e2eDataRoot 'user_management.e2e.db'
|
||||
$smtpCaptureFile = Join-Path $e2eRunRoot 'smtp-capture.jsonl'
|
||||
$e2eConfigPath = Join-Path $e2eRunRoot 'config.yaml'
|
||||
$bootstrapSecret = 'e2e-bootstrap-secret'
|
||||
|
||||
New-Item -ItemType Directory -Force $goCacheDir, $goModCacheDir, $goPathDir, $e2eDataRoot | Out-Null
|
||||
New-Item -ItemType Directory -Force $goCacheDir, $goModCacheDir, $goPathDir, $e2eRunRoot, $e2eDataRoot | Out-Null
|
||||
Set-Content -Path $e2eConfigPath -Encoding utf8 -Value @(
|
||||
'default:',
|
||||
' admin_email: ""',
|
||||
' admin_password: ""'
|
||||
)
|
||||
|
||||
function Get-FreeTcpPort {
|
||||
$listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Loopback, 0)
|
||||
@@ -160,28 +199,36 @@ $backendBaseUrl = "http://127.0.0.1:$selectedBackendPort"
|
||||
$frontendBaseUrl = "http://127.0.0.1:$selectedFrontendPort"
|
||||
|
||||
try {
|
||||
$serverSrcPath = Join-Path $projectRoot 'cmd\server'
|
||||
Push-Location $projectRoot
|
||||
try {
|
||||
$env:GOCACHE = $goCacheDir
|
||||
go build -o $serverExePath $serverSrcPath
|
||||
$env:GOMODCACHE = $goModCacheDir
|
||||
$env:GOPATH = $goPathDir
|
||||
$env:GOTELEMETRY = 'off'
|
||||
go build -o $serverExePath ./cmd/server
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw 'server build failed'
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
Remove-Item Env:GOCACHE -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:GOMODCACHE -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:GOPATH -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:GOTELEMETRY -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$env:DATA_DIR = $e2eRunRoot
|
||||
$env:SERVER_PORT = "$selectedBackendPort"
|
||||
$env:DATABASE_DBNAME = $e2eDbPath
|
||||
$env:SERVER_MODE = 'debug'
|
||||
$env:SERVER_FRONTEND_URL = $frontendBaseUrl
|
||||
$env:CORS_ALLOWED_ORIGINS = "$frontendBaseUrl,http://localhost:$selectedFrontendPort"
|
||||
$env:SERVER_MODE = 'debug'
|
||||
$env:SERVER_FRONTEND_URL = $frontendBaseUrl
|
||||
$env:CORS_ALLOWED_ORIGINS = "$frontendBaseUrl,http://localhost:$selectedFrontendPort"
|
||||
$env:LOGGING_OUTPUT = 'stdout'
|
||||
$env:EMAIL_HOST = '127.0.0.1'
|
||||
$env:EMAIL_PORT = "$selectedSMTPPort"
|
||||
$env:EMAIL_FROM_EMAIL = 'noreply@test.local'
|
||||
$env:EMAIL_FROM_NAME = 'UMS E2E'
|
||||
$env:BOOTSTRAP_SECRET = $bootstrapSecret
|
||||
# JWT secret must be at least 32 bytes
|
||||
$env:JWT_SECRET = 'e2e-test-jwt-secret-at-least-32-bytes-long-for-security'
|
||||
|
||||
@@ -232,15 +279,25 @@ $env:CORS_ALLOWED_ORIGINS = "$frontendBaseUrl,http://localhost:$selectedFrontend
|
||||
$env:E2E_LOGIN_USERNAME = $AdminUsername
|
||||
$env:E2E_LOGIN_PASSWORD = $AdminPassword
|
||||
$env:E2E_LOGIN_EMAIL = $AdminEmail
|
||||
$env:E2E_BOOTSTRAP_SECRET = $bootstrapSecret
|
||||
$env:E2E_EXPECT_ADMIN_BOOTSTRAP = '1'
|
||||
$env:E2E_EXTERNAL_WEB_SERVER = '1'
|
||||
$env:E2E_BASE_URL = $frontendBaseUrl
|
||||
$env:E2E_API_BASE_URL = "$backendBaseUrl/api/v1"
|
||||
$env:E2E_SMTP_CAPTURE_FILE = $smtpCaptureFile
|
||||
|
||||
Push-Location $frontendRoot
|
||||
try {
|
||||
$lastError = $null
|
||||
for ($attempt = 1; $attempt -le 2; $attempt++) {
|
||||
$suiteAttempts = 2
|
||||
if ($env:E2E_SUITE_ATTEMPTS) {
|
||||
$parsedSuiteAttempts = 0
|
||||
if ([int]::TryParse($env:E2E_SUITE_ATTEMPTS, [ref]$parsedSuiteAttempts) -and $parsedSuiteAttempts -gt 0) {
|
||||
$suiteAttempts = $parsedSuiteAttempts
|
||||
}
|
||||
}
|
||||
|
||||
for ($attempt = 1; $attempt -le $suiteAttempts; $attempt++) {
|
||||
try {
|
||||
& (Join-Path $PSScriptRoot 'run-cdp-smoke.ps1') `
|
||||
-Port $BrowserPort `
|
||||
@@ -249,7 +306,7 @@ $env:CORS_ALLOWED_ORIGINS = "$frontendBaseUrl,http://localhost:$selectedFrontend
|
||||
break
|
||||
} catch {
|
||||
$lastError = $_
|
||||
if ($attempt -ge 2) {
|
||||
if ($attempt -ge $suiteAttempts) {
|
||||
throw
|
||||
}
|
||||
$retryReason = if ($_.Exception -and $_.Exception.Message) { $_.Exception.Message } else { $_ | Out-String }
|
||||
@@ -263,12 +320,15 @@ $env:CORS_ALLOWED_ORIGINS = "$frontendBaseUrl,http://localhost:$selectedFrontend
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
Remove-Item Env:DATA_DIR -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_LOGIN_USERNAME -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_LOGIN_PASSWORD -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_LOGIN_EMAIL -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_BOOTSTRAP_SECRET -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_EXPECT_ADMIN_BOOTSTRAP -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_EXTERNAL_WEB_SERVER -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_BASE_URL -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_API_BASE_URL -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:E2E_SMTP_CAPTURE_FILE -ErrorAction SilentlyContinue
|
||||
}
|
||||
} finally {
|
||||
@@ -290,9 +350,11 @@ $env:CORS_ALLOWED_ORIGINS = "$frontendBaseUrl,http://localhost:$selectedFrontend
|
||||
Remove-Item Env:EMAIL_FROM_NAME -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:VITE_API_PROXY_TARGET -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:VITE_API_BASE_URL -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:BOOTSTRAP_SECRET -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:JWT_SECRET -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:DEFAULT_ADMIN_EMAIL -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:DEFAULT_ADMIN_PASSWORD -ErrorAction SilentlyContinue
|
||||
Remove-Item $serverExePath -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item $e2eConfigPath -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item $e2eRunRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user