fix(proxy): recognize team admins from members_with_roles in project create/update permission check

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
jesus 2026-09-08 15:34:28 +00:00
parent 21e3857845
commit 548d3d1b0a
2 changed files with 40 additions and 8 deletions

View file

@ -22,7 +22,7 @@ from litellm._uuid import uuid
from litellm.proxy._types import *
from litellm.proxy.auth.auth_checks import delete_cached_project_object
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.proxy.management_endpoints.common_utils import _set_object_metadata_field
from litellm.proxy.management_endpoints.common_utils import _is_user_team_admin, _set_object_metadata_field
from litellm.proxy.management_helpers.utils import (
management_endpoint_wrapper,
)
@ -105,14 +105,16 @@ async def _check_user_permission_for_project(
if not team_id or not user_api_key_dict.user_id:
return False
team = team_object
if team is None:
team = await _team_table(prisma_client).find_unique(where={"team_id": team_id})
team_row: Final = (
team_object
if team_object is not None
else await _team_table(prisma_client).find_unique(where={"team_id": team_id})
)
if team_row is None:
return False
if team and team.admins:
return user_api_key_dict.user_id in team.admins
return False
team: Final = LiteLLM_TeamTable.model_validate(team_row.model_dump())
return _is_user_team_admin(user_api_key_dict, team) or user_api_key_dict.user_id in (team.admins or [])
async def _validate_team_exists(

View file

@ -1368,3 +1368,33 @@ async def test_new_project_flag_on_access_group_model_returns_400(monkeypatch):
assert "prod-models" in str(exc_info.value)
assert "expand to multiple models at request time" in str(exc_info.value)
@pytest.mark.asyncio
async def test_check_user_permission_for_project_uses_members_with_roles():
"""Team admins added via /team/member_add live in members_with_roles, not the legacy admins list."""
from litellm.proxy._types import LiteLLM_TeamTable, Member
from litellm_enterprise.proxy.management_endpoints.project_endpoints import (
_check_user_permission_for_project,
)
team = LiteLLM_TeamTable(
team_id="team-1",
admins=[],
members_with_roles=[
Member(user_id="team-admin", role="admin"),
Member(user_id="plain-member", role="user"),
],
)
async def check(user_id: str) -> bool:
return await _check_user_permission_for_project(
user_api_key_dict=UserAPIKeyAuth(user_id=user_id, user_role=LitellmUserRoles.INTERNAL_USER),
team_id="team-1",
prisma_client=mock.MagicMock(),
team_object=team,
)
assert await check("team-admin") is True
assert await check("plain-member") is False
assert await check("stranger") is False