Source code for app.core.projects

"""Projects API router - full CRUD for Kumiho projects."""

from typing import Any, List

from fastapi import APIRouter, Depends, HTTPException, Query, Request, status

from app.dependencies import get_kumiho_client
from app.models.project import ProjectCreate, ProjectUpdate, ProjectResponse
from app.models.common import StatusResponse
from app.core.kumiho_http import translate_kumiho_exception
import kumiho
from kumiho.client import ProjectLimitError

router = APIRouter()


[docs] @router.get("", response_model=List[ProjectResponse]) async def list_projects( request: Request, client: Any = Depends(get_kumiho_client) ): """List all projects visible to the authenticated user.""" try: projects = kumiho.get_projects() author = getattr(request.state, "kumiho_author", None) username = getattr(request.state, "kumiho_username", None) return [ProjectResponse.from_domain(p, author=author, username=username) for p in projects] except Exception as e: raise translate_kumiho_exception(e)
[docs] @router.post("", response_model=ProjectResponse, status_code=status.HTTP_201_CREATED) async def create_project( request_state: Request, request: ProjectCreate, client: Any = Depends(get_kumiho_client) ): """Create a new project.""" try: project = kumiho.create_project( name=request.name, description=request.description ) author = getattr(request_state.state, "kumiho_author", None) username = getattr(request_state.state, "kumiho_username", None) return ProjectResponse.from_domain(project, author=author, username=username) except ProjectLimitError as e: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=f"Project limit reached: {str(e)}" ) except HTTPException: raise except Exception as e: raise translate_kumiho_exception(e)
[docs] @router.get("/{name}", response_model=ProjectResponse) async def get_project( request: Request, name: str, client: Any = Depends(get_kumiho_client) ): """Get a specific project by name.""" try: project = kumiho.get_project(name) if not project: raise HTTPException(status_code=404, detail="Project not found") author = getattr(request.state, "kumiho_author", None) username = getattr(request.state, "kumiho_username", None) return ProjectResponse.from_domain(project, author=author, username=username) except HTTPException: raise except Exception as e: raise translate_kumiho_exception(e)
[docs] @router.patch("/{name}", response_model=ProjectResponse) async def update_project( request_state: Request, name: str, request: ProjectUpdate, client: Any = Depends(get_kumiho_client) ): """Update a project's properties.""" try: project = kumiho.get_project(name) if not project: raise HTTPException(status_code=404, detail="Project not found") updated = project.update( description=request.description, allow_public=request.allow_public ) author = getattr(request_state.state, "kumiho_author", None) username = getattr(request_state.state, "kumiho_username", None) return ProjectResponse.from_domain(updated, author=author, username=username) except HTTPException: raise except Exception as e: raise translate_kumiho_exception(e)
[docs] @router.delete("/{name}", status_code=status.HTTP_204_NO_CONTENT) async def delete_project( name: str, force: bool = Query(False, description="Force deletion even if project has content"), client: Any = Depends(get_kumiho_client) ): """Delete a project.""" try: project = kumiho.get_project(name) if not project: raise HTTPException(status_code=404, detail="Project not found") project.delete(force=force) except HTTPException: raise except Exception as e: raise translate_kumiho_exception(e)