feat(FN-004): merge fusion/fn-004

This commit is contained in:
Fusion
2026-05-14 06:47:30 +02:00
parent 4cbd30ff42
commit 3a18a1f170
62 changed files with 2567 additions and 11 deletions
+100
View File
@@ -0,0 +1,100 @@
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.user import User
from app.models.workspace import Workspace
from app.schemas.workspace import WorkspaceCreate, WorkspaceRead, WorkspaceUpdate
router = APIRouter(tags=["workspaces"])
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}/workspaces", response_model=WorkspaceRead, status_code=status.HTTP_201_CREATED) # noqa: E501
async def create_workspace(
project_id: UUID,
ws_in: WorkspaceCreate,
current_user: User = Depends(get_current_active_user),
session: AsyncSession = Depends(get_db_session),
) -> Workspace:
await _get_project_for_user(project_id, current_user, session)
ws = Workspace(**ws_in.model_dump(), project_id=project_id)
session.add(ws)
await session.commit()
await session.refresh(ws)
return ws
@router.get("/projects/{project_id}/workspaces", response_model=list[WorkspaceRead])
async def list_workspaces(
project_id: UUID,
current_user: User = Depends(get_current_active_user),
session: AsyncSession = Depends(get_db_session),
) -> list[Workspace]:
await _get_project_for_user(project_id, current_user, session)
result = await session.execute(
select(Workspace).where(Workspace.project_id == project_id)
)
return list(result.scalars().all())
@router.get("/projects/{project_id}/workspaces/{ws_id}", response_model=WorkspaceRead)
async def get_workspace(
project_id: UUID,
ws_id: UUID,
current_user: User = Depends(get_current_active_user),
session: AsyncSession = Depends(get_db_session),
) -> Workspace:
await _get_project_for_user(project_id, current_user, session)
ws = await session.get(Workspace, ws_id)
if not ws or ws.project_id != project_id:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Workspace not found")
return ws
@router.put("/projects/{project_id}/workspaces/{ws_id}", response_model=WorkspaceRead)
async def update_workspace(
project_id: UUID,
ws_id: UUID,
ws_in: WorkspaceUpdate,
current_user: User = Depends(get_current_active_user),
session: AsyncSession = Depends(get_db_session),
) -> Workspace:
await _get_project_for_user(project_id, current_user, session)
ws = await session.get(Workspace, ws_id)
if not ws or ws.project_id != project_id:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Workspace not found")
update_data = ws_in.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(ws, field, value)
await session.commit()
await session.refresh(ws)
return ws
@router.delete("/projects/{project_id}/workspaces/{ws_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_workspace(
project_id: UUID,
ws_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)
ws = await session.get(Workspace, ws_id)
if not ws or ws.project_id != project_id:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Workspace not found")
await session.delete(ws)
await session.commit()