WIP-CHECKPOINT[auth-refactor]: 固化工程师崩溃前部分成果 + 同树其他未提交WIP(仅源码,不含密钥/二进制)-- 待重激活工程师续作
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
# Release Notes v0.7.1
|
||||
|
||||
> 📅 发布日期:2026-06-23 | 类型:🔐 安全 + ✨ 功能 | 紧急度:🟡 重要
|
||||
> 🔄 补充:2026-06-24 hotfix #116/#118/#119/#120 已部署(详见文末"补充 hotfix"小节)
|
||||
|
||||
## 🎯 本版本重点
|
||||
|
||||
1. **修复扫码登录 iOS NSURLErrorCannotFindHost** — 企微 App 用户扫码不再报错
|
||||
2. **完整 MFA + RBAC 权限体系** — 5 角色细粒度权限 + 高危操作二次认证
|
||||
3. **H5 员工端企微 OAuth 登录** — 员工不再需要输账号密码
|
||||
4. **🆕 扫码登录去掉手机 confirm 步骤** — 企微 App 无确认 UI,扫码成功 = 直接登录
|
||||
|
||||
## 🔐 安全修复
|
||||
|
||||
### #109 P0:扫码登录 NSURLError 修复
|
||||
|
||||
**问题**:用户企微 App 访问 `https://itsupport.servyou.com.cn/itportal/`,扫描二维码后跳转报 `NSURLErrorCannotFindHost`(iOS WebView DNS 解析失败)
|
||||
|
||||
**根因**:`backend/app/config.py` 新字段 `qrcode_oauth_callback` 用了 pydantic 默认行为,**不剥环境变量前缀**
|
||||
- 字段名:`qrcode_oauth_callback`
|
||||
- pydantic-settings 期望 env:`QRCODE_OAUTH_CALLBACK`
|
||||
- 实际 env:`WECOM_QRCODE_CALLBACK`(带前缀,匹配不上)
|
||||
- 结果:`settings.qrcode_oauth_callback = ""`,qrcode_service 走兜底返回**相对路径** `/api/auth_qrcode/scan`
|
||||
- iOS WebView 拼接相对路径失败 → DNS 解析错误
|
||||
|
||||
**修复**:
|
||||
```python
|
||||
from pydantic import Field
|
||||
|
||||
class Settings(BaseSettings):
|
||||
qrcode_oauth_callback: str = Field(
|
||||
default="",
|
||||
validation_alias="WECOM_QRCODE_CALLBACK",
|
||||
)
|
||||
```
|
||||
|
||||
**部署**:docker commit + restart + 验证,详见 [[phase1-progress#109-hotfix-二轮修复]]
|
||||
|
||||
### RBAC 5 角色 × 4 资源 × 4 操作 × 3 范围
|
||||
|
||||
- **5 角色**:super_admin / admin / agent / user / guest
|
||||
- **4 资源**:user / conversation / config / audit_log
|
||||
- **4 操作**:read / create / update / delete
|
||||
- **3 范围**:all / department / self
|
||||
|
||||
### 高危路由白名单 + 中间件
|
||||
|
||||
5 类高危操作需 OTP 二次认证:
|
||||
- `role_change`(角色变更)
|
||||
- `config_change`(配置变更)
|
||||
- `data_export`(数据导出)
|
||||
- `account_disable`(账户禁用)
|
||||
- `account_create_reset`(账户创建/重置)
|
||||
|
||||
## ✨ 新功能
|
||||
|
||||
### 后端扫码登录(端点 4 个)
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
|---|---|---|
|
||||
| `/api/auth_qrcode/create` | POST | 生成二维码(含 PNG base64) |
|
||||
| `/api/auth_qrcode/poll/{ticket}` | POST | 扫码端轮询 |
|
||||
| `/api/auth_qrcode/scan` | POST | 企微回调 |
|
||||
| `/api/auth_qrcode/confirm` | POST | 用户确认登录 |
|
||||
|
||||
### 后端 MFA + pyotp(端点 5 个)
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
|---|---|---|
|
||||
| `/api/mfa/status` | GET | 查询绑定状态 |
|
||||
| `/api/mfa/bind/start` | POST | 开始绑定(返回 secret + QR) |
|
||||
| `/api/mfa/bind/confirm` | POST | 确认绑定 |
|
||||
| `/api/mfa/verify` | POST | 验证 OTP |
|
||||
| `/api/mfa/disable` | POST | 禁用 MFA |
|
||||
|
||||
### 前端 MFA UI
|
||||
|
||||
- `MfaBind.vue` — 绑定弹窗
|
||||
- `useHighRiskOtp.ts` composable — 高危操作 OTP 弹窗
|
||||
- `Login.vue` / `TopBar.vue` — 集成 MFA 状态显示
|
||||
- 路由 + store 全链路集成
|
||||
|
||||
### H5 员工端 OAuth 登录
|
||||
|
||||
- 部署路径:`https://itsupport.servyou.com.cn/itdesk/`
|
||||
- 自动 OAuth 静默授权(`snsapi_base`)
|
||||
- 会话列表 + 消息收发
|
||||
- 已完成 E2E 验证(#104)
|
||||
|
||||
## 🛠️ 部署要点
|
||||
|
||||
### 必备环境变量
|
||||
|
||||
```bash
|
||||
# /opt/wecom-it-desk/.env
|
||||
WECOM_QRCODE_CALLBACK=https://itsupport.servyou.com.cn/api/auth_qrcode/scan
|
||||
WECOM_SSO_ENABLED=true
|
||||
WECOM_SSO_CALLBACK_BASE=https://itsupport.servyou.com.cn
|
||||
```
|
||||
|
||||
### 部署清单
|
||||
|
||||
- [x] Backend commit `78f60c6`(v0.7.1-dev)
|
||||
- [x] docker 镜像 `wecom-it-desk-backend:latest` 已 commit 新 config
|
||||
- [x] 容器已重启 + /api/ready 200
|
||||
- [x] H5 dist 已部署到 `/opt/wecom-it-desk/nginx/html/itdesk/`
|
||||
- [x] nginx 已 reload
|
||||
- [x] /api/auth_qrcode/create 返回绝对 URL
|
||||
- [ ] Gitea push(等用户重授权 token)
|
||||
- [ ] 企微 App 实际扫码验证
|
||||
|
||||
## ⚠️ 已知问题
|
||||
|
||||
1. **Gitea push 阻塞**:`workbuddy-claude` token 2026-06-15 被吊销,需去 Gitea Web 重授权
|
||||
2. **#108 still pending**:v0.7.1-dev 78f60c6 未推到 origin
|
||||
3. **/api/admin/ IP 白名单**仍是 0.0.0.0/0(临时方案),v1.0 前必须收窄
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [[H5-DEPLOY-RUNBOOK-v0.7.1]] — H5 部署 runbook
|
||||
- [[DEPLOY-LOGIN-MIGRATION-v0.7.0]] — 旧版扫码登录
|
||||
- [[E2E-CHECKLIST-v0.7.0]] — 端到端验收
|
||||
- [[NGINX-DOMAIN-ROUTING]] — nginx 域名分发
|
||||
- [[USER-GUIDE-QRCODE-MFA]] — 用户手册
|
||||
- [[phase1-progress]] — 进展跟踪
|
||||
|
||||
## 📊 改动统计
|
||||
|
||||
- **代码**:22 文件 / +4705 行
|
||||
- **测试**:78 passed + 4 xfail + 33 pre-existing failures(已分类)
|
||||
- **文档**:5 新增 / 3 更新
|
||||
- **Agent**:4 并行 worktree 合并
|
||||
|
||||
---
|
||||
|
||||
## 🔄 补充 hotfix(2026-06-24 部署)
|
||||
|
||||
### #116 P0 + #118 P0:扫码端点 405 + ticket≠state
|
||||
|
||||
**问题**:
|
||||
- 坐席扫码登录报 `405 Method Not Allowed`
|
||||
- 企微 OAuth 回调走 GET(`?code=xxx&state=<ticket>`),旧代码只支持 POST
|
||||
- 即使改双方法,`Optional[str] = None` 没 `Query()` 装饰器,FastAPI 当 body 参数处理
|
||||
- 函数参数叫 `ticket`,企微用 `state`,参数名不匹配
|
||||
|
||||
**修复**:`backend/app/api/auth_qrcode.py` scan 端点
|
||||
```python
|
||||
@router.api_route("/scan", methods=["GET", "POST"], response_model=None)
|
||||
async def scan_qrcode(
|
||||
body: Optional[QrcodeScanRequest] = None,
|
||||
ticket: Optional[str] = Query(None, description="兼容旧参数名"),
|
||||
state: Optional[str] = Query(None, description="企微 OAuth state 标准参数名"),
|
||||
code: Optional[str] = Query(None, description="企微 OAuth 授权码"),
|
||||
redis_client = Depends(dep_redis),
|
||||
):
|
||||
if body is not None:
|
||||
final_ticket, final_code = body.ticket, body.code
|
||||
else:
|
||||
final_ticket = state or ticket # 优先 state(企微标准),回退 ticket
|
||||
final_code = code
|
||||
```
|
||||
|
||||
**部署**:`deploy-staging/hotfix-116-qrcode-scan-get/` — webcli v7 一键,20/20 pytest 过
|
||||
|
||||
### #119:webcli v7 全自动部署链路
|
||||
|
||||
复用 jumpserver Playwright + Luna webcli + OTP 自动,实现 18-31KB 命令脚本单次输入,2-3 分钟跑完。
|
||||
|
||||
### #120 P0:扫码成功 = 自动登录(去掉 confirm)
|
||||
|
||||
**问题**:企微 App 端没有"确认登录" UI,旧 confirm 步骤在生产永远走不通(用户报告"扫码成功后,手机端没有出现确认登录按钮")
|
||||
|
||||
**用户决策**:方案 A — 扫码成功 = 自动登录(推荐),2026-06-24 拍板
|
||||
|
||||
**修复**:`backend/app/services/qrcode_service.py` `process_scan` 默认 `auto_confirm=True`
|
||||
- 扫码成功直接写 `qrcode:confirm:{ticket}`(含 token)
|
||||
- 前端 poll 立即拿到 status=confirmed + token
|
||||
- 跳过手机 confirm 步骤
|
||||
- 默认 roles=["user"],admin/agent 走 portal 端角色选择
|
||||
|
||||
**测试**:20/20 pytest 过(`test_scan_then_poll_returns_confirmed` + `test_scan_auto_confirm_writes_confirm_key` 等)
|
||||
|
||||
**部署**:`deploy-staging/hotfix-120-qrcode-auto-confirm/` — webcli v7 一键,容器内 `/api/ready` 200 OK
|
||||
|
||||
**残留**:外部域名 `https://itsupport.servyou.com.cn/api/ready` 不通(nginx `/api/` upstream 配错 + 8000 端口未暴露),**等 #48 修复**。容器内 backend 完全健康。
|
||||
Reference in New Issue
Block a user