fix(opp): LIKE 模式参数化——SQL字面量裸%被驱动当格式化符炸ValueError(实测500), agent.% 改走 ${agent_pat}$ 传值

This commit is contained in:
yumoqing 2026-09-09 15:18:50 +08:00
parent 8627b855c0
commit 2f71d851ef
2 changed files with 10 additions and 5 deletions

View File

@ -72,7 +72,8 @@ slash 命令:`/hot` `/ai` `/reports` `/oppdiag`。
1. **按项目 owner 过滤**`list_visible_reports` 单一事实源):
- 挂项目的报告:当前用户是项目 owner`sd_projects.created_by==uid`)才可见;
agent 创建的项目(`created_by LIKE 'agent.%'`)降级为同机构成员可见
agent 创建的项目(`created_by LIKE 'agent.%'`,模式经 `${kw}$` 参数化——
SQL 字面量裸 `%` 会被驱动当格式化符炸 ValueError实测踩过降级为同机构成员可见
(对齐 `check_project_owner` 既有降级语义,不重复发明)
- 未挂项目的报告(平台级调研,存量数据大多是这类):登录用户可见
- 项目已删的孤儿报告owner 无法验证 → 不可见宁缺勿漏LEFT JOIN 自然排除)

View File

@ -110,6 +110,9 @@ async def list_visible_reports(sor, user_id):
if not user_id:
return []
uorg = await _user_org(sor, user_id)
# ⚠️ LIKE 模式必须走 ${kw}$ 参数化——SQL 字面量里的裸 % 会被驱动当格式化符
# (实测 ValueError: unsupported format characterrag_client.py 的
# NOT LIKE 'agent.%' 是同一颗潜伏雷)。参数值里的 % 安全。
sql = (
"SELECT r.id, r.project_id, r.software, r.title, r.status, r.ppt_path, "
"r.created_by, r.created_at, r.updated_at, "
@ -117,10 +120,11 @@ async def list_visible_reports(sor, user_id):
"FROM opp_reports r LEFT JOIN sd_projects p ON r.project_id = p.id "
"WHERE (r.project_id IS NULL OR r.project_id = '') "
" OR p.created_by = ${uid}$ "
+ (" OR (p.created_by LIKE 'agent.%' AND p.org_id = ${uorg}$ AND ${uorg}$ <> '') "
if uorg else "")
+ "ORDER BY r.created_at DESC LIMIT 200")
recs = await sor.sqlExe(sql, {"uid": user_id, "uorg": uorg})
" OR (p.created_by LIKE ${agent_pat}$ "
" AND p.org_id = ${uorg}$ AND ${uorg}$ <> '') "
"ORDER BY r.created_at DESC LIMIT 200")
recs = await sor.sqlExe(sql, {"uid": user_id, "uorg": uorg,
"agent_pat": "agent.%"})
await sor.sqlExe("COMMIT", {})
return rows_to_dicts(recs)