131 lines
4.3 KiB
Python
131 lines
4.3 KiB
Python
# Grey Haven Studio - FastAPI CRUD Endpoint Template
|
|
# Copy this template for new resource endpoints
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlmodel import Session
|
|
from typing import Optional
|
|
|
|
from app.core.dependencies import get_current_user, get_db
|
|
from app.models.user import User
|
|
from app.repositories.resource_repository import ResourceRepository # TODO: Update import
|
|
from app.schemas.resource import ResourceCreate, ResourceRead, ResourceUpdate, PaginatedResponse # TODO: Update import
|
|
|
|
# TODO: Update prefix, tags, and model name
|
|
router = APIRouter(prefix="/api/v1/resources", tags=["resources"])
|
|
|
|
|
|
@router.get("", response_model=PaginatedResponse[ResourceRead], status_code=status.HTTP_200_OK)
|
|
async def list_resources(
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
# TODO: Add filter parameters as needed
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> PaginatedResponse[ResourceRead]:
|
|
"""
|
|
List all resources in the current tenant with pagination.
|
|
|
|
- **skip**: Number of records to skip (pagination offset)
|
|
- **limit**: Maximum number of records to return (max 100)
|
|
- **Returns**: Paginated list of resources
|
|
"""
|
|
repository = ResourceRepository(db, tenant_id=current_user.tenant_id)
|
|
|
|
# TODO: Build filter criteria if needed
|
|
filters = {}
|
|
|
|
resources = await repository.list(filters=filters, skip=skip, limit=limit)
|
|
total = await repository.count(filters=filters)
|
|
|
|
return PaginatedResponse(
|
|
items=resources,
|
|
total=total,
|
|
skip=skip,
|
|
limit=limit,
|
|
has_more=(skip + limit) < total,
|
|
)
|
|
|
|
|
|
@router.get("/{resource_id}", response_model=ResourceRead, status_code=status.HTTP_200_OK)
|
|
async def get_resource(
|
|
resource_id: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> ResourceRead:
|
|
"""Get a single resource by ID (tenant-isolated)."""
|
|
repository = ResourceRepository(db, tenant_id=current_user.tenant_id)
|
|
resource = await repository.get_by_id(resource_id)
|
|
if not resource:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Resource with ID {resource_id} not found",
|
|
)
|
|
return resource
|
|
|
|
|
|
@router.post("", response_model=ResourceRead, status_code=status.HTTP_201_CREATED)
|
|
async def create_resource(
|
|
resource_data: ResourceCreate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> ResourceRead:
|
|
"""
|
|
Create a new resource in the current tenant.
|
|
|
|
**Errors**:
|
|
- 409 Conflict: Duplicate resource
|
|
- 422 Validation Error: Invalid data
|
|
"""
|
|
repository = ResourceRepository(db, tenant_id=current_user.tenant_id)
|
|
|
|
try:
|
|
resource = await repository.create(resource_data)
|
|
return resource
|
|
except IntegrityError:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail="Resource with this identifier already exists",
|
|
)
|
|
|
|
|
|
@router.put("/{resource_id}", response_model=ResourceRead, status_code=status.HTTP_200_OK)
|
|
async def update_resource(
|
|
resource_id: str,
|
|
resource_data: ResourceUpdate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> ResourceRead:
|
|
"""
|
|
Update an existing resource (tenant-isolated).
|
|
|
|
All fields are optional - only provided fields will be updated.
|
|
"""
|
|
repository = ResourceRepository(db, tenant_id=current_user.tenant_id)
|
|
resource = await repository.update(resource_id, resource_data)
|
|
if not resource:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Resource with ID {resource_id} not found",
|
|
)
|
|
return resource
|
|
|
|
|
|
@router.delete("/{resource_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def delete_resource(
|
|
resource_id: str,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
) -> None:
|
|
"""
|
|
Soft-delete a resource (tenant-isolated).
|
|
|
|
Returns 204 No Content on success (no response body).
|
|
"""
|
|
repository = ResourceRepository(db, tenant_id=current_user.tenant_id)
|
|
success = await repository.delete(resource_id)
|
|
if not success:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Resource with ID {resource_id} not found",
|
|
)
|