forked from phoenix/litellm-mirror
[ Proxy - User Management]: If user assigned to a team don't show Default Team (#5791)
* rename endpoint to ui_settings * ui allow DEFAULT_TEAM_DISABLED * fix logic * docs Set `default_team_disabled: true` on your litellm config.yaml
This commit is contained in:
parent
91e58d9049
commit
e6018a464f
8 changed files with 56 additions and 12 deletions
|
@ -239,6 +239,22 @@ If you don't see all your keys this could be due to a cached token. So just re-l
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### Disable `Default Team` on Admin UI
|
||||||
|
|
||||||
|
Use this if you want to hide the Default Team on the Admin UI
|
||||||
|
|
||||||
|
The following logic will apply
|
||||||
|
- If team assigned don't show `Default Team`
|
||||||
|
- If no team assigned then they should see `Default Team`
|
||||||
|
|
||||||
|
Set `default_team_disabled: true` on your litellm config.yaml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
general_settings:
|
||||||
|
master_key: sk-1234
|
||||||
|
default_team_disabled: true # OR you can set env var PROXY_DEFAULT_TEAM_DISABLED="true"
|
||||||
|
```
|
||||||
|
|
||||||
### Sign in with Username, Password when SSO is on
|
### Sign in with Username, Password when SSO is on
|
||||||
|
|
||||||
If you need to access the UI via username/password when SSO is on navigate to `/fallback/login`. This route will allow you to sign in with your username/password credentials.
|
If you need to access the UI via username/password when SSO is on navigate to `/fallback/login`. This route will allow you to sign in with your username/password credentials.
|
||||||
|
|
|
@ -289,7 +289,7 @@ class LiteLLMRoutes(enum.Enum):
|
||||||
"/key/delete",
|
"/key/delete",
|
||||||
"/global/spend/logs",
|
"/global/spend/logs",
|
||||||
"/global/predict/spend/logs",
|
"/global/predict/spend/logs",
|
||||||
"/sso/get/logout_url",
|
"/sso/get/ui_settings",
|
||||||
]
|
]
|
||||||
|
|
||||||
management_routes = [ # key
|
management_routes = [ # key
|
||||||
|
|
|
@ -1038,7 +1038,7 @@ async def user_api_key_auth(
|
||||||
# this token is only used for managing the ui
|
# this token is only used for managing the ui
|
||||||
allowed_routes = [
|
allowed_routes = [
|
||||||
"/sso",
|
"/sso",
|
||||||
"/sso/get/logout_url",
|
"/sso/get/ui_settings",
|
||||||
"/login",
|
"/login",
|
||||||
"/key/generate",
|
"/key/generate",
|
||||||
"/key/update",
|
"/key/update",
|
||||||
|
|
|
@ -21,6 +21,11 @@ model_list:
|
||||||
api_base: https://exampleopenaiendpoint-production.up.railway.app
|
api_base: https://exampleopenaiendpoint-production.up.railway.app
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
general_settings:
|
||||||
|
master_key: sk-1234
|
||||||
|
default_team_disabled: true
|
||||||
|
|
||||||
litellm_settings:
|
litellm_settings:
|
||||||
success_callback: ["prometheus"]
|
success_callback: ["prometheus"]
|
||||||
|
|
||||||
|
|
|
@ -659,6 +659,11 @@ def load_from_azure_key_vault(use_azure_key_vault: bool = False):
|
||||||
# Set your Azure Key Vault URI
|
# Set your Azure Key Vault URI
|
||||||
KVUri = os.getenv("AZURE_KEY_VAULT_URI", None)
|
KVUri = os.getenv("AZURE_KEY_VAULT_URI", None)
|
||||||
|
|
||||||
|
if KVUri is None:
|
||||||
|
raise Exception(
|
||||||
|
"Error when loading keys from Azure Key Vault: AZURE_KEY_VAULT_URI is not set."
|
||||||
|
)
|
||||||
|
|
||||||
credential = DefaultAzureCredential()
|
credential = DefaultAzureCredential()
|
||||||
|
|
||||||
# Create the SecretClient using the credential
|
# Create the SecretClient using the credential
|
||||||
|
@ -8342,16 +8347,25 @@ async def login(request: Request):
|
||||||
|
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/sso/get/logout_url",
|
"/sso/get/ui_settings",
|
||||||
tags=["experimental"],
|
tags=["experimental"],
|
||||||
include_in_schema=False,
|
include_in_schema=False,
|
||||||
dependencies=[Depends(user_api_key_auth)],
|
dependencies=[Depends(user_api_key_auth)],
|
||||||
)
|
)
|
||||||
async def get_logout_url(request: Request):
|
async def get_ui_settings(request: Request):
|
||||||
_proxy_base_url = os.getenv("PROXY_BASE_URL", None)
|
_proxy_base_url = os.getenv("PROXY_BASE_URL", None)
|
||||||
_logout_url = os.getenv("PROXY_LOGOUT_URL", None)
|
_logout_url = os.getenv("PROXY_LOGOUT_URL", None)
|
||||||
|
|
||||||
return {"PROXY_BASE_URL": _proxy_base_url, "PROXY_LOGOUT_URL": _logout_url}
|
default_team_disabled = general_settings.get("default_team_disabled", False)
|
||||||
|
if "PROXY_DEFAULT_TEAM_DISABLED" in os.environ:
|
||||||
|
if os.environ["PROXY_DEFAULT_TEAM_DISABLED"].lower() == "true":
|
||||||
|
default_team_disabled = True
|
||||||
|
|
||||||
|
return {
|
||||||
|
"PROXY_BASE_URL": _proxy_base_url,
|
||||||
|
"PROXY_LOGOUT_URL": _logout_url,
|
||||||
|
"DEFAULT_TEAM_DISABLED": default_team_disabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/onboarding/get_token", include_in_schema=False)
|
@app.get("/onboarding/get_token", include_in_schema=False)
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Select, SelectItem, Text, Title } from "@tremor/react";
|
import { Select, SelectItem, Text, Title } from "@tremor/react";
|
||||||
|
import { ProxySettings } from "./user_dashboard";
|
||||||
|
|
||||||
interface DashboardTeamProps {
|
interface DashboardTeamProps {
|
||||||
teams: Object[] | null;
|
teams: Object[] | null;
|
||||||
setSelectedTeam: React.Dispatch<React.SetStateAction<any | null>>;
|
setSelectedTeam: React.Dispatch<React.SetStateAction<any | null>>;
|
||||||
userRole: string | null;
|
userRole: string | null;
|
||||||
|
proxySettings: ProxySettings | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type TeamInterface = {
|
type TeamInterface = {
|
||||||
|
@ -17,6 +19,7 @@ const DashboardTeam: React.FC<DashboardTeamProps> = ({
|
||||||
teams,
|
teams,
|
||||||
setSelectedTeam,
|
setSelectedTeam,
|
||||||
userRole,
|
userRole,
|
||||||
|
proxySettings,
|
||||||
}) => {
|
}) => {
|
||||||
const defaultTeam: TeamInterface = {
|
const defaultTeam: TeamInterface = {
|
||||||
models: [],
|
models: [],
|
||||||
|
@ -31,6 +34,8 @@ const DashboardTeam: React.FC<DashboardTeamProps> = ({
|
||||||
if (userRole === "App User") {
|
if (userRole === "App User") {
|
||||||
// Non-Admin SSO users should only see their own team - they should not see "Default Team"
|
// Non-Admin SSO users should only see their own team - they should not see "Default Team"
|
||||||
updatedTeams = teams;
|
updatedTeams = teams;
|
||||||
|
} else if (proxySettings && proxySettings.DEFAULT_TEAM_DISABLED === true) {
|
||||||
|
updatedTeams = teams ? [...teams] : [defaultTeam];
|
||||||
} else {
|
} else {
|
||||||
updatedTeams = teams ? [...teams, defaultTeam] : [defaultTeam];
|
updatedTeams = teams ? [...teams, defaultTeam] : [defaultTeam];
|
||||||
}
|
}
|
||||||
|
|
|
@ -2752,8 +2752,8 @@ export const getProxyBaseUrlAndLogoutUrl = async (
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
let url = proxyBaseUrl
|
let url = proxyBaseUrl
|
||||||
? `${proxyBaseUrl}/sso/get/logout_url`
|
? `${proxyBaseUrl}/sso/get/ui_settings`
|
||||||
: `/sso/get/logout_url`;
|
: `sso/get/ui_settings`;
|
||||||
|
|
||||||
//message.info("Requesting model data");
|
//message.info("Requesting model data");
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
|
|
|
@ -28,6 +28,12 @@ type UserSpendData = {
|
||||||
max_budget?: number | null;
|
max_budget?: number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface ProxySettings {
|
||||||
|
PROXY_BASE_URL: string | null;
|
||||||
|
PROXY_LOGOUT_URL: string | null;
|
||||||
|
DEFAULT_TEAM_DISABLED: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
function getCookie(name: string) {
|
function getCookie(name: string) {
|
||||||
console.log("COOKIES", document.cookie)
|
console.log("COOKIES", document.cookie)
|
||||||
const cookieValue = document.cookie
|
const cookieValue = document.cookie
|
||||||
|
@ -46,8 +52,6 @@ interface UserDashboardProps {
|
||||||
setUserEmail: React.Dispatch<React.SetStateAction<string | null>>;
|
setUserEmail: React.Dispatch<React.SetStateAction<string | null>>;
|
||||||
setTeams: React.Dispatch<React.SetStateAction<Object[] | null>>;
|
setTeams: React.Dispatch<React.SetStateAction<Object[] | null>>;
|
||||||
setKeys: React.Dispatch<React.SetStateAction<Object[] | null>>;
|
setKeys: React.Dispatch<React.SetStateAction<Object[] | null>>;
|
||||||
setProxySettings: React.Dispatch<React.SetStateAction<any>>;
|
|
||||||
proxySettings: any;
|
|
||||||
premiumUser: boolean;
|
premiumUser: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +71,6 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
||||||
setUserEmail,
|
setUserEmail,
|
||||||
setTeams,
|
setTeams,
|
||||||
setKeys,
|
setKeys,
|
||||||
setProxySettings,
|
|
||||||
proxySettings,
|
|
||||||
premiumUser,
|
premiumUser,
|
||||||
}) => {
|
}) => {
|
||||||
const [userSpendData, setUserSpendData] = useState<UserSpendData | null>(
|
const [userSpendData, setUserSpendData] = useState<UserSpendData | null>(
|
||||||
|
@ -87,6 +89,7 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
||||||
const [accessToken, setAccessToken] = useState<string | null>(null);
|
const [accessToken, setAccessToken] = useState<string | null>(null);
|
||||||
const [teamSpend, setTeamSpend] = useState<number | null>(null);
|
const [teamSpend, setTeamSpend] = useState<number | null>(null);
|
||||||
const [userModels, setUserModels] = useState<string[]>([]);
|
const [userModels, setUserModels] = useState<string[]>([]);
|
||||||
|
const [proxySettings, setProxySettings] = useState<ProxySettings | null>(null);
|
||||||
const defaultTeam: TeamInterface = {
|
const defaultTeam: TeamInterface = {
|
||||||
models: [],
|
models: [],
|
||||||
team_alias: "Default Team",
|
team_alias: "Default Team",
|
||||||
|
@ -166,7 +169,7 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
||||||
} else {
|
} else {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const proxy_settings = await getProxyBaseUrlAndLogoutUrl(accessToken);
|
const proxy_settings: ProxySettings = await getProxyBaseUrlAndLogoutUrl(accessToken);
|
||||||
setProxySettings(proxy_settings);
|
setProxySettings(proxy_settings);
|
||||||
|
|
||||||
const response = await userInfoCall(
|
const response = await userInfoCall(
|
||||||
|
@ -347,6 +350,7 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
||||||
teams={teams}
|
teams={teams}
|
||||||
setSelectedTeam={setSelectedTeam}
|
setSelectedTeam={setSelectedTeam}
|
||||||
userRole={userRole}
|
userRole={userRole}
|
||||||
|
proxySettings={proxySettings}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue