Files
Nexus/docs/changelog/2026-06-01-bug-audit-fixes.md
T
2026-07-08 22:31:31 +08:00

78 lines
4.3 KiB
Markdown
Raw 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.
# Changelog: 全站 bug 审查修复 (前端9项 + 后端5项)
**日期**: 2026-06-01
**变更摘要**: 全站巡检发现并修复 14 个 bug1 P0 + 9 P1 + 4 P2),涵盖前端全局搜索崩溃、TOTP登录流程断裂、服务器编辑域名污染、后端Redis阻塞、并发session竞态等
## 动机
对 Nexus 全站进行系统性 bug 审查,发现多个影响生产使用的问题。最严重的 3 个:全局搜索因 `http` 未导入直接崩溃、TOTP 双因素登录完全不可用、编辑服务器后域名被端口字符串污染导致后续连接失败。
## 涉及文件
| 文件 | 变更类型 | 说明 |
|------|----------|------|
| `frontend/src/App.vue` | 修改 | 添加 `http` 导入 |
| `frontend/src/pages/LoginPage.vue` | 修改 | TOTP异常捕获 + 锁定倒计时响应式 |
| `frontend/src/pages/ServersPage.vue` | 修改 | 编辑时 domain 不再拼接端口 |
| `frontend/src/pages/PushPage.vue` | 修改 | Set 索引 → 迭代器 |
| `frontend/src/pages/SettingsPage.vue` | 修改 | API字符串值转数字 |
| `frontend/src/api/index.ts` | 修改 | 删除重复 getList 定义 |
| `frontend/src/pages/TerminalPage.vue` | 修改 | 路径验证正则放松 |
| `frontend/src/composables/useWebSocket.ts` | 修改 | 关闭旧连接再建新连接 |
| `server/api/websocket.py` | 修改 | redis.keys → scan_iter |
| `server/application/services/auth_service.py` | 修改 | TTL 仅在无TTL时设置 |
| `server/api/servers.py` | 修改 | 批量操作加 asyncio.Lock |
| `server/api/settings.py` | 修改 | 弃用API替换 |
## 详细变更
### 前端 P0 修复
1. **App.vue `http` 未导入** — 第320行 `doSearch()` 调用 `http.get()` 但只导入了 `api`,导致 `ReferenceError: http is not defined`。修复:`import { api, http } from '@/api'`
### 前端 P1 修复
2. **TOTP 登录流程断裂**`api()` 在后端返回 202 时抛 `TotpRequiredError`(非 `ApiError` 子类),`LoginPage` catch 只检查 `e instanceof ApiError`TOTP 用户看到"网络错误"无法登录。修复:导入 `TotpRequiredError` 并在 catch 中优先检查
3. **ServersPage 编辑域名污染**`editServer()` 设置 `form.address = domain:port`,保存时 `domain: form.address` 发送含端口字符串。修复:`form.address = item.domain`
4. **PushPage Set 索引无效**`selectedIds.value[0]``Set<number>` 返回 `undefined`。修复:`selectedIds.value.values().next().value`
5. **SettingsPage 类型转换** — API 返回 `value: "80"` 字符串直接赋值给 number 字段。修复:正则检测纯数字字符串并 `Number()` 转换
### 前端 P2 修复
6. **api/index.ts 重复定义**`getList` 方法定义两次,删除第二个
7. **LoginPage 锁定倒计时**`remainingMinutes` computed 依赖 `Date.now()` 非响应式。修复:使用 `ref(Date.now())` + `watch(lockoutUntil)` + 30秒定时器
8. **TerminalPage 路径验证过严** — 正则 `/^[a-zA-Z0-9/._\-]+$/` 排除空格/中文/~。修复:`/^[^\x00-\x1f\x7f"']+$/` 仅排除控制字符和引号
9. **useWebSocket 连接泄漏** — CONNECTING/CLOSING 状态时创建新连接但不关闭旧连接。修复:关闭旧连接后再创建新的
### 后端 P1 修复
10. **websocket.py redis.keys() 阻塞**`KEYS` 命令 O(N) 扫描整个键空间。修复:`scan_iter(match="ws:count:*")` 非阻塞迭代
11. **auth_service.py TTL 重置** — 每次 `sadd``expire` 重置 TTL,频繁刷新的管理员 refresh token 键永不过期。修复:`ttl = await redis.ttl(key)`,仅在 `ttl < 0` 时设置 expire
12. **servers.py 并发 session commit** — 批量操作中 `asyncio.gather` 并发协程共享同一 db session 并 `commit()`。修复:添加 `asyncio.Lock()` 序列化 commit
### 后端 P2 修复
13. **settings.py asyncio.get_event_loop()** — Python 3.10+ 弃用。修复:`asyncio.get_running_loop()`
14. **settings.py datetime.utcfromtimestamp()** — Python 3.12+ 弃用。修复:`datetime.fromtimestamp(ts, tz=timezone.utc)`
## 是否需迁移/重启
- ✅ 需重启 — 后端代码变更
- ✅ 前端需重新构建部署
## 验证方式
1. 登录页 → 输入 admin/Nexus@2026 → 成功跳转仪表盘 ✓
2. 全局搜索框 → 输入"机器人" → 无崩溃(之前会 ReferenceError)✓
3. 控制台零错误 ✓
4. 健康检查 → `ok`