diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index aacc9f525b..58f48412ca 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -432,6 +432,7 @@ class LiteLLMRoutes(enum.Enum): "/model/new", "/model/update", "/model/delete", + "/user/daily/activity", ] # routes that manage their own allowed/disallowed logic ## Org Admin Routes ## diff --git a/litellm/proxy/management_endpoints/internal_user_endpoints.py b/litellm/proxy/management_endpoints/internal_user_endpoints.py index 5ecd210d3e..fe5c1bacab 100644 --- a/litellm/proxy/management_endpoints/internal_user_endpoints.py +++ b/litellm/proxy/management_endpoints/internal_user_endpoints.py @@ -1480,6 +1480,14 @@ async def get_user_daily_activity( if api_key: where_conditions["api_key"] = api_key + if ( + user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN + and user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN_VIEW_ONLY + ): + where_conditions[ + "user_id" + ] = user_api_key_dict.user_id # only allow access to own data + # Get total count for pagination total_count = await prisma_client.db.litellm_dailyuserspend.count( where=where_conditions diff --git a/ui/litellm-dashboard/src/components/leftnav.tsx b/ui/litellm-dashboard/src/components/leftnav.tsx index 8879ba6eef..f58f60db33 100644 --- a/ui/litellm-dashboard/src/components/leftnav.tsx +++ b/ui/litellm-dashboard/src/components/leftnav.tsx @@ -23,7 +23,7 @@ import { LockOutlined, ToolOutlined, } from '@ant-design/icons'; -import { old_admin_roles, v2_admin_role_names, all_admin_roles, rolesAllowedToSeeUsage, rolesWithWriteAccess } from '../utils/roles'; +import { old_admin_roles, v2_admin_role_names, all_admin_roles, rolesAllowedToSeeUsage, rolesWithWriteAccess, internalUserRoles } from '../utils/roles'; const { Sider } = Layout; @@ -44,55 +44,55 @@ interface MenuItem { icon?: React.ReactNode; } -// Note: If a menu item does not have a role, it is visible to all roles. -const menuItems: MenuItem[] = [ - { key: "1", page: "api-keys", label: "Virtual Keys", icon: }, - { key: "3", page: "llm-playground", label: "Test Key", icon: , roles: rolesWithWriteAccess }, - { key: "2", page: "models", label: "Models", icon: , roles: rolesWithWriteAccess }, - { key: "4", page: "usage", label: "Usage", icon: }, - { key: "6", page: "teams", label: "Teams", icon: }, - { key: "17", page: "organizations", label: "Organizations", icon: , roles: all_admin_roles }, - { key: "5", page: "users", label: "Internal Users", icon: , roles: all_admin_roles }, - { key: "14", page: "api_ref", label: "API Reference", icon: }, - { key: "16", page: "model-hub", label: "Model Hub", icon: }, - { key: "15", page: "logs", label: "Logs", icon: }, - - - { - key: "experimental", - page: "experimental", - label: "Experimental", - icon: , - roles: all_admin_roles, - children: [ - { key: "9", page: "caching", label: "Caching", icon: , roles: all_admin_roles }, - { key: "10", page: "budgets", label: "Budgets", icon: , roles: all_admin_roles }, - { key: "11", page: "guardrails", label: "Guardrails", icon: , roles: all_admin_roles }, - { key: "12", page: "new_usage", label: "New Usage", icon: , roles: all_admin_roles }, - { key: "18", page: "mcp-tools", label: "MCP Tools", icon: , roles: all_admin_roles }, - ] - }, - { - key: "settings", - page: "settings", - label: "Settings", - icon: , - roles: all_admin_roles, - children: [ - { key: "11", page: "general-settings", label: "Router Settings", icon: , roles: all_admin_roles }, - { key: "12", page: "pass-through-settings", label: "Pass-Through", icon: , roles: all_admin_roles }, - { key: "8", page: "settings", label: "Logging & Alerts", icon: , roles: all_admin_roles }, - { key: "13", page: "admin-panel", label: "Admin Settings", icon: , roles: all_admin_roles }, - ] - } -]; const Sidebar: React.FC = ({ setPage, userRole, defaultSelectedKey, }) => { + // Note: If a menu item does not have a role, it is visible to all roles. + const menuItems: MenuItem[] = [ + { key: "1", page: "api-keys", label: "Virtual Keys", icon: }, + { key: "3", page: "llm-playground", label: "Test Key", icon: , roles: rolesWithWriteAccess }, + { key: "2", page: "models", label: "Models", icon: , roles: rolesWithWriteAccess }, + { key: "4", page: "usage", label: "Usage", icon: }, + { key: "6", page: "teams", label: "Teams", icon: }, + { key: "17", page: "organizations", label: "Organizations", icon: , roles: all_admin_roles }, + { key: "5", page: "users", label: "Internal Users", icon: , roles: all_admin_roles }, + { key: "14", page: "api_ref", label: "API Reference", icon: }, + { key: "16", page: "model-hub", label: "Model Hub", icon: }, + { key: "15", page: "logs", label: "Logs", icon: }, + + + + { + key: "experimental", + page: "experimental", + label: "Experimental", + icon: , + children: [ + { key: "9", page: "caching", label: "Caching", icon: , roles: all_admin_roles }, + { key: "10", page: "budgets", label: "Budgets", icon: , roles: all_admin_roles }, + { key: "11", page: "guardrails", label: "Guardrails", icon: , roles: all_admin_roles }, + { key: "12", page: "new_usage", label: "New Usage", icon: , roles: [...all_admin_roles, ...internalUserRoles] }, + { key: "18", page: "mcp-tools", label: "MCP Tools", icon: , roles: all_admin_roles }, + ] + }, + { + key: "settings", + page: "settings", + label: "Settings", + icon: , + roles: all_admin_roles, + children: [ + { key: "11", page: "general-settings", label: "Router Settings", icon: , roles: all_admin_roles }, + { key: "12", page: "pass-through-settings", label: "Pass-Through", icon: , roles: all_admin_roles }, + { key: "8", page: "settings", label: "Logging & Alerts", icon: , roles: all_admin_roles }, + { key: "13", page: "admin-panel", label: "Admin Settings", icon: , roles: all_admin_roles }, + ] + } + ]; // Find the menu item that matches the default page, including in submenus const findMenuItemKey = (page: string): string => { // Check top-level items @@ -111,9 +111,22 @@ const Sidebar: React.FC = ({ const selectedMenuKey = findMenuItemKey(defaultSelectedKey); - const filteredMenuItems = menuItems.filter(item => - !item.roles || item.roles.includes(userRole) - ); + const filteredMenuItems = menuItems.filter(item => { + // Check if parent item has roles and user has access + const hasParentAccess = !item.roles || item.roles.includes(userRole); + + if (!hasParentAccess) return false; + + // Filter children if they exist + if (item.children) { + item.children = item.children.filter(child => + !child.roles || child.roles.includes(userRole) + ); + } + + return true; + }); + return (