feat: Add pagination, search, and filter functionality to user retrieval endpoint

This commit is contained in:
JSC
2025-08-17 11:44:15 +02:00
parent 99c757a073
commit e6f796a3c9
2 changed files with 130 additions and 9 deletions

View File

@@ -1,8 +1,8 @@
"""Admin users endpoints."""
from typing import Annotated
from typing import Annotated, Any
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.database import get_db
@@ -10,7 +10,7 @@ from app.core.dependencies import get_admin_user
from app.models.plan import Plan
from app.models.user import User
from app.repositories.plan import PlanRepository
from app.repositories.user import UserRepository
from app.repositories.user import UserRepository, UserSortField, SortOrder, UserStatus
from app.schemas.auth import UserResponse
from app.schemas.user import UserUpdate
@@ -45,13 +45,33 @@ def _user_to_response(user: User) -> UserResponse:
@router.get("/")
async def list_users(
session: Annotated[AsyncSession, Depends(get_db)],
limit: int = 100,
offset: int = 0,
) -> list[UserResponse]:
"""Get all users (admin only)."""
page: Annotated[int, Query(description="Page number", ge=1)] = 1,
limit: Annotated[int, Query(description="Items per page", ge=1, le=100)] = 50,
search: Annotated[str | None, Query(description="Search in name or email")] = None,
sort_by: Annotated[UserSortField, Query(description="Sort by field")] = UserSortField.NAME,
sort_order: Annotated[SortOrder, Query(description="Sort order")] = SortOrder.ASC,
status_filter: Annotated[UserStatus, Query(description="Filter by status")] = UserStatus.ALL,
) -> dict[str, Any]:
"""Get all users with pagination, search, and filters (admin only)."""
user_repo = UserRepository(session)
users = await user_repo.get_all_with_plan(limit=limit, offset=offset)
return [_user_to_response(user) for user in users]
users, total_count = await user_repo.get_all_with_plan_paginated(
page=page,
limit=limit,
search=search,
sort_by=sort_by,
sort_order=sort_order,
status_filter=status_filter,
)
total_pages = (total_count + limit - 1) // limit # Ceiling division
return {
"users": [_user_to_response(user) for user in users],
"total": total_count,
"page": page,
"limit": limit,
"total_pages": total_pages,
}
@router.get("/{user_id}")