mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-10 22:41:41 +00:00
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:
parent
21e3857845
commit
548d3d1b0a
2 changed files with 40 additions and 8 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue