From aca8ae7962b8e72de86c4d51399be81fa977cf7e Mon Sep 17 00:00:00 2001 From: = Date: Fri, 3 Oct 2025 18:57:50 -0700 Subject: [PATCH 1/9] fixes issue where empty premium fields were blocking key edit --- .../management_endpoints/common_utils.py | 2 +- .../key_management_endpoints.py | 2 +- litellm/proxy/utils.py | 9 +- .../guardrails/GuardrailSelector.tsx | 7 +- .../KeyInfoView.handleKeyUpdate.test.tsx | 338 ++++++++++++++++++ .../components/templates/key_edit_view.tsx | 10 +- .../components/templates/key_info_view.tsx | 6 + 7 files changed, 363 insertions(+), 11 deletions(-) create mode 100644 ui/litellm-dashboard/src/components/templates/KeyInfoView.handleKeyUpdate.test.tsx diff --git a/litellm/proxy/management_endpoints/common_utils.py b/litellm/proxy/management_endpoints/common_utils.py index 8f2ba37a9d..149ca6e2f6 100644 --- a/litellm/proxy/management_endpoints/common_utils.py +++ b/litellm/proxy/management_endpoints/common_utils.py @@ -43,7 +43,7 @@ def _set_object_metadata_field( value: Value to set for the field """ if field_name in LiteLLM_ManagementEndpoint_MetadataFields_Premium: - _premium_user_check() + _premium_user_check(field_name) object_data.metadata = object_data.metadata or {} object_data.metadata[field_name] = value diff --git a/litellm/proxy/management_endpoints/key_management_endpoints.py b/litellm/proxy/management_endpoints/key_management_endpoints.py index 007c0164be..7ce38c2d68 100644 --- a/litellm/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/proxy/management_endpoints/key_management_endpoints.py @@ -903,7 +903,7 @@ def prepare_metadata_fields( if k in LiteLLM_ManagementEndpoint_MetadataFields_Premium: from litellm.proxy.utils import _premium_user_check - _premium_user_check() + _premium_user_check(k) casted_metadata[k] = v except Exception as e: diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index 5b11c25b2b..8d2cb3c08f 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -3571,17 +3571,22 @@ def handle_exception_on_proxy(e: Exception) -> ProxyException: ) -def _premium_user_check(): +def _premium_user_check(feature:str=None): """ Raises an HTTPException if the user is not a premium user """ from litellm.proxy.proxy_server import premium_user + if feature: + detail_msg = f"This feature is only available for LiteLLM Enterprise users: {feature}. {CommonProxyErrors.not_premium_user.value}" + else: + detail_msg = f"This feature is only available for LiteLLM Enterprise users. {CommonProxyErrors.not_premium_user.value}" + if not premium_user: raise HTTPException( status_code=403, detail={ - "error": f"This feature is only available for LiteLLM Enterprise users. {CommonProxyErrors.not_premium_user.value}" + "error": detail_msg }, ) diff --git a/ui/litellm-dashboard/src/components/guardrails/GuardrailSelector.tsx b/ui/litellm-dashboard/src/components/guardrails/GuardrailSelector.tsx index b6f072cdfa..d111a1d8b3 100644 --- a/ui/litellm-dashboard/src/components/guardrails/GuardrailSelector.tsx +++ b/ui/litellm-dashboard/src/components/guardrails/GuardrailSelector.tsx @@ -9,13 +9,15 @@ interface GuardrailSelectorProps { value?: string[]; className?: string; accessToken: string; + disabled?: boolean; } const GuardrailSelector: React.FC = ({ onChange, value, className, - accessToken + accessToken, + disabled }) => { const [guardrails, setGuardrails] = useState([]); const [loading, setLoading] = useState(false); @@ -51,7 +53,8 @@ const GuardrailSelector: React.FC = ({