diff --git a/litellm/proxy/management/teams/endpoints.py b/litellm/proxy/management/teams/endpoints.py index 0b3e2f47c19..6688005ca99 100644 --- a/litellm/proxy/management/teams/endpoints.py +++ b/litellm/proxy/management/teams/endpoints.py @@ -10,6 +10,7 @@ from litellm.proxy.list_api.common import PROBLEM_TYPE_BASE, ManagementProblem from litellm.proxy.list_api.list_framework import handle_list from litellm.proxy.management.teams.authz import TeamAccess from litellm.proxy.management.teams.dependencies import get_roster_db, get_team_access, get_teams +from litellm.proxy.management.teams.exceptions import roster_problem from litellm.proxy.management.teams.repository import RawQuery, TeamMemberRows from litellm.proxy.management.teams.schemas import TeamMemberListItem from litellm.proxy.management.teams.service import ( @@ -26,30 +27,6 @@ from litellm.types.proxy.management_endpoints.management_v1 import ListResponse, router: Final = APIRouter(prefix=MANAGEMENT_V1_PREFIX) -def _roster_problem(refusal: TeamNotFound | RosterHidden) -> ManagementProblem: - match refusal: - case TeamNotFound(team_id=team_id): - return ManagementProblem( - ProblemDetail( - type=f"{PROBLEM_TYPE_BASE}team-not-found", - title="Team not found", - status=404, - detail=f"Team id={team_id} does not exist in db", - ) - ) - case RosterHidden(team_id=team_id): - return ManagementProblem( - ProblemDetail( - type=f"{PROBLEM_TYPE_BASE}forbidden", - title="Forbidden", - status=403, - detail=f"Not allowed to read the members of team={team_id}", - ) - ) - case _: - assert_never(refusal) - - @router.get( "/teams/{team_id}/members", tags=["team management"], @@ -97,7 +74,7 @@ async def list_team_members( caller=user_api_key_dict, ) case TeamNotFound() | RosterHidden(): - raise _roster_problem(lookup) + raise roster_problem(lookup) case _: assert_never(lookup) except ManagementProblem: diff --git a/litellm/proxy/management/teams/exceptions.py b/litellm/proxy/management/teams/exceptions.py new file mode 100644 index 00000000000..6c207e9726c --- /dev/null +++ b/litellm/proxy/management/teams/exceptions.py @@ -0,0 +1,29 @@ +from typing_extensions import assert_never + +from litellm.proxy.list_api.common import PROBLEM_TYPE_BASE, ManagementProblem +from litellm.proxy.management.teams.service import RosterHidden, TeamNotFound +from litellm.types.proxy.management_endpoints.management_v1 import ProblemDetail + + +def roster_problem(refusal: TeamNotFound | RosterHidden) -> ManagementProblem: + match refusal: + case TeamNotFound(team_id=team_id): + return ManagementProblem( + ProblemDetail( + type=f"{PROBLEM_TYPE_BASE}team-not-found", + title="Team not found", + status=404, + detail=f"Team id={team_id} does not exist in db", + ) + ) + case RosterHidden(team_id=team_id): + return ManagementProblem( + ProblemDetail( + type=f"{PROBLEM_TYPE_BASE}forbidden", + title="Forbidden", + status=403, + detail=f"Not allowed to read the members of team={team_id}", + ) + ) + case _: + assert_never(refusal) diff --git a/tests/unit/proxy/management/teams/test_exceptions.py b/tests/unit/proxy/management/teams/test_exceptions.py new file mode 100644 index 00000000000..245c0e40280 --- /dev/null +++ b/tests/unit/proxy/management/teams/test_exceptions.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +import pytest + +from litellm.proxy.list_api.common import PROBLEM_TYPE_BASE +from litellm.proxy.management.teams.exceptions import roster_problem +from litellm.proxy.management.teams.service import RosterHidden, TeamNotFound + + +@pytest.mark.parametrize( + ("refusal", "status", "problem_type"), + [ + pytest.param(TeamNotFound(team_id="team-404"), 404, f"{PROBLEM_TYPE_BASE}team-not-found", id="unknown-team"), + pytest.param(RosterHidden(team_id="team-403"), 403, f"{PROBLEM_TYPE_BASE}forbidden", id="hidden-roster"), + ], +) +def test_roster_problem_answers_each_refusal_with_its_own_status_and_names_the_team( + refusal: TeamNotFound | RosterHidden, status: int, problem_type: str +) -> None: + problem = roster_problem(refusal).problem + + assert (problem.status, problem.type) == (status, problem_type) + assert refusal.team_id in problem.detail