from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.auth.dependencies import get_current_active_user from app.db import get_db_session from app.models.project import Project from app.models.repository import Repository from app.models.user import User from app.schemas.repository import RepositoryCreate, RepositoryRead, RepositoryUpdate router = APIRouter(tags=["repositories"]) async def _get_project_for_user( project_id: UUID, user: User, session: AsyncSession ) -> Project: project = await session.get(Project, project_id) if not project or project.owner_id != user.id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Project not found") return project @router.post("/projects/{project_id}/repositories", response_model=RepositoryRead, status_code=status.HTTP_201_CREATED) # noqa: E501 async def create_repository( project_id: UUID, repo_in: RepositoryCreate, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> Repository: await _get_project_for_user(project_id, current_user, session) repo = Repository(**repo_in.model_dump(), project_id=project_id) session.add(repo) await session.commit() await session.refresh(repo) return repo @router.get("/projects/{project_id}/repositories", response_model=list[RepositoryRead]) async def list_repositories( project_id: UUID, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> list[Repository]: await _get_project_for_user(project_id, current_user, session) result = await session.execute( select(Repository).where(Repository.project_id == project_id) ) return list(result.scalars().all()) @router.get("/projects/{project_id}/repositories/{repo_id}", response_model=RepositoryRead) async def get_repository( project_id: UUID, repo_id: UUID, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> Repository: await _get_project_for_user(project_id, current_user, session) repo = await session.get(Repository, repo_id) if not repo or repo.project_id != project_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Repository not found") return repo @router.put("/projects/{project_id}/repositories/{repo_id}", response_model=RepositoryRead) async def update_repository( project_id: UUID, repo_id: UUID, repo_in: RepositoryUpdate, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> Repository: await _get_project_for_user(project_id, current_user, session) repo = await session.get(Repository, repo_id) if not repo or repo.project_id != project_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Repository not found") update_data = repo_in.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(repo, field, value) await session.commit() await session.refresh(repo) return repo @router.delete("/projects/{project_id}/repositories/{repo_id}", status_code=status.HTTP_204_NO_CONTENT) # noqa: E501 async def delete_repository( project_id: UUID, repo_id: UUID, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> None: await _get_project_for_user(project_id, current_user, session) repo = await session.get(Repository, repo_id) if not repo or repo.project_id != project_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Repository not found") await session.delete(repo) await session.commit()