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:
2026-04-23 07:14:12 +08:00
parent 82109ec216
commit 3f3bb82f1d
41 changed files with 2681 additions and 283 deletions

View File

@@ -1,5 +1,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
const getAccessTokenMock = vi.fn<() => string | null>()
function jsonResponse(data: unknown, init: ResponseInit = {}) {
return new Response(JSON.stringify(data), {
status: 200,
@@ -12,6 +14,9 @@ function jsonResponse(data: unknown, init: ResponseInit = {}) {
async function loadCsrfModule() {
vi.resetModules()
vi.doMock('./auth-session', () => ({
getAccessToken: () => getAccessTokenMock(),
}))
return import('./csrf')
}
@@ -27,6 +32,8 @@ describe('csrf helpers', () => {
vi.clearAllMocks()
vi.unstubAllGlobals()
vi.unstubAllEnvs()
getAccessTokenMock.mockReset()
getAccessTokenMock.mockReturnValue(null)
clearCsrfCookie()
vi.stubGlobal('fetch', vi.fn())
})
@@ -85,6 +92,7 @@ describe('csrf helpers', () => {
it('fetches and stores a csrf token from the default relative api base', async () => {
const fetchMock = vi.mocked(fetch)
getAccessTokenMock.mockReturnValue('access-token')
fetchMock.mockResolvedValueOnce(
jsonResponse({
code: 0,
@@ -105,6 +113,7 @@ describe('csrf helpers', () => {
method: 'GET',
credentials: 'include',
headers: {
Authorization: 'Bearer access-token',
'Content-Type': 'application/json',
},
},

View File

@@ -13,6 +13,7 @@
// 使用原生 fetch 获取 CSRF Token
import { config } from '@/lib/config'
import { getAccessToken } from './auth-session'
// CSRF Token 存储
let csrfToken: string | null = null
@@ -84,13 +85,19 @@ export async function initCSRFToken(): Promise<string | null> {
if (!token) {
try {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
}
const accessToken = getAccessToken()
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
// 使用原生 fetch 避免循环依赖
const response = await fetch(buildUrl('/auth/csrf-token'), {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
headers,
})
if (response.ok) {