知识图谱的权限逻辑和知识库的权限逻辑保持一致
This commit is contained in:
parent
07b24c1f31
commit
9c056ab391
|
|
@ -632,6 +632,29 @@ async def chat_completion(
|
|||
)
|
||||
|
||||
|
||||
def _wrap_mcp_tool_safe(tool):
|
||||
"""
|
||||
包装 MCP 工具,确保第三方服务异常(网络不可达、超时等)被捕获并以
|
||||
错误字符串返回,而非向上抛出。
|
||||
|
||||
这样 LangChain Agent 在工具调用失败时仍能写入对应的 ToolMessage,
|
||||
保持 checkpoint 中消息历史的完整性,避免下次对话因 tool_calls 缺少
|
||||
配对回复而触发 LLM 400 BadRequest 错误。
|
||||
"""
|
||||
original_arun = tool._arun
|
||||
|
||||
async def safe_arun(*args, **kwargs):
|
||||
try:
|
||||
return await original_arun(*args, **kwargs)
|
||||
except Exception as exc:
|
||||
error_msg = f"工具 [{tool.name}] 调用失败: {exc}"
|
||||
logger.warning(f"MCP 工具异常已捕获,返回错误字符串以维持对话完整性: {error_msg}")
|
||||
return error_msg
|
||||
|
||||
tool._arun = safe_arun
|
||||
return tool
|
||||
|
||||
|
||||
async def _create_agent_for_request(
|
||||
request: ChatRequest,
|
||||
current_user: User,
|
||||
|
|
@ -699,6 +722,7 @@ async def _create_agent_for_request(
|
|||
# 普通聊天模式
|
||||
mcp_client = await get_mcp_client()
|
||||
mcp_tools = await mcp_client.get_tools()
|
||||
# mcp_tools = [_wrap_mcp_tool_safe(t) for t in mcp_tools]
|
||||
logger.info(f"成功加载 {len(mcp_tools)} 个 MCP 工具")
|
||||
|
||||
# 查询用户设置(深度思考是否与模型侧一致取决于 user_list.is_reasoner,
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ async def _fetch_graph_or_404(conn: asyncpg.Connection, graph_pk: int, user: Use
|
|||
creator_id=raw.get("creator_id"),
|
||||
visibility=raw.get("visibility") or "private",
|
||||
)
|
||||
if not can_view_graph(user, gr):
|
||||
if not await can_view_graph(conn, user, gr):
|
||||
raise HTTPException(status_code=404, detail="图谱不存在或无权访问")
|
||||
return raw
|
||||
|
||||
|
|
|
|||
|
|
@ -159,17 +159,19 @@ async def can_upload_to_kb(conn: asyncpg.Connection, user: User, kb: KnowledgeBa
|
|||
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# 知识图谱级权限(保持不变)
|
||||
# 知识图谱级权限(与知识库规则完全一致)
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
def can_view_graph(user: User, g: GraphRecord) -> bool:
|
||||
"""判断用户是否可查看该知识图谱(规则与知识库一致)。"""
|
||||
async def can_view_graph(conn: asyncpg.Connection, user: User, g: GraphRecord) -> bool:
|
||||
"""判断用户是否可查看该知识图谱。leader 权限覆盖本部门及所有子孙部门(与知识库一致)。"""
|
||||
if user.role == "admin":
|
||||
return True
|
||||
if g.creator_id is not None and user.id == g.creator_id:
|
||||
return True
|
||||
if user.role == "leader" and user.department_id is not None and g.department_id == user.department_id:
|
||||
return True
|
||||
if user.role == "leader" and user.department_id is not None and g.department_id is not None:
|
||||
managed = await get_managed_dept_ids(conn, user)
|
||||
if g.department_id in managed:
|
||||
return True
|
||||
vis = g.visibility or "private"
|
||||
if vis == "private":
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ async def check_knowledge_graph_has_rag(knowledge_graph_id: int, user: User) ->
|
|||
creator_id=raw.get("creator_id"),
|
||||
visibility=raw.get("visibility") or "private",
|
||||
)
|
||||
if not can_view_graph(user, gr):
|
||||
if not await can_view_graph(conn, user, gr):
|
||||
return False
|
||||
return (
|
||||
raw.get("build_status") == "completed"
|
||||
|
|
@ -633,7 +633,7 @@ async def get_knowledge_graph_tool_flags(user: User, graph_id: int) -> Dict[str,
|
|||
creator_id=raw.get("creator_id"),
|
||||
visibility=raw.get("visibility") or "private",
|
||||
)
|
||||
if not can_view_graph(user, gr):
|
||||
if not await can_view_graph(conn, user, gr):
|
||||
return out
|
||||
if raw.get("build_status") != "completed":
|
||||
return out
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from typing import Any, Dict, List, Optional, Tuple
|
|||
import asyncpg
|
||||
|
||||
from core.graph_metadata import graph_table_sql
|
||||
from core.permissions import can_manage_graph, can_view_graph
|
||||
from core.permissions import can_manage_graph, can_view_graph, get_managed_dept_ids
|
||||
from models.graph_metadata import GraphRecord
|
||||
from models.user import User
|
||||
from logger.logging import get_logger
|
||||
|
|
@ -95,13 +95,18 @@ class KnowledgeGraphService:
|
|||
dept_id = user.department_id
|
||||
uid = user.id
|
||||
|
||||
# leader 需要获取本部门及所有子孙部门 ID,与知识库列表保持一致
|
||||
managed_dept_ids: List[int] = []
|
||||
if role == "leader" and dept_id is not None:
|
||||
managed_dept_ids = await get_managed_dept_ids(conn, user)
|
||||
|
||||
where_sql = """
|
||||
g.enterprise_id = $1
|
||||
AND (
|
||||
$2::text = 'admin'
|
||||
OR g.creator_id = $3
|
||||
OR ($2::text = 'leader' AND g.department_id IS NOT NULL AND g.department_id = $4)
|
||||
OR (g.visibility = 'department' AND g.department_id IS NOT NULL AND g.department_id = $4)
|
||||
OR ($2::text = 'leader' AND g.department_id IS NOT NULL AND g.department_id = ANY($4::int[]))
|
||||
OR (g.visibility = 'department' AND g.department_id IS NOT NULL AND g.department_id = $5)
|
||||
OR (g.visibility = 'enterprise')
|
||||
)
|
||||
"""
|
||||
|
|
@ -114,6 +119,7 @@ class KnowledgeGraphService:
|
|||
enterprise_id,
|
||||
role,
|
||||
uid,
|
||||
managed_dept_ids,
|
||||
dept_id,
|
||||
)
|
||||
|
||||
|
|
@ -131,11 +137,12 @@ class KnowledgeGraphService:
|
|||
LEFT JOIN department d ON d.id = g.department_id
|
||||
WHERE {where_sql}
|
||||
ORDER BY g.created_at DESC
|
||||
LIMIT $5 OFFSET $6
|
||||
LIMIT $6 OFFSET $7
|
||||
""",
|
||||
enterprise_id,
|
||||
role,
|
||||
uid,
|
||||
managed_dept_ids,
|
||||
dept_id,
|
||||
page_size,
|
||||
offset,
|
||||
|
|
@ -182,6 +189,6 @@ class KnowledgeGraphService:
|
|||
gr = KnowledgeGraphService._row_to_graph_record(raw)
|
||||
except Exception:
|
||||
return None
|
||||
if not can_view_graph(user, gr):
|
||||
if not await can_view_graph(conn, user, gr):
|
||||
return None
|
||||
return await KnowledgeGraphService.enrich_graph_for_response(conn, raw, user)
|
||||
|
|
|
|||
Loading…
Reference in New Issue