This commit is contained in:
朱潮 2026-02-11 22:43:15 +08:00
parent bd0bf6056e
commit 4a8fffaf7d
3 changed files with 50 additions and 28 deletions

View File

@ -20,7 +20,6 @@ CREATE INDEX IF NOT EXISTS idx_agent_user_is_active ON agent_user(is_active);
CREATE TABLE IF NOT EXISTS agent_bots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
bot_id VARCHAR(255) NOT NULL UNIQUE,
settings JSONB DEFAULT '{"language": "zh", "enable_memori": false, "enable_thinking": false, "tool_response": false}'::jsonb,
owner_id UUID NOT NULL REFERENCES agent_user(id) ON DELETE RESTRICT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
@ -28,7 +27,6 @@ CREATE TABLE IF NOT EXISTS agent_bots (
);
-- agent_bots 索引
CREATE INDEX IF NOT EXISTS idx_agent_bots_bot_id ON agent_bots(bot_id);
CREATE INDEX IF NOT EXISTS idx_agent_bots_owner_id ON agent_bots(owner_id);
-- 3. 创建 agent_user_tokens 表

View File

@ -27,7 +27,7 @@ TOKEN_EXPIRE_HOURS = 24
# ============== 认证函数 ==============
async def verify_admin_auth(authorization: Optional[str]) -> tuple[bool, Optional[str]]:
async def verify_admin_auth(authorization: Optional[str]) -> tuple[bool, Optional[str], Optional[str]]:
"""
验证管理员认证
@ -35,17 +35,17 @@ async def verify_admin_auth(authorization: Optional[str]) -> tuple[bool, Optiona
authorization: Authorization header
Returns:
tuple[bool, Optional[str]]: (是否有效, 用户名)
tuple[bool, Optional[str], Optional[str]]: (是否有效, 用户名, 用户ID)
"""
provided_token = extract_api_key_from_auth(authorization)
if not provided_token:
return False, None
return False, None, None
pool = get_db_pool_manager().pool
async with pool.connection() as conn:
async with conn.cursor() as cursor:
# 检查 token 是否有效且未过期
# 先检查 admin token 表
await cursor.execute("""
SELECT username, expires_at
FROM agent_admin_tokens
@ -54,10 +54,32 @@ async def verify_admin_auth(authorization: Optional[str]) -> tuple[bool, Optiona
""", (provided_token,))
row = await cursor.fetchone()
if not row:
return False, None
if row:
# admin token 有效,返回 admin 用户信息
username = row[0]
# 获取 admin 用户在 agent_user 表中的 ID
await cursor.execute("""
SELECT id FROM agent_user WHERE username = %s
""", (username,))
user_row = await cursor.fetchone()
user_id = str(user_row[0]) if user_row else None
return True, username, user_id
return True, row[0]
# 如果 admin token 无效,再检查普通用户 token
await cursor.execute("""
SELECT u.id, u.username, u.is_admin, t.expires_at
FROM agent_user_tokens t
JOIN agent_user u ON t.user_id = u.id
WHERE t.token = %s
AND t.expires_at > NOW()
AND u.is_active = TRUE
""", (provided_token,))
user_row = await cursor.fetchone()
if user_row:
return True, user_row[1], str(user_row[0])
return False, None, None
def verify_auth(authorization: Optional[str]) -> None:
@ -154,7 +176,7 @@ async def is_admin_user(authorization: Optional[str]) -> bool:
Returns:
bool: 是否是管理员
"""
admin_valid, _ = await verify_admin_auth(authorization)
admin_valid, _, admin_user_id = await verify_admin_auth(authorization)
if admin_valid:
return True
@ -232,7 +254,7 @@ async def is_bot_owner(bot_id: str, user_id: str) -> bool:
检查用户是否是 Bot 的所有者
Args:
bot_id: Bot UUID
bot_id: Bot UUID (可能是 bot_id 字段
user_id: 用户 UUID
Returns:
@ -1219,7 +1241,7 @@ async def get_bots(authorization: Optional[str] = Header(None)):
List[BotResponse]: Bot 列表
"""
# 支持管理员认证和用户认证
admin_valid, admin_username = await verify_admin_auth(authorization)
admin_valid, admin_username, admin_user_id = await verify_admin_auth(authorization)
user_valid, user_id, user_username = await verify_user_auth(authorization)
if not admin_valid and not user_valid:
@ -1245,9 +1267,9 @@ async def get_bots(authorization: Optional[str] = Header(None)):
return [
BotResponse(
id=str(row[0]),
id=str(row[0]), # 使用 UUID 主键
name=row[1],
bot_id=row[2],
bot_id=str(row[0]), # bot_id 也指向主键 id
is_owner=True,
is_shared=False,
owner={"id": str(row[6]), "username": row[7]} if row[6] else None,
@ -1276,9 +1298,9 @@ async def get_bots(authorization: Optional[str] = Header(None)):
return [
BotResponse(
id=str(row[0]),
id=str(row[0]), # 使用 UUID 主键
name=row[1],
bot_id=row[2],
bot_id=str(row[0]), # bot_id 也指向主键 id
is_owner=(str(row[6]) == user_id if row[6] else False),
is_shared=(str(row[6]) != user_id and row[8] is not None) if row[6] else False,
owner={"id": str(row[6]), "username": row[7]} if row[6] else None,
@ -1307,7 +1329,7 @@ async def create_bot(request: BotCreate, authorization: Optional[str] = Header(N
BotResponse: 创建的 Bot 信息
"""
# 支持管理员认证和用户认证
admin_valid, admin_username = await verify_admin_auth(authorization)
admin_valid, admin_username, admin_user_id = await verify_admin_auth(authorization)
user_valid, user_id, user_username = await verify_user_auth(authorization)
if not admin_valid and not user_valid:
@ -1369,7 +1391,7 @@ async def update_bot(
BotResponse: 更新后的 Bot 信息
"""
# 支持管理员认证和用户认证
admin_valid, admin_username = await verify_admin_auth(authorization)
admin_valid, admin_username, admin_user_id = await verify_admin_auth(authorization)
user_valid, user_id, user_username = await verify_user_auth(authorization)
if not admin_valid and not user_valid:
@ -1444,7 +1466,7 @@ async def delete_bot(bot_uuid: str, authorization: Optional[str] = Header(None))
SuccessResponse: 删除结果
"""
# 支持管理员认证和用户认证
admin_valid, admin_username = await verify_admin_auth(authorization)
admin_valid, admin_username, admin_user_id = await verify_admin_auth(authorization)
user_valid, user_id, user_username = await verify_user_auth(authorization)
if not admin_valid and not user_valid:
@ -1491,7 +1513,7 @@ async def get_bot_settings(bot_uuid: str, authorization: Optional[str] = Header(
BotSettingsResponse: Bot 设置信息
"""
# 支持管理员认证和用户认证
admin_valid, admin_username = await verify_admin_auth(authorization)
admin_valid, admin_username, admin_user_id = await verify_admin_auth(authorization)
user_valid, user_id, user_username = await verify_user_auth(authorization)
if not admin_valid and not user_valid:
@ -1500,8 +1522,11 @@ async def get_bot_settings(bot_uuid: str, authorization: Optional[str] = Header(
detail="Unauthorized"
)
# 用户需要检查是否有 read 权限
if user_valid:
# 获取实际的用户ID优先使用 admin 的 user_id
actual_user_id = admin_user_id if admin_user_id else user_id
# 如果是普通用户(非 admin检查是否有 read 权限
if user_valid and not admin_user_id:
if not await check_bot_access(bot_uuid, user_id, 'read'):
raise HTTPException(
status_code=403,
@ -1587,7 +1612,7 @@ async def update_bot_settings(
SuccessResponse: 更新结果
"""
# 支持管理员认证和用户认证
admin_valid, admin_username = await verify_admin_auth(authorization)
admin_valid, admin_username, admin_user_id = await verify_admin_auth(authorization)
user_valid, user_id, user_username = await verify_user_auth(authorization)
if not admin_valid and not user_valid:
@ -1648,7 +1673,6 @@ async def update_bot_settings(
async with pool.connection() as conn:
async with conn.cursor() as cursor:
# 检查 Bot 是否存在
await cursor.execute("SELECT id, settings FROM agent_bots WHERE id = %s", (bot_uuid,))
row = await cursor.fetchone()
@ -2027,7 +2051,7 @@ async def admin_verify(authorization: Optional[str] = Header(None)):
Returns:
AdminVerifyResponse: 验证结果
"""
valid, username = await verify_admin_auth(authorization)
valid, username, admin_user_id = await verify_admin_auth(authorization)
return AdminVerifyResponse(
valid=valid,
@ -2307,7 +2331,7 @@ async def search_users(
List[UserSearchResponse]: 用户列表
"""
# 支持管理员认证<E8AEA4><E8AF81>用户认证
admin_valid, _ = await verify_admin_auth(authorization)
admin_valid, _, admin_user_id = await verify_admin_auth(authorization)
user_valid, user_id, _ = await verify_user_auth(authorization)
if not admin_valid and not user_valid:

View File

@ -463,7 +463,7 @@ async def fetch_bot_config_from_db(bot_user_id: str) -> Dict[str, Any]:
await cursor.execute(
"""
SELECT id, name, settings
FROM agent_bots WHERE bot_id = %s
FROM agent_bots WHERE id = %s
""",
(bot_user_id,)
)
@ -472,7 +472,7 @@ async def fetch_bot_config_from_db(bot_user_id: str) -> Dict[str, Any]:
if not bot_row:
raise HTTPException(
status_code=404,
detail=f"Bot with bot_id '{bot_user_id}' not found"
detail=f"Bot with id '{bot_user_id}' not found"
)
bot_uuid = bot_row[0]