mirror of
https://github.com/BerriAI/litellm.git
synced 2025-04-26 03:04:13 +00:00
Show 'user_email' on key table on UI (#8887)
All checks were successful
Read Version from pyproject.toml / read-version (push) Successful in 35s
All checks were successful
Read Version from pyproject.toml / read-version (push) Successful in 35s
* refactor(internal_user_endpoints.py): refactor `/user/list` to accept 'user_ids' and use prisma for db calls enables bulk search from UI * fix(internal_user_endpoints.py): fix linting errors * fix(all_keys_table.tsx): show user email on create key table make it easier for admin to know which key is associated to which user * docs(internal_user_endpoints.py): improve docstring * fix: sync schema with main * fix(columns.tsx): display SSO ID on Internal User Table make it easy to identify what the SSO ID for a user is * fix(columns.tsx): add tooltip to header help user understand what SSO ID means * style: add more tooltips in the management flows make it easier to understand what you're seeing * style(all_keys_table.tsx): replace 'Not Set' with '-' reduces words on table * fix(internal_user_endpoints.py): fix user ids check * test: fix test * fix(internal_user_endpoints.py): maintain returning key count in `/user/list`
This commit is contained in:
parent
740bd7e9ce
commit
887c66c6b7
8 changed files with 199 additions and 67 deletions
|
@ -753,6 +753,9 @@ async def get_users(
|
|||
role: Optional[str] = fastapi.Query(
|
||||
default=None, description="Filter users by role"
|
||||
),
|
||||
user_ids: Optional[str] = fastapi.Query(
|
||||
default=None, description="Get list of users by user_ids"
|
||||
),
|
||||
page: int = fastapi.Query(default=1, ge=1, description="Page number"),
|
||||
page_size: int = fastapi.Query(
|
||||
default=25, ge=1, le=100, description="Number of items per page"
|
||||
|
@ -770,12 +773,19 @@ async def get_users(
|
|||
- proxy_admin_viewer
|
||||
- internal_user
|
||||
- internal_user_viewer
|
||||
user_ids: Optional[str]
|
||||
Get list of users by user_ids. Comma separated list of user_ids.
|
||||
page: int
|
||||
The page number to return
|
||||
page_size: int
|
||||
The number of items per page
|
||||
|
||||
Currently - admin-only endpoint.
|
||||
|
||||
Example curl:
|
||||
```
|
||||
http://0.0.0.0:4000/user/list?user_ids=default_user_id,693c1a4a-1cc0-4c7c-afe8-b5d2c8d52e17
|
||||
```
|
||||
"""
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
|
||||
|
@ -787,49 +797,69 @@ async def get_users(
|
|||
|
||||
# Calculate skip and take for pagination
|
||||
skip = (page - 1) * page_size
|
||||
take = page_size
|
||||
|
||||
# Prepare the query conditions
|
||||
where_clause = ""
|
||||
# Build where conditions based on provided parameters
|
||||
where_conditions: Dict[str, Any] = {}
|
||||
|
||||
if role:
|
||||
where_clause = f"""WHERE "user_role" = '{role}'"""
|
||||
where_conditions["user_role"] = {
|
||||
"contains": role,
|
||||
"mode": "insensitive", # Case-insensitive search
|
||||
}
|
||||
|
||||
# Single optimized SQL query that gets both users and total count
|
||||
sql_query = f"""
|
||||
WITH total_users AS (
|
||||
SELECT COUNT(*) AS total_number_internal_users
|
||||
FROM "LiteLLM_UserTable"
|
||||
),
|
||||
paginated_users AS (
|
||||
SELECT
|
||||
u.*,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM "LiteLLM_VerificationToken" vt
|
||||
WHERE vt."user_id" = u."user_id"
|
||||
) AS key_count
|
||||
FROM "LiteLLM_UserTable" u
|
||||
{where_clause}
|
||||
LIMIT {take} OFFSET {skip}
|
||||
if user_ids and isinstance(user_ids, str):
|
||||
user_id_list = [uid.strip() for uid in user_ids.split(",") if uid.strip()]
|
||||
where_conditions["user_id"] = {
|
||||
"in": user_id_list, # Now passing a list of strings as required by Prisma
|
||||
}
|
||||
|
||||
users: Optional[List[LiteLLM_UserTable]] = (
|
||||
await prisma_client.db.litellm_usertable.find_many(
|
||||
where=where_conditions,
|
||||
skip=skip,
|
||||
take=page_size,
|
||||
order={"created_at": "desc"},
|
||||
)
|
||||
)
|
||||
SELECT
|
||||
(SELECT total_number_internal_users FROM total_users),
|
||||
*
|
||||
FROM paginated_users;
|
||||
"""
|
||||
|
||||
# Execute the query
|
||||
results = await prisma_client.db.query_raw(sql_query)
|
||||
# Get total count from the first row (if results exist)
|
||||
total_count = 0
|
||||
if len(results) > 0:
|
||||
total_count = results[0].get("total_number_internal_users")
|
||||
# Get total count of user rows
|
||||
total_count = await prisma_client.db.litellm_usertable.count(
|
||||
where=where_conditions # type: ignore
|
||||
)
|
||||
|
||||
# Get key count for each user
|
||||
if users is not None:
|
||||
user_keys = await prisma_client.db.litellm_verificationtoken.group_by(
|
||||
by=["user_id"],
|
||||
count={"user_id": True},
|
||||
where={"user_id": {"in": [user.user_id for user in users]}},
|
||||
)
|
||||
user_key_counts = {
|
||||
item["user_id"]: item["_count"]["user_id"] for item in user_keys
|
||||
}
|
||||
else:
|
||||
user_key_counts = {}
|
||||
|
||||
verbose_proxy_logger.debug(f"Total count of users: {total_count}")
|
||||
|
||||
# Calculate total pages
|
||||
total_pages = -(-total_count // page_size) # Ceiling division
|
||||
|
||||
# Prepare response
|
||||
user_list: List[LiteLLM_UserTableWithKeyCount] = []
|
||||
if users is not None:
|
||||
for user in users:
|
||||
user_list.append(
|
||||
LiteLLM_UserTableWithKeyCount(
|
||||
**user.model_dump(), key_count=user_key_counts.get(user.user_id, 0)
|
||||
)
|
||||
) # Return full key object
|
||||
else:
|
||||
user_list = []
|
||||
|
||||
return {
|
||||
"users": results,
|
||||
"users": user_list,
|
||||
"total": total_count,
|
||||
"page": page,
|
||||
"page_size": page_size,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue