From 912d5ebbede168e8a43366e914ffa8581082d9ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=BD=AE?= Date: Thu, 26 Feb 2026 18:11:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=B8=AD=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routes/bot_manager.py | 165 ++++++++++++++++++++++++++++++++++++++++++ utils/settings.py | 2 +- 2 files changed, 166 insertions(+), 1 deletion(-) diff --git a/routes/bot_manager.py b/routes/bot_manager.py index c6bfc17..d0dcecc 100644 --- a/routes/bot_manager.py +++ b/routes/bot_manager.py @@ -463,6 +463,18 @@ class UserSearchResponse(BaseModel): email: Optional[str] = None +class UserProfileUpdateRequest(BaseModel): + """用户更新个人信息请求""" + username: Optional[str] = None + email: Optional[str] = None + + +class ChangePasswordRequest(BaseModel): + """用户修改密码请求""" + old_password: str + new_password: str + + # --- 模型相关(已废弃,模型管理已迁移到 New API)--- @@ -2438,6 +2450,159 @@ async def get_current_user(authorization: Optional[str] = Header(None)): ) +@router.patch("/api/v1/users/me", response_model=UserInfoResponse) +async def update_current_user( + request: UserProfileUpdateRequest, + authorization: Optional[str] = Header(None) +): + """ + 更新当前用户信息 + + Args: + request: 更新请求(username 或 email) + authorization: Bearer token + + Returns: + UserInfoResponse: 更新后的用户信息 + """ + valid, user_id, current_username = await verify_user_auth(authorization) + + if not valid: + raise HTTPException( + status_code=401, + detail="Invalid token" + ) + + pool = get_db_pool_manager().pool + + async with pool.connection() as conn: + async with conn.cursor() as cursor: + # 构建更新字段 + update_fields = [] + values = [] + + if request.username is not None: + # 检查用户名是否已被其他用户使用 + await cursor.execute(""" + SELECT id FROM agent_user WHERE username = %s AND id != %s + """, (request.username, user_id)) + if await cursor.fetchone(): + raise HTTPException( + status_code=400, + detail="用户名已存在" + ) + update_fields.append("username = %s") + values.append(request.username) + + if request.email is not None: + # 检查邮箱是否已被其他用户使用 + await cursor.execute(""" + SELECT id FROM agent_user WHERE email = %s AND id != %s + """, (request.email, user_id)) + if await cursor.fetchone(): + raise HTTPException( + status_code=400, + detail="邮箱已被使用" + ) + update_fields.append("email = %s") + values.append(request.email) + + if not update_fields: + raise HTTPException( + status_code=400, + detail="No fields to update" + ) + + update_fields.append("updated_at = NOW()") + values.append(user_id) + + await cursor.execute(f""" + UPDATE agent_user + SET {', '.join(update_fields)} + WHERE id = %s + RETURNING id, username, email, is_admin, created_at, last_login + """, values) + row = await cursor.fetchone() + + if not row: + raise HTTPException( + status_code=404, + detail="User not found" + ) + + await conn.commit() + + return UserInfoResponse( + id=str(row[0]), + username=row[1], + email=row[2], + is_admin=row[3] or False, + created_at=row[4].isoformat() if row[4] else "", + last_login=row[5].isoformat() if row[5] else None + ) + + +@router.post("/api/v1/users/me/change-password", response_model=SuccessResponse) +async def change_current_user_password( + request: ChangePasswordRequest, + authorization: Optional[str] = Header(None) +): + """ + 修改当前用户密码 + + Args: + request: 修改密码请求(old_password, new_password) + authorization: Bearer token + + Returns: + SuccessResponse: 操作结果 + """ + valid, user_id, _ = await verify_user_auth(authorization) + + if not valid: + raise HTTPException( + status_code=401, + detail="Invalid token" + ) + + pool = get_db_pool_manager().pool + + async with pool.connection() as conn: + async with conn.cursor() as cursor: + # 验证旧密码 + old_password_hash = hash_password(request.old_password) + + await cursor.execute(""" + SELECT id FROM agent_user WHERE id = %s AND password_hash = %s + """, (user_id, old_password_hash)) + row = await cursor.fetchone() + + if not row: + raise HTTPException( + status_code=400, + detail="原密码错误" + ) + + # 更新新密码 + new_password_hash = hash_password(request.new_password) + + await cursor.execute(""" + UPDATE agent_user + SET password_hash = %s, + updated_at = NOW() + WHERE id = %s + RETURNING username + """, (new_password_hash, user_id)) + user_row = await cursor.fetchone() + + await conn.commit() + + return SuccessResponse( + success=True, + message="密码修改成功" + ) + + @router.get("/api/v1/users", response_model=List[UserSearchResponse]) async def search_users( q: str = "", diff --git a/utils/settings.py b/utils/settings.py index 033e5a8..f8406ef 100644 --- a/utils/settings.py +++ b/utils/settings.py @@ -117,6 +117,6 @@ NEW_API_ADMIN_KEY = os.getenv("NEW_API_ADMIN_KEY", "") # ============================================================ # Single Agent Mode Configuration # ============================================================ -SINGLE_AGENT_MODE = os.getenv("SINGLE_AGENT_MODE", "true") == "true" +SINGLE_AGENT_MODE = os.getenv("SINGLE_AGENT_MODE", "false") == "true" TEMPLATE_BOT_ID = os.getenv("TEMPLATE_BOT_ID", "403a2b63-88e4-4db1-b712-8dcf31fc98ea") TEMPLATE_BOT_NAME = os.getenv("TEMPLATE_BOT_NAME", "智能助手")