diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index bb7d787d9d..074fa5719f 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -2458,6 +2458,7 @@ class UserAPIKeyAuth( user_max_budget: Optional[float] = None request_route: Optional[str] = None user: Optional[Any] = None # Expanded user object when expand=user is used + created_by_user: Optional[Any] = None # Expanded created_by user when expand=user is used end_user_object_permission: Optional[LiteLLM_ObjectPermissionTable] = None model_config = ConfigDict(arbitrary_types_allowed=True) diff --git a/litellm/proxy/management_endpoints/key_management_endpoints.py b/litellm/proxy/management_endpoints/key_management_endpoints.py index 654205252b..941b2c276d 100644 --- a/litellm/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/proxy/management_endpoints/key_management_endpoints.py @@ -4597,9 +4597,11 @@ async def _list_key_helper( user_map = {} if expand and "user" in expand: user_ids = [key.user_id for key in keys if key.user_id] - if user_ids: + created_by_ids = [key.created_by for key in keys if key.created_by] + all_ids = list(set(user_ids + created_by_ids)) # Remove duplicates + if all_ids: users = await prisma_client.db.litellm_usertable.find_many( - where={"user_id": {"in": list(set(user_ids))}} # Remove duplicates + where={"user_id": {"in": all_ids}} ) user_map = {user.user_id: user for user in users} @@ -4617,11 +4619,19 @@ async def _list_key_helper( key_dict = await attach_object_permission_to_dict(key_dict, prisma_client) # Include user information if expand includes "user" - if expand and "user" in expand and key.user_id and key.user_id in user_map: - try: - key_dict["user"] = user_map[key.user_id].model_dump() - except Exception: - key_dict["user"] = user_map[key.user_id].dict() + if expand and "user" in expand: + if key.user_id and key.user_id in user_map: + try: + key_dict["user"] = user_map[key.user_id].model_dump() + except Exception: + key_dict["user"] = user_map[key.user_id].dict() + if key.created_by and key.created_by in user_map: + created_by_user = user_map[key.created_by] + key_dict["created_by_user"] = { + "user_id": created_by_user.user_id, + "user_email": created_by_user.user_email, + "user_alias": created_by_user.user_alias, + } if return_full_object is True or (expand and "user" in expand): if use_deleted_table: diff --git a/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx b/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx index fd0cd4dd50..6091794170 100644 --- a/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx +++ b/ui/litellm-dashboard/src/components/VirtualKeysPage/VirtualKeysTable.tsx @@ -311,25 +311,40 @@ export function VirtualKeysTable({ teams, organizations, onSortChange, currentSo cell: (info) => { const userId = info.getValue() as string | null; if (!userId) return "-"; + const key = info.row.original; + const createdByUser = key.created_by_user; + const userAlias = createdByUser?.user_alias ?? null; + const userEmail = createdByUser?.user_email ?? null; const isDefaultAdmin = userId === "default_user_id"; + const displayValue = userAlias || userEmail || userId; const width = 160; const popoverContent = (