feat: OTP首次绑定 + 三端登录修复 + 管理端权限修复 (2026-07-08)

OTP首次绑定:
- 新增统一 OTP 路由 /auth/otp-* (otp.py + router.py)
- 坐席端 OTP 绑定面板 (OtpBindPanel.vue)
- 管理端 OTP 管理列表 (MfaManage.vue)
- agent_login 签发半认证 token 支持首次绑定流程

三端登录修复:
- 坐席/管理端去掉'返回扫码登录'按钮
- 管理端改为二维码始终可见+轮询扫码状态
- 员工端 /itdesk/ 改为 alias 直接服务 H5 (不再301重定向)
- docker-compose 添加 h5 volume 挂载

管理端权限修复:
- 扫码登录改用 get_user_roles() 替代写死 roles=['agent']
- get_user_roles() 增加 agents.role 回退
- 新增 GET /admin/roles/user-roles 端点
- 角色管理页加载用户角色分配数据

文档更新:
- OTP PRD + 系统设计文档
- 故障排查手册 v1.1 (新增6案例)
- nginx 生产基准配置
This commit is contained in:
Simon
2026-07-08 21:54:57 +08:00
parent 6f0fbbb066
commit 400ce3ddcb
27 changed files with 2822 additions and 312 deletions
+10 -3
View File
@@ -18,6 +18,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.models.role import Role
from app.models.role_mapping_rule import RoleMappingRule
from app.models.user_role import UserRole
from app.models.agent import Agent
from app.services.wecom_service import WecomService
logger = logging.getLogger(__name__)
@@ -59,26 +60,32 @@ class RoleMappingService:
async def get_user_roles(self, employee_id: str) -> List[str]:
"""获取用户的角色列表。
查询 user_roles 表,返回用户拥有的角色标识列表
查询 user_roles 表,同时回退到 agents.role 字段作为补充
Args:
employee_id: 企微 UserID
Returns:
List[str]: 角色标识列表(如 ["user", "agent"]
List[str]: 角色标识列表(如 ["user", "agent", "admin"]
"""
stmt = (
select(Role.name)
.join(UserRole, Role.id == UserRole.role_id)
.where(UserRole.employee_id == employee_id)
.where(
# 过滤已过期的角色
(UserRole.expires_at.is_(None)) | (UserRole.expires_at > datetime.now())
)
)
result = await self.db.execute(stmt)
roles = [row[0] for row in result.all()]
# 回退到 agents.role 字段(兼容旧数据)
agent_stmt = select(Agent.role).where(Agent.user_id == employee_id)
agent_result = await self.db.execute(agent_stmt)
agent_role = agent_result.scalar_one_or_none()
if agent_role and agent_role not in roles:
roles.append(agent_role)
# 如果没有角色,添加默认的 user 角色
if not roles:
roles = ["user"]