Coverage for app/routers/teams.py: 91.49%

47 statements  

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

1from uuid import UUID 

2 

3from fastapi import APIRouter, Depends, HTTPException, status 

4from sqlalchemy.orm import Session 

5 

6from app.crud import teams as crud_teams 

7from app.database import get_db 

8from app.models import User 

9from app.schemas import TeamCreate, TeamResponse, TeamUpdate, TeamWithMembers 

10from app.utils.keycloak_auth import get_current_user_keycloak 

11from app.utils.permissions import require_staff 

12 

13router = APIRouter() 

14 

15 

16# ---------------------------------------------------------------- 

17# GET ALL TEAMS 

18# ---------------------------------------------------------------- 

19@router.get("/", response_model=list[TeamResponse]) 

20def list_teams( 

21 skip: int = 0, 

22 limit: int = 100, 

23 deployment_id: UUID | None = None, 

24 db: Session = Depends(get_db), 

25 current_user: User = Depends(get_current_user_keycloak) 

26): 

27 """ 

28 Get all teams, optionally filtered to a single deployment. 

29 

30 All authenticated users may list teams; per-team membership gating 

31 happens at ``GET /teams/{team_id}``. 

32 """ 

33 teams = crud_teams.get_teams(db, skip=skip, limit=limit, deployment_id=deployment_id) 

34 return teams 

35 

36 

37# ---------------------------------------------------------------- 

38# GET TEAM BY ID 

39# ---------------------------------------------------------------- 

40@router.get("/{team_id}", response_model=TeamWithMembers) 

41def get_team( 

42 team_id: UUID, 

43 db: Session = Depends(get_db), 

44 current_user: User = Depends(get_current_user_keycloak) 

45): 

46 """Get team by ID with all members""" 

47 team = crud_teams.get_team(db, team_id) 

48 if not team: 

49 raise HTTPException( 

50 status_code=status.HTTP_404_NOT_FOUND, 

51 detail="Team not found" 

52 ) 

53 return team 

54 

55 

56# ---------------------------------------------------------------- 

57# CREATE TEAM (TEACHER/ADMIN ONLY) 

58# ---------------------------------------------------------------- 

59@router.post("/", response_model=TeamResponse, status_code=status.HTTP_201_CREATED) 

60def create_team( 

61 team: TeamCreate, 

62 db: Session = Depends(get_db), 

63 current_user: User = Depends(require_staff) 

64): 

65 """ 

66 Create a new team 

67 - **Requires**: TEACHER or ADMIN role 

68 """ 

69 return crud_teams.create_team(db, team) 

70 

71 

72# ---------------------------------------------------------------- 

73# UPDATE TEAM (TEACHER/ADMIN ONLY) 

74# ---------------------------------------------------------------- 

75@router.put("/{team_id}", response_model=TeamResponse) 

76def update_team( 

77 team_id: UUID, 

78 team_update: TeamUpdate, 

79 db: Session = Depends(get_db), 

80 current_user: User = Depends(require_staff) 

81): 

82 """ 

83 Update a team 

84 - **Requires**: TEACHER or ADMIN role 

85 """ 

86 team = crud_teams.update_team(db, team_id, team_update) 

87 if not team: 

88 raise HTTPException( 

89 status_code=status.HTTP_404_NOT_FOUND, 

90 detail="Team not found" 

91 ) 

92 return team 

93 

94 

95# ---------------------------------------------------------------- 

96# DELETE TEAM (TEACHER/ADMIN ONLY) 

97# ---------------------------------------------------------------- 

98@router.delete("/{team_id}", status_code=status.HTTP_204_NO_CONTENT) 

99def delete_team( 

100 team_id: UUID, 

101 db: Session = Depends(get_db), 

102 current_user: User = Depends(require_staff) 

103): 

104 """ 

105 Delete a team 

106 - **Requires**: TEACHER or ADMIN role 

107 """ 

108 success = crud_teams.delete_team(db, team_id) 

109 if not success: 

110 raise HTTPException( 

111 status_code=status.HTTP_404_NOT_FOUND, 

112 detail="Team not found" 

113 ) 

114 return None 

115 

116 

117# ---------------------------------------------------------------- 

118# ADD USER TO TEAM (TEACHER/ADMIN ONLY) 

119# ---------------------------------------------------------------- 

120@router.post("/{team_id}/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT) 

121def add_user_to_team( 

122 team_id: UUID, 

123 user_id: UUID, 

124 db: Session = Depends(get_db), 

125 current_user: User = Depends(require_staff) 

126): 

127 """ 

128 Add a user to a team 

129 - **Requires**: TEACHER or ADMIN role 

130 """ 

131 success = crud_teams.add_user_to_team(db, team_id, user_id) 

132 if not success: 

133 raise HTTPException( 

134 status_code=status.HTTP_400_BAD_REQUEST, 

135 detail="User already in team or team not found" 

136 ) 

137 return None 

138 

139 

140# ---------------------------------------------------------------- 

141# REMOVE USER FROM TEAM (TEACHER/ADMIN ONLY) 

142# ---------------------------------------------------------------- 

143@router.delete("/{team_id}/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT) 

144def remove_user_from_team( 

145 team_id: UUID, 

146 user_id: UUID, 

147 db: Session = Depends(get_db), 

148 current_user: User = Depends(require_staff) 

149): 

150 """ 

151 Remove a user from a team 

152 - **Requires**: TEACHER or ADMIN role 

153 """ 

154 success = crud_teams.remove_user_from_team(db, team_id, user_id) 

155 if not success: 

156 raise HTTPException( 

157 status_code=status.HTTP_404_NOT_FOUND, 

158 detail="User not in team or team not found" 

159 ) 

160 return None