from __future__ import annotations import uuid from fastapi import APIRouter, Depends, HTTPException, Response, status from sqlalchemy.ext.asyncio import AsyncSession from cpv3.infrastructure.auth import get_current_user from cpv3.db.session import get_db from cpv3.modules.projects.schemas import ProjectCreate, ProjectRead, ProjectUpdate from cpv3.modules.projects.service import ProjectService from cpv3.modules.users.models import User router = APIRouter(prefix="/api/projects", tags=["Projects"]) @router.get("/", response_model=list[ProjectRead]) async def list_all_projects( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> list[ProjectRead]: service = ProjectService(db) projects = await service.list_projects(requester=current_user) return [ProjectRead.model_validate(p) for p in projects] @router.post("/", response_model=ProjectRead, status_code=status.HTTP_201_CREATED) async def create_project_endpoint( body: ProjectCreate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> ProjectRead: service = ProjectService(db) project = await service.create_project(requester=current_user, data=body) return ProjectRead.model_validate(project) @router.get("/{project_id}/", response_model=ProjectRead) async def retrieve_project( project_id: uuid.UUID, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> ProjectRead: service = ProjectService(db) project = await service.get_project(project_id) if project is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Not found") if not current_user.is_staff and project.owner_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden") return ProjectRead.model_validate(project) @router.patch("/{project_id}/", response_model=ProjectRead) async def patch_project( project_id: uuid.UUID, body: ProjectUpdate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> ProjectRead: service = ProjectService(db) project = await service.get_project(project_id) if project is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Not found") if not current_user.is_staff and project.owner_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden") project = await service.update_project(project, body) return ProjectRead.model_validate(project) @router.delete("/{project_id}/", status_code=status.HTTP_204_NO_CONTENT) async def delete_project( project_id: uuid.UUID, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ) -> Response: service = ProjectService(db) project = await service.get_project(project_id) if project is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Not found") if not current_user.is_staff and project.owner_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden") await service.deactivate_project(project) return Response(status_code=status.HTTP_204_NO_CONTENT)