WIP-CHECKPOINT[auth-refactor]: 固化工程师崩溃前部分成果 + 同树其他未提交WIP(仅源码,不含密钥/二进制)-- 待重激活工程师续作
This commit is contained in:
@@ -205,10 +205,14 @@ class QrcodeService:
|
||||
|
||||
优先使用 settings.wecom_sso_callback_base + /api/auth_qrcode/scan 拼接完整 URL。
|
||||
企微要求 redirect_uri 必须是完整的可信域名 URL,不能用相对路径。
|
||||
如果未配置 wecom_sso_callback_base,则抛出异常提醒配置。
|
||||
如果未配置 wecom_sso_callback_base,则尝试读取环境变量作为兜底。
|
||||
"""
|
||||
import os
|
||||
# 优先使用 wecom_sso_callback_base 构建完整 URL
|
||||
callback_base = getattr(settings, "wecom_sso_callback_base", "")
|
||||
if not callback_base:
|
||||
# 兜底: 读环境变量
|
||||
callback_base = os.getenv("WECOM_SSO_CALLBACK_BASE", "")
|
||||
if callback_base:
|
||||
# 去除末尾斜杠,确保路径正确拼接
|
||||
base = callback_base.rstrip("/")
|
||||
@@ -249,25 +253,28 @@ class QrcodeService:
|
||||
logger.warning(f"扫码失败: ticket 已过期或不存在 ticket={ticket[:8]}...")
|
||||
raise ValueError("扫码票据已过期或不存在")
|
||||
|
||||
# 2. 获取用户身份
|
||||
# 2. 获取用户身份(含企微头像 URL,供 confirm 时落库)
|
||||
employee_id = ""
|
||||
name = ""
|
||||
avatar = ""
|
||||
if _dev_mode_enabled():
|
||||
# dev 模式: 用预设 dev 用户
|
||||
# 提取 code 中的 userid(约定 dev 模式下 code 形如 "dev:dev-user-001")
|
||||
employee_id, name = self._dev_extract_user(code)
|
||||
employee_id, name, avatar = self._dev_extract_user(code)
|
||||
logger.info(
|
||||
f"[DEV] 扫码回调模拟: ticket={ticket[:8]}..., "
|
||||
f"employee_id={employee_id}, name={name}"
|
||||
)
|
||||
else:
|
||||
# 生产模式: 调企微 OAuth API
|
||||
employee_id, name = await self._fetch_oauth_user(code)
|
||||
employee_id, name, avatar = await self._fetch_oauth_user(code)
|
||||
|
||||
# 3. 写 Redis 扫码结果(TTL 120s,等待 confirm 端点消费)
|
||||
# avatar 一并写入,confirm 时无需再次调用企微 API 即可同步头像
|
||||
scan_payload = {
|
||||
"employee_id": employee_id,
|
||||
"name": name,
|
||||
"avatar": avatar,
|
||||
"scanned_at": datetime.now().isoformat(),
|
||||
}
|
||||
await self.redis.setex(
|
||||
@@ -303,9 +310,9 @@ class QrcodeService:
|
||||
"""
|
||||
# dev 模式预设用户表(与 dev_auth.py 保持一致)
|
||||
DEV_USERS = {
|
||||
"dev-user-001": ("dev-user-001", "张三(普通员工)"),
|
||||
"dev-agent-001": ("dev-agent-001", "李四(IT 坐席)"),
|
||||
"dev-admin-001": ("dev-admin-001", "钱七(系统管理员)"),
|
||||
"dev-user-001": ("dev-user-001", "张三(普通员工)", ""),
|
||||
"dev-agent-001": ("dev-agent-001", "李四(IT 坐席)", ""),
|
||||
"dev-admin-001": ("dev-admin-001", "钱七(系统管理员)", ""),
|
||||
}
|
||||
|
||||
if code.startswith("dev:"):
|
||||
@@ -313,10 +320,11 @@ class QrcodeService:
|
||||
if user_id in DEV_USERS:
|
||||
return DEV_USERS[user_id]
|
||||
|
||||
# 兜底:用 settings 默认 dev 用户
|
||||
# 兜底:用 settings 默认 dev 用户(dev 模式无企微头像,avatar 留空)
|
||||
return (
|
||||
settings.dev_default_userid,
|
||||
settings.dev_default_name,
|
||||
"",
|
||||
)
|
||||
|
||||
async def _fetch_oauth_user(self, code: str) -> tuple[str, str]:
|
||||
@@ -350,7 +358,8 @@ class QrcodeService:
|
||||
|
||||
user_info = await wecom.get_user_info(user_id)
|
||||
name = user_info.get("name", "")
|
||||
return user_id, name
|
||||
avatar = user_info.get("avatar", "")
|
||||
return user_id, name, avatar
|
||||
finally:
|
||||
try:
|
||||
await wecom.close()
|
||||
@@ -408,6 +417,7 @@ class QrcodeService:
|
||||
|
||||
employee_id = scan_data.get("employee_id", "")
|
||||
name = scan_data.get("name", "")
|
||||
avatar = scan_data.get("avatar", "")
|
||||
if not employee_id:
|
||||
raise ValueError("扫码数据缺少 employee_id")
|
||||
|
||||
@@ -432,6 +442,7 @@ class QrcodeService:
|
||||
employee_id=employee_id,
|
||||
name=name,
|
||||
roles=roles,
|
||||
avatar=avatar,
|
||||
login_source="qrcode",
|
||||
)
|
||||
|
||||
@@ -458,6 +469,7 @@ class QrcodeService:
|
||||
"token": token,
|
||||
"employee_id": employee_id,
|
||||
"name": name,
|
||||
"avatar": avatar,
|
||||
"roles": roles,
|
||||
"require_otp": require_otp,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user