chore: 整理项目结构,清理归档文件,更新部署配置

This commit is contained in:
Simon
2026-07-04 21:01:39 +08:00
parent 8bd4ab0366
commit 64ff1bf7d5
508 changed files with 43575 additions and 14129 deletions
+55 -5
View File
@@ -38,6 +38,7 @@ from unittest.mock import AsyncMock, patch
import pytest
import pytest_asyncio
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.agent import Agent
@@ -49,20 +50,57 @@ from tests.conftest import create_test_conversation, create_test_agent, MockRedi
# 辅助函数
# =============================================================================
async def login_agent(client, user_id: str, name: str) -> dict:
async def login_agent(client, user_id: str, name: str, db_session=None) -> dict:
"""登录坐席并返回认证头字典。
做什么:调用登录 API 获取 token,组装 Authorization 头
为什么:invite-participant 和 remove-participant 端点需要坐席认证
做什么:
1. 如果提供 db_session,确保 Agent + UserRole(agent) 存在
2. 调用登录 API 获取 token,组装 Authorization 头
为什么:leave-participant 等端点需要 agent 角色(RBAC 检查 user_roles 表)
Args:
client: httpx 异步测试客户端
user_id: 坐席ID
name: 坐席名称
db_session: 数据库会话(可选,传入时会创建 UserRole 确保 agent 角色)
Returns:
dict: {"Authorization": "Bearer xxx"}
"""
from app.models.role import Role
from app.models.user_role import UserRole
# 如果提供了 db_session,确保 agent 角色和 UserRole 记录存在
if db_session is not None:
# 确保 agent 角色存在
stmt = select(Role).where(Role.name == "agent")
result = await db_session.execute(stmt)
agent_role = result.scalars().first()
if not agent_role:
agent_role = Role(
name="agent",
display_name="坐席",
description="IT 坐席角色",
permissions=[],
)
db_session.add(agent_role)
await db_session.flush()
# 确保 UserRole 关联存在
ur_stmt = select(UserRole).where(
UserRole.employee_id == user_id,
UserRole.role_id == agent_role.id,
)
ur_result = await db_session.execute(ur_stmt)
if not ur_result.scalars().first():
db_session.add(UserRole(
employee_id=user_id,
role_id=agent_role.id,
source="manual",
assigned_by="test_fixture",
))
await db_session.flush()
response = await client.post(
"/agents/login",
json={"user_id": user_id, "name": name},
@@ -568,10 +606,14 @@ class TestLeaveAsParticipant:
],
)
# 添加认证(传入 db_session 确保 agent 角色)
headers = await login_agent(client, "agent_leave", "坐席", db_session)
with patch("app.services.ws_manager.manager.broadcast", new_callable=AsyncMock):
response = await client.post(
f"/conversations/{conv.id}/leave-participant",
json={"employee_id": "emp_leaver"},
headers=headers,
)
assert response.status_code == 200
@@ -597,9 +639,13 @@ class TestLeaveAsParticipant:
agent_user_id="agent_leave_002",
)
# 添加认证(传入 db_session 确保 agent 角色)
headers = await login_agent(client, "agent_leave_002", "坐席", db_session)
response = await client.post(
f"/conversations/{conv.id}/leave-participant",
json={"employee_id": "emp_stranger"},
headers=headers,
)
data = response.json()
@@ -611,9 +657,12 @@ class TestLeaveAsParticipant:
):
"""验证退出不存在的会话 → 错误码 3003。"""
fake_id = str(uuid.uuid4())
# 添加认证(传入 db_session 确保 agent 角色)
headers = await login_agent(client, "agent_leave_999", "坐席", db_session)
response = await client.post(
f"/conversations/{fake_id}/leave-participant",
json={"employee_id": "emp_ghost"},
headers=headers,
)
data = response.json()
@@ -648,7 +697,7 @@ class TestInviteEndToEnd:
agent_user_id="owner_e2e",
)
headers = await login_agent(client, "owner_e2e", "坐席E2E")
headers = await login_agent(client, "owner_e2e", "坐席E2E", db_session)
# Step 1: 邀请
with patch("app.services.ws_manager.manager.broadcast", new_callable=AsyncMock):
@@ -680,11 +729,12 @@ class TestInviteEndToEnd:
zhang = next(p for p in participants_after_join if p["id"] == "emp_e2e_zhang")
assert zhang["joined"] is True
# Step 3: 退出
# Step 3: 退出(需要 agent 认证)
with patch("app.services.ws_manager.manager.broadcast", new_callable=AsyncMock):
leave_resp = await client.post(
f"/conversations/{conv.id}/leave-participant",
json={"employee_id": "emp_e2e_zhang"},
headers=headers,
)
assert leave_resp.status_code == 200