fix(avatar): prevent takeover loops and isolate settings
This commit is contained in:
@@ -6,7 +6,17 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from database import get_db
|
||||
from routers.knowledge import UPLOAD_DIR
|
||||
from models import Avatar, KnowledgeDoc, KnowledgeChunk, QAPair, Authorization, User
|
||||
from models import (
|
||||
Authorization,
|
||||
Avatar,
|
||||
KnowledgeChunk,
|
||||
KnowledgeDoc,
|
||||
QAPair,
|
||||
TakeoverCursor,
|
||||
TakeoverMessage,
|
||||
TakeoverReplyTask,
|
||||
User,
|
||||
)
|
||||
from responses import ok, fail
|
||||
|
||||
router = APIRouter(tags=["分身"])
|
||||
@@ -74,18 +84,21 @@ def list_avatars(page: int = 1, limit: int = 20, authorization: str = Header(Non
|
||||
|
||||
|
||||
@router.get("/avatar/{avatar_id}")
|
||||
def get_avatar(avatar_id: str, db: Session = Depends(get_db)):
|
||||
a = db.query(Avatar).filter(Avatar.id == avatar_id).first()
|
||||
if not a:
|
||||
return fail("分身不存在", 404)
|
||||
return ok(a.to_dict())
|
||||
def get_avatar(
|
||||
avatar_id: str,
|
||||
authorization: str = Header(None),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
return ok(_require_owned_avatar(db, avatar_id, authorization).to_dict())
|
||||
|
||||
|
||||
@router.post("/avatar")
|
||||
def create_avatar(payload: dict = Body(...), authorization: str = Header(None), db: Session = Depends(get_db)):
|
||||
user = _resolve_user(authorization, db)
|
||||
if not user:
|
||||
raise HTTPException(status_code=401, detail="未登录")
|
||||
a = Avatar(
|
||||
owner_id=user.huihui_user_id if user else "",
|
||||
owner_id=user.huihui_user_id,
|
||||
name=payload.get("name", "未命名分身"),
|
||||
display_name=payload.get("displayName", "") or payload.get("display_name", ""),
|
||||
description=payload.get("description", ""),
|
||||
@@ -102,10 +115,13 @@ def create_avatar(payload: dict = Body(...), authorization: str = Header(None),
|
||||
|
||||
|
||||
@router.put("/avatar/{avatar_id}")
|
||||
def update_avatar(avatar_id: str, payload: dict = Body(...), db: Session = Depends(get_db)):
|
||||
a = db.query(Avatar).filter(Avatar.id == avatar_id).first()
|
||||
if not a:
|
||||
return fail("分身不存在", 404)
|
||||
def update_avatar(
|
||||
avatar_id: str,
|
||||
payload: dict = Body(...),
|
||||
authorization: str = Header(None),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
a = _require_owned_avatar(db, avatar_id, authorization)
|
||||
mapping = {
|
||||
"displayName": "display_name",
|
||||
"photoUrl": "photo_url",
|
||||
@@ -114,22 +130,32 @@ def update_avatar(avatar_id: str, payload: dict = Body(...), db: Session = Depen
|
||||
for key in ("name", "displayName", "description", "photoUrl", "emoji", "status", "tokenBalance", "config"):
|
||||
if key in payload:
|
||||
col = mapping.get(key, key)
|
||||
setattr(a, col, payload[key])
|
||||
value = payload[key]
|
||||
if key == "config":
|
||||
if not isinstance(value, dict):
|
||||
return fail("分身配置格式不正确", 400)
|
||||
value = {**(a.config or {}), **value}
|
||||
setattr(a, col, value)
|
||||
db.commit()
|
||||
db.refresh(a)
|
||||
return ok(a.to_dict())
|
||||
|
||||
|
||||
@router.delete("/avatar/{avatar_id}")
|
||||
def delete_avatar(avatar_id: str, db: Session = Depends(get_db)):
|
||||
a = db.query(Avatar).filter(Avatar.id == avatar_id).first()
|
||||
if not a:
|
||||
return fail("分身不存在", 404)
|
||||
def delete_avatar(
|
||||
avatar_id: str,
|
||||
authorization: str = Header(None),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
a = _require_owned_avatar(db, avatar_id, authorization)
|
||||
# 级联清理关联数据,避免孤儿记录
|
||||
db.query(KnowledgeDoc).filter(KnowledgeDoc.avatar_id == avatar_id).delete()
|
||||
db.query(KnowledgeChunk).filter(KnowledgeChunk.avatar_id == avatar_id).delete()
|
||||
db.query(QAPair).filter(QAPair.avatar_id == avatar_id).delete()
|
||||
db.query(Authorization).filter(Authorization.avatar_id == avatar_id).delete()
|
||||
db.query(TakeoverReplyTask).filter(TakeoverReplyTask.avatar_id == avatar_id).delete()
|
||||
db.query(TakeoverMessage).filter(TakeoverMessage.avatar_id == avatar_id).delete()
|
||||
db.query(TakeoverCursor).filter(TakeoverCursor.avatar_id == avatar_id).delete()
|
||||
db.delete(a)
|
||||
db.commit()
|
||||
return ok({"success": True})
|
||||
|
||||
Reference in New Issue
Block a user