65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
"""用户 AI 接口配置。api_key 用 Fernet 加密存储,不回显明文。"""
|
|
from fastapi import APIRouter, Depends
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.db import get_db
|
|
from app.deps import get_current_user
|
|
from app.models.user import User, UserSettings
|
|
from app.schemas.settings import SettingsOut, SettingsUpdate
|
|
from app.services import crypto
|
|
|
|
router = APIRouter(prefix="/api/settings", tags=["settings"])
|
|
|
|
|
|
async def _get_or_create(db: AsyncSession, user_id: str) -> UserSettings:
|
|
row = await db.scalar(
|
|
select(UserSettings).where(UserSettings.user_id == user_id)
|
|
)
|
|
if row is None:
|
|
row = UserSettings(user_id=user_id)
|
|
db.add(row)
|
|
await db.flush()
|
|
return row
|
|
|
|
|
|
def _to_out(s: UserSettings) -> SettingsOut:
|
|
return SettingsOut(
|
|
llm_base_url=s.llm_base_url,
|
|
llm_text_model=s.llm_text_model,
|
|
llm_vision_model=s.llm_vision_model,
|
|
has_api_key=bool(s.llm_api_key_encrypted),
|
|
)
|
|
|
|
|
|
@router.get("", response_model=SettingsOut)
|
|
async def get_settings(
|
|
db: AsyncSession = Depends(get_db),
|
|
current: User = Depends(get_current_user),
|
|
):
|
|
s = await _get_or_create(db, current.id)
|
|
await db.commit()
|
|
return _to_out(s)
|
|
|
|
|
|
@router.put("", response_model=SettingsOut)
|
|
async def update_settings(
|
|
payload: SettingsUpdate,
|
|
db: AsyncSession = Depends(get_db),
|
|
current: User = Depends(get_current_user),
|
|
):
|
|
s = await _get_or_create(db, current.id)
|
|
data = payload.model_dump(exclude_unset=True)
|
|
for field in ("llm_base_url", "llm_text_model", "llm_vision_model"):
|
|
if field in data:
|
|
setattr(s, field, data[field])
|
|
# api_key:显式传非空值才更新;传空字符串表示清除
|
|
if "api_key" in data:
|
|
if payload.api_key:
|
|
s.llm_api_key_encrypted = crypto.encrypt(payload.api_key)
|
|
elif payload.api_key == "":
|
|
s.llm_api_key_encrypted = None
|
|
await db.commit()
|
|
await db.refresh(s)
|
|
return _to_out(s)
|