mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-06 08:16:43 +00:00
fix(proxy): return persisted team memberships from /user/new so first CLI login gets the default team (#39545)
* fix(proxy): return persisted team memberships from /user/new new_user attached default teams after building its response from the pre-membership snapshot, so NewUserResponse.teams was always empty for users created with default_internal_user_params.teams. The CLI SSO flow reads that response on a user's first login and minted a teamless JWT, which skipped the default team's model allowlist. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(proxy): return team ids as a tuple to satisfy LIT001 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
4b1e24eae9
commit
c2265b0ef3
2 changed files with 19 additions and 0 deletions
|
|
@ -426,6 +426,11 @@ async def add_new_user_to_default_team(
|
|||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
|
||||
async def _fetch_user_team_ids(user_id: str, prisma_client: "PrismaClient") -> tuple[str, ...]:
|
||||
user_row: Final = await _user_table(prisma_client).find_unique(where={"user_id": user_id})
|
||||
return tuple(user_row.teams) if user_row is not None else ()
|
||||
|
||||
|
||||
@router.post(
|
||||
"/user/new",
|
||||
tags=["Internal User management"],
|
||||
|
|
@ -580,6 +585,11 @@ async def new_user(
|
|||
)
|
||||
|
||||
user_id: Final = cast(str | None, response.get("user_id", None))
|
||||
attached_team_ids: Final = (
|
||||
await _fetch_user_team_ids(user_id=user_id, prisma_client=prisma_client)
|
||||
if user_id is not None and (_team_id is not None or teams is not None)
|
||||
else None
|
||||
)
|
||||
|
||||
if organization_ids is not None and user_id is not None:
|
||||
await _add_user_to_organizations(
|
||||
|
|
@ -596,6 +606,8 @@ async def new_user(
|
|||
response_dict[key] = value
|
||||
|
||||
response_dict["key"] = response.get("token", "")
|
||||
if attached_team_ids is not None:
|
||||
response_dict["teams"] = list(attached_team_ids)
|
||||
|
||||
new_user_response: Final = NewUserResponse.model_validate(response_dict)
|
||||
|
||||
|
|
|
|||
|
|
@ -1449,6 +1449,11 @@ async def test_new_user_default_teams_flow(mocker):
|
|||
return 5 # Low user count, under limit
|
||||
|
||||
mock_prisma_client.db.litellm_usertable.count = mock_count
|
||||
persisted_user_row = mocker.MagicMock()
|
||||
persisted_user_row.teams = ["96fed65b-0182-4ff4-8429-2721cd7d42af"]
|
||||
mock_prisma_client.db.litellm_usertable.find_unique = mocker.AsyncMock(
|
||||
return_value=persisted_user_row
|
||||
)
|
||||
|
||||
# Mock duplicate checks to pass
|
||||
async def mock_check_duplicate_user_email(*args, **kwargs):
|
||||
|
|
@ -1477,6 +1482,7 @@ async def test_new_user_default_teams_flow(mocker):
|
|||
"token": "sk-test-token-123",
|
||||
"expires": None,
|
||||
"max_budget": 100,
|
||||
"teams": [],
|
||||
}
|
||||
|
||||
# Mock _add_user_to_team
|
||||
|
|
@ -1551,6 +1557,7 @@ async def test_new_user_default_teams_flow(mocker):
|
|||
# Verify response structure
|
||||
assert response.user_id == "test-user-123"
|
||||
assert response.key == "sk-test-token-123"
|
||||
assert response.teams == ["96fed65b-0182-4ff4-8429-2721cd7d42af"]
|
||||
|
||||
finally:
|
||||
# Restore original default params (always assign, never delattr — the attribute
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue