Coverage for app/routers/tasks.py: 93.33%

30 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-07-25 15:51 +0000

1""" 

2Tasks Router 

3 

4Read-only access to task information for a deployment. Tasks are created by the 

5deployment flow itself; this router exposes status and details so the frontend 

6can render progress. 

7 

8Every endpoint enforces ``ensure_deployment_access`` (to prevent IDOR) plus 

9``ensure_deployment_owner_view``, so only the deployment creator, teachers, and 

10admins can read task logs — which contain Terraform outputs, IPs, and worker 

11stack traces. Members get a 403 even though they can read deployment metadata. 

12""" 

13 

14from uuid import UUID 

15 

16from fastapi import APIRouter, Depends, HTTPException, status 

17from sqlalchemy.orm import Session 

18 

19from app.crud import deployments as crud_deployments 

20from app.crud import tasks as crud_tasks 

21from app.database import get_db 

22from app.models import User 

23from app.schemas import TaskResponse 

24from app.utils.keycloak_auth import get_current_user_keycloak 

25from app.utils.permissions import ensure_deployment_access, ensure_deployment_owner_view 

26 

27router = APIRouter() 

28 

29 

30@router.get("/deployment/{deployment_id}", response_model=list[TaskResponse]) 

31def get_deployment_tasks( 

32 deployment_id: UUID, 

33 db: Session = Depends(get_db), 

34 current_user: User = Depends(get_current_user_keycloak), 

35): 

36 """List all tasks for a deployment the caller has owner-access to.""" 

37 deployment = crud_deployments.get_deployment(db, deployment_id) 

38 if not deployment: 

39 raise HTTPException( 

40 status_code=status.HTTP_404_NOT_FOUND, 

41 detail="Deployment not found", 

42 ) 

43 ensure_deployment_access(deployment, current_user, db) 

44 ensure_deployment_owner_view(deployment, current_user) 

45 return crud_tasks.get_tasks(db, deployment_id=deployment_id) 

46 

47 

48@router.get("/{task_id}", response_model=TaskResponse) 

49def get_task( 

50 task_id: UUID, 

51 db: Session = Depends(get_db), 

52 current_user: User = Depends(get_current_user_keycloak), 

53): 

54 """Fetch a single task; only the deployment owner-view sees it.""" 

55 task = crud_tasks.get_task(db, task_id) 

56 if not task: 

57 raise HTTPException( 

58 status_code=status.HTTP_404_NOT_FOUND, 

59 detail="Task not found", 

60 ) 

61 deployment = crud_deployments.get_deployment(db, task.deploymentId) 

62 if not deployment: 

63 raise HTTPException( 

64 status_code=status.HTTP_404_NOT_FOUND, 

65 detail="Deployment for task not found", 

66 ) 

67 ensure_deployment_access(deployment, current_user, db) 

68 ensure_deployment_owner_view(deployment, current_user) 

69 return task