feat: expose user_email in organization members response

Add user_email field to LiteLLM_OrganizationMembershipTable with a model_validator
that populates it from the nested user object, and update the /organization/info
Prisma query to select user_email from the related user record.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
yuneng-jiang
2026-02-20 21:14:29 -08:00
parent b7efca22a2
commit b61537cd0f
3 changed files with 42 additions and 1 deletions
+10
View File
@@ -2437,9 +2437,19 @@ class LiteLLM_OrganizationMembershipTable(LiteLLMPydanticObjectBase):
Any
] = None # You might want to replace 'Any' with a more specific type if available
litellm_budget_table: Optional[LiteLLM_BudgetTable] = None
user_email: Optional[str] = None
model_config = ConfigDict(protected_namespaces=())
@model_validator(mode="after")
def populate_user_email(self) -> "LiteLLM_OrganizationMembershipTable":
if self.user_email is None and self.user is not None:
if isinstance(self.user, dict):
self.user_email = self.user.get("user_email")
else:
self.user_email = getattr(self.user, "user_email", None)
return self
class LiteLLM_OrganizationTableUpdate(LiteLLM_BudgetTable):
"""Represents user-controllable params for a LiteLLM_OrganizationTable record"""
@@ -721,7 +721,13 @@ async def info_organization(organization_id: str):
where={"organization_id": organization_id},
include={
"litellm_budget_table": True,
"members": True,
"members": {
"include": {
"user": {
"select": {"user_email": True},
}
}
},
"teams": True,
"object_permission": True,
},
@@ -535,3 +535,28 @@ async def test_list_organization_filter_by_org_alias(monkeypatch):
"members": True,
"teams": True,
}
@pytest.mark.asyncio
async def test_organization_info_includes_user_email(monkeypatch):
"""
Test that GET /organization/info returns user_email in members list.
"""
from litellm.proxy._types import LiteLLM_OrganizationMembershipTable
from datetime import datetime
# Simulate a membership row with a nested user object that has user_email
raw_membership = {
"user_id": "user_abc",
"organization_id": "org_xyz",
"user_role": "org_admin",
"spend": 0.0,
"budget_id": None,
"created_at": datetime.utcnow(),
"updated_at": datetime.utcnow(),
"user": {"user_email": "alice@example.com"},
"litellm_budget_table": None,
}
membership = LiteLLM_OrganizationMembershipTable(**raw_membership)
assert membership.user_email == "alice@example.com"