diff --git a/litellm/proxy/auth/litellm_license.py b/litellm/proxy/auth/litellm_license.py index c6c61ad4e..ffd9f5273 100644 --- a/litellm/proxy/auth/litellm_license.py +++ b/litellm/proxy/auth/litellm_license.py @@ -35,8 +35,11 @@ class LicenseCheck: return False def is_premium(self) -> bool: - if self.license_str is None: + try: + if self.license_str is None: + return False + elif self._verify(license_str=self.license_str): + return True + return False + except Exception as e: return False - elif self._verify(license_str=self.license_str): - return True - return False diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 8fa5e15bd..7af5b4c94 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -174,7 +174,6 @@ except Exception as e: _license_check = LicenseCheck() premium_user: bool = _license_check.is_premium() - ui_link = f"/ui/" ui_message = ( f"👉 [```LiteLLM Admin Panel on /ui```]({ui_link}). Create, Edit Keys with SSO" @@ -9587,6 +9586,7 @@ async def fallback_login(request: Request): "/login", include_in_schema=False ) # hidden since this is a helper for UI sso login async def login(request: Request): + global premium_user try: import multipart except ImportError: @@ -9662,6 +9662,7 @@ async def login(request: Request): "user_email": user_id, "user_role": "app_admin", # this is the path without sso - we can assume only admins will use this "login_method": "username_password", + "premium_user": premium_user, }, "secret", algorithm="HS256", @@ -9712,7 +9713,7 @@ def get_image(): @app.get("/sso/callback", tags=["experimental"]) async def auth_callback(request: Request): """Verify login""" - global general_settings, ui_access_mode + global general_settings, ui_access_mode, premium_user microsoft_client_id = os.getenv("MICROSOFT_CLIENT_ID", None) google_client_id = os.getenv("GOOGLE_CLIENT_ID", None) generic_client_id = os.getenv("GENERIC_CLIENT_ID", None) @@ -9992,6 +9993,7 @@ async def auth_callback(request: Request): "user_email": user_email, "user_role": user_role, "login_method": "sso", + "premium_user": premium_user, }, "secret", algorithm="HS256", diff --git a/ui/litellm-dashboard/src/app/page.tsx b/ui/litellm-dashboard/src/app/page.tsx index 7df196d9b..845e7d957 100644 --- a/ui/litellm-dashboard/src/app/page.tsx +++ b/ui/litellm-dashboard/src/app/page.tsx @@ -20,6 +20,7 @@ import { Typography } from "antd"; const CreateKeyPage = () => { const { Title, Paragraph } = Typography; const [userRole, setUserRole] = useState(""); + const [premiumUser, setPremiumUser] = useState(false); const [userEmail, setUserEmail] = useState(null); const [teams, setTeams] = useState(null); const [keys, setKeys] = useState(null); @@ -68,6 +69,10 @@ const CreateKeyPage = () => { } else { console.log(`User Email is not set ${decoded}`); } + + if (decoded.premium_user) { + setPremiumUser(decoded.premium_user); + } } } }, [token]); @@ -104,6 +109,7 @@ const CreateKeyPage = () => { userRole={userRole} userEmail={userEmail} showSSOBanner={showSSOBanner} + premiumUser={premiumUser} />
@@ -134,6 +140,7 @@ const CreateKeyPage = () => { accessToken={accessToken} modelData={modelData} setModelData={setModelData} + premiumUser={premiumUser} /> ) : page == "llm-playground" ? ( = ({ userID, modelData = { data: [] }, setModelData, + premiumUser, }) => { const [pendingRequests, setPendingRequests] = useState([]); const [form] = Form.useForm(); @@ -1609,6 +1611,7 @@ const ModelDashboard: React.FC = ({ streamingModelMetricsCategories } customTooltip={customTooltip} + premiumUser={premiumUser} /> diff --git a/ui/litellm-dashboard/src/components/model_metrics/time_to_first_token.tsx b/ui/litellm-dashboard/src/components/model_metrics/time_to_first_token.tsx index 10e400397..96e609b29 100644 --- a/ui/litellm-dashboard/src/components/model_metrics/time_to_first_token.tsx +++ b/ui/litellm-dashboard/src/components/model_metrics/time_to_first_token.tsx @@ -1,17 +1,19 @@ import React from "react"; -import { LineChart } from "@tremor/react"; +import { LineChart, Callout, Button } from "@tremor/react"; interface TimeToFirstTokenProps { modelMetrics: any[]; modelMetricsCategories: string[]; customTooltip: any; + premiumUser: boolean; } const TimeToFirstToken: React.FC = ({ modelMetrics, modelMetricsCategories, customTooltip, + premiumUser, }) => { - return ( + return premiumUser ? ( = ({ connectNulls={true} customTooltip={customTooltip} /> + ) : ( +
+ + Premium features are available for users with a specific license, please + contact LiteLLM to unlock this limitation. + + +
); }; diff --git a/ui/litellm-dashboard/src/components/navbar.tsx b/ui/litellm-dashboard/src/components/navbar.tsx index eddbb0b78..0247319af 100644 --- a/ui/litellm-dashboard/src/components/navbar.tsx +++ b/ui/litellm-dashboard/src/components/navbar.tsx @@ -3,8 +3,8 @@ import Link from "next/link"; import Image from "next/image"; import React, { useState } from "react"; -import type { MenuProps } from 'antd'; -import { Dropdown, Space } from 'antd'; +import type { MenuProps } from "antd"; +import { Dropdown, Space } from "antd"; import { useSearchParams } from "next/navigation"; import { Button, @@ -23,28 +23,32 @@ interface NavbarProps { userRole: string | null; userEmail: string | null; showSSOBanner: boolean; + premiumUser: boolean; } const Navbar: React.FC = ({ userID, userRole, userEmail, showSSOBanner, + premiumUser, }) => { console.log("User ID:", userID); console.log("userEmail:", userEmail); console.log("showSSOBanner:", showSSOBanner); + console.log("premiumUser:", premiumUser); // const userColors = require('./ui_colors.json') || {}; const isLocal = process.env.NODE_ENV === "development"; const imageUrl = isLocal ? "http://localhost:4000/get_image" : "/get_image"; - const items: MenuProps['items'] = [ + const items: MenuProps["items"] = [ { - key: '1', + key: "1", label: ( <>

Role: {userRole}

ID: {userID}

+

Premium User: {String(premiumUser)}

), }, @@ -68,41 +72,39 @@ const Navbar: React.FC = ({
- {showSSOBanner ? ( - -
- - Request hosted proxy - + + Request hosted proxy +
) : null} -
- - - {userEmail} - - + + {userEmail} +
-
- + ); };