Files
geointel/backend/app/api/routes/projects.py
T
Codex 0fae53a7de
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s
Harden RC7 API response contracts
2026-07-18 05:07:35 +02:00

67 lines
2.6 KiB
Python

from __future__ import annotations
from typing import Literal
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.schemas import Envelope
from app.schemas.project import ProjectCreate, ProjectDeleteResult, ProjectList, ProjectRead, ProjectUpdate
from app.services.project_service import ProjectService
from app.utils.response import envelope
router = APIRouter(prefix="/projects", tags=["projects"])
@router.get("", response_model=Envelope[ProjectList])
def list_projects(
limit: int = Query(default=50, ge=1, le=200),
offset: int = Query(default=0, ge=0),
name: str | None = Query(default=None, min_length=1, max_length=255),
project_status: Literal["active", "archived", "all"] = Query(default="active", alias="status"),
db: Session = Depends(get_db),
):
projects, total = ProjectService.list_projects(
db,
limit=limit,
offset=offset,
name=name,
project_status=project_status,
)
return envelope({"items": [ProjectRead.model_validate(item).model_dump() for item in projects], "total": total, "limit": limit, "offset": offset})
@router.post("", status_code=status.HTTP_201_CREATED, response_model=Envelope[ProjectRead])
def create_project(payload: ProjectCreate, db: Session = Depends(get_db)):
project = ProjectService.create_project(db, payload)
return envelope(ProjectRead.model_validate(project).model_dump())
@router.get("/{project_id}", response_model=Envelope[ProjectRead])
def get_project(project_id: UUID, db: Session = Depends(get_db)):
project = ProjectService.get_project(db, project_id)
if not project:
raise HTTPException(status_code=404, detail="Project not found")
return envelope(ProjectRead.model_validate(project).model_dump())
@router.patch("/{project_id}", response_model=Envelope[ProjectRead])
def update_project(project_id: UUID, payload: ProjectUpdate, db: Session = Depends(get_db)):
project = ProjectService.update_project(db, project_id, payload)
if not project:
raise HTTPException(status_code=404, detail="Project not found")
return envelope(ProjectRead.model_validate(project).model_dump())
@router.delete(
"/{project_id}",
status_code=status.HTTP_200_OK,
response_model=Envelope[ProjectDeleteResult],
)
def delete_project(project_id: UUID, db: Session = Depends(get_db)):
if not ProjectService.delete_project(db, project_id):
raise HTTPException(status_code=404, detail="Project not found")
return envelope({"deleted": True})