feat(v0.7.1): P0 修复 + 企微 SSO + RBAC 细粒度 + audit_log

P0 修复:
- /api/ready import 错误 (_get_engine + settings.create_redis_client)
- 删 agent.otp_secret/otp_enabled 双字段 (migration 026)
- 重建 021_rbac migration (IF NOT EXISTS 兼容)

P1 新增:
- 企微 SSO (auth_wecom_sso.py, useWeChatWorkSSO composable, PortalSelect UA 检测)
- RBAC 5 角色 × 4 资源 × 4 操作 × 3 范围 (rbac_service + seed_rbac + require_permission)
- audit_log 模型 + migration 027 + 服务 + API
- 管理后台 RBAC 权限矩阵 UI (PermissionsMatrix.vue)

质量:
- pytest 405 passed / 33 pre-existing failed / 4 xfailed (v0.7.1 引入失败 = 0)
- conftest GBK patch 强制 UTF-8 读 .env
- .gitignore 排除 *.b64 (含 admin token 凭据)
- DEPLOY-v0.7.1.md 7 步 runbook + 4 坑 + 回滚预案
This commit is contained in:
Simon
2026-06-22 17:38:47 +08:00
parent 2e6ac0f0ab
commit 78f60c6857
30 changed files with 2928 additions and 49 deletions
+19
View File
@@ -11,14 +11,18 @@
# 3. dev 模式: 跳过企微 OAuth2,使用预设 dev 用户直接模拟扫码结果
# =============================================================================
import base64
import json
import logging
import os
import secrets
from datetime import datetime, timedelta
from io import BytesIO
from typing import Any, Dict, Optional
from urllib.parse import urlencode
import qrcode
import redis.asyncio as aioredis
from app.config import settings
@@ -140,10 +144,25 @@ class QrcodeService:
return {
"ticket": ticket,
"qrcode_url": qrcode_url,
"qrcode_png_base64": self._render_qrcode_png(qrcode_url),
"expires_in": TICKET_TTL_SECONDS,
"expires_at": expires_at,
}
@staticmethod
def _render_qrcode_png(url: str) -> str:
"""把 url 编成 PNG 并返回 base64 字符串,供前端 <img :src="data:image/png;base64,..."> 直接渲染。
依赖: requirements.txt 已有 qrcode[pil]==7.4.2 (2026-06-15 加的,原本为 OTP 绑定)。
"""
qr = qrcode.QRCode(version=1, box_size=10, border=2)
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
buf = BytesIO()
img.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode("ascii")
def _build_oauth_url(self, ticket: str) -> str:
"""拼接企微 OAuth2 授权 URL(供前端生成二维码)。