import uuid from datetime import datetime, timezone from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.core.database import get_db from app.core.deps import get_superuser from app.core.security import get_password_hash, verify_password from app.models.user import SystemSettings, User from app.schemas import ( AdminProfileUpdate, AdminUserCreate, AdminUserOut, AdminUserPasswordUpdate, AIProviderEnum, PublicSettingsOut, SystemSettingsOut, SystemSettingsUpdate, ) router = APIRouter(prefix="/admin", tags=["admin"]) def settings_to_out(row: SystemSettings) -> SystemSettingsOut: return SystemSettingsOut( registration_enabled=row.registration_enabled, ai_provider=AIProviderEnum(row.ai_provider or "ollama"), ollama_base_url=row.ollama_base_url, ollama_model=row.ollama_model, openai_base_url=row.openai_base_url, openai_model=row.openai_model, openai_api_key_set=bool(row.openai_api_key), updated_at=row.updated_at, ) def get_or_create_settings(db: Session) -> SystemSettings: row = db.get(SystemSettings, 1) if row is None: row = SystemSettings(id=1, registration_enabled=True) db.add(row) db.commit() db.refresh(row) return row @router.get("/settings", response_model=SystemSettingsOut) def get_settings( db: Session = Depends(get_db), _: User = Depends(get_superuser), ): return settings_to_out(get_or_create_settings(db)) @router.patch("/settings", response_model=SystemSettingsOut) def update_settings( data: SystemSettingsUpdate, db: Session = Depends(get_db), _: User = Depends(get_superuser), ): row = get_or_create_settings(db) if data.registration_enabled is not None: row.registration_enabled = data.registration_enabled if data.ai_provider is not None: row.ai_provider = data.ai_provider.value if data.ollama_base_url is not None: row.ollama_base_url = data.ollama_base_url or None if data.ollama_model is not None: row.ollama_model = data.ollama_model or None if data.openai_base_url is not None: row.openai_base_url = data.openai_base_url or None if data.openai_model is not None: row.openai_model = data.openai_model or None if data.openai_api_key is not None and data.openai_api_key.strip(): row.openai_api_key = data.openai_api_key.strip() row.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(row) return settings_to_out(row) @router.patch("/profile", response_model=AdminUserOut) def update_profile( data: AdminProfileUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_superuser), ): if not data.username and not data.password: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="请填写要修改的内容") if data.password: if not data.current_password: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="修改密码需提供当前密码") if not verify_password(data.current_password, current_user.password_hash): raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="当前密码错误") if data.username and data.username != current_user.username: if db.query(User).filter(User.username == data.username).first(): raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="用户名已存在") current_user.username = data.username if data.password: current_user.password_hash = get_password_hash(data.password) db.commit() db.refresh(current_user) return current_user @router.get("/users", response_model=list[AdminUserOut]) def list_users( db: Session = Depends(get_db), _: User = Depends(get_superuser), ): return db.query(User).order_by(User.created_at).all() @router.post("/users", response_model=AdminUserOut, status_code=status.HTTP_201_CREATED) def create_user( data: AdminUserCreate, db: Session = Depends(get_db), _: User = Depends(get_superuser), ): if db.query(User).filter(User.username == data.username).first(): raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="用户名已存在") user = User(username=data.username, password_hash=get_password_hash(data.password)) db.add(user) db.commit() db.refresh(user) return user @router.patch("/users/{user_id}", response_model=AdminUserOut) def reset_user_password( user_id: uuid.UUID, data: AdminUserPasswordUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_superuser), ): user = db.get(User, user_id) if user is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在") if user.is_superuser and user.id != current_user.id: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="不能修改其他超级管理员") user.password_hash = get_password_hash(data.password) db.commit() db.refresh(user) return user @router.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_user( user_id: uuid.UUID, db: Session = Depends(get_db), current_user: User = Depends(get_superuser), ): if user_id == current_user.id: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="不能删除当前登录账号") user = db.get(User, user_id) if user is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在") if user.is_superuser: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="不能删除超级管理员") db.delete(user) db.commit()