anovo-api / routers /admin.py
rushabh13's picture
Add model choices and fix tone analysis
c82f749
Raw
History Blame Contribute Delete
4.53 kB
"""Admin endpoints: user management and site statistics."""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import func
from sqlalchemy.orm import Session
from config import settings
from database import get_db
from models.db_models import HistoryEntry, User
from models.schemas import (
AdminModelInfo,
AdminModelsResponse,
AdminStatsResponse,
AdminUserUpdate,
UserResponse,
)
from routers.auth import _current_user_id
from services.auth_service import get_user_by_id
from services.llm_client import PREMIUM_MODEL_PROFILES
router = APIRouter(prefix="/api/admin", tags=["admin"])
MODEL_LABELS = {
"gpt-oss-120b": "GPT-OSS 120B",
"gpt-oss-20b": "GPT-OSS 20B",
"compound": "Groq Compound",
"compound-mini": "Groq Compound Mini",
"qwen-3.6-27b": "Qwen 3.6 27B",
}
def _require_admin(
user_id: int = Depends(_current_user_id),
db: Session = Depends(get_db),
) -> User:
"""Dependency that requires the caller to be an admin."""
user = get_user_by_id(db, user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
if not user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
return user
@router.get("/users", response_model=list[UserResponse], summary="List all users")
def list_users(
skip: int = 0,
limit: int = 50,
search: str = "",
admin: User = Depends(_require_admin),
db: Session = Depends(get_db),
) -> list[UserResponse]:
query = db.query(User)
if search:
pattern = f"%{search}%"
query = query.filter(
(User.username.ilike(pattern)) | (User.email.ilike(pattern))
)
users = query.order_by(User.created_at.desc()).offset(skip).limit(limit).all()
return [UserResponse.model_validate(u) for u in users]
@router.patch("/users/{user_id}", response_model=UserResponse, summary="Update a user")
def update_user(
user_id: int,
updates: AdminUserUpdate,
admin: User = Depends(_require_admin),
db: Session = Depends(get_db),
) -> UserResponse:
target = get_user_by_id(db, user_id)
if not target:
raise HTTPException(status_code=404, detail="User not found")
if updates.is_premium is not None:
target.is_premium = updates.is_premium
if updates.is_admin is not None:
target.is_admin = updates.is_admin
db.commit()
db.refresh(target)
return UserResponse.model_validate(target)
@router.delete("/users/{user_id}", status_code=204, summary="Delete a user")
def delete_user(
user_id: int,
admin: User = Depends(_require_admin),
db: Session = Depends(get_db),
):
target = get_user_by_id(db, user_id)
if not target:
raise HTTPException(status_code=404, detail="User not found")
if target.id == admin.id:
raise HTTPException(status_code=400, detail="Cannot delete yourself")
db.query(HistoryEntry).filter(HistoryEntry.user_id == user_id).delete()
db.delete(target)
db.commit()
@router.get("/stats", response_model=AdminStatsResponse, summary="Site statistics")
def get_stats(
admin: User = Depends(_require_admin),
db: Session = Depends(get_db),
) -> AdminStatsResponse:
total_users = db.query(func.count(User.id)).scalar() or 0
premium_users = db.query(func.count(User.id)).filter(User.is_premium.is_(True)).scalar() or 0
admin_users = db.query(func.count(User.id)).filter(User.is_admin.is_(True)).scalar() or 0
total_history = db.query(func.count(HistoryEntry.id)).scalar() or 0
return AdminStatsResponse(
total_users=total_users,
premium_users=premium_users,
admin_users=admin_users,
total_history_entries=total_history,
)
@router.get("/models", response_model=AdminModelsResponse, summary="Writing model status")
def model_status(
admin: User = Depends(_require_admin),
) -> AdminModelsResponse:
"""Return safe, non-secret provider information for the admin dashboard."""
return AdminModelsResponse(
provider="Groq",
provider_configured=bool(settings.groq_api_keys or settings.groq_api_key),
standard_model=settings.groq_model,
models=[
AdminModelInfo(
id=profile,
label=MODEL_LABELS[profile],
provider_model=provider_model,
status="preview" if profile == "qwen-3.6-27b" else "production",
)
for profile, provider_model in PREMIUM_MODEL_PROFILES.items()
],
)