mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
Fixing Edit SSO Settings Modal
This commit is contained in:
parent
4cdcdc98e8
commit
2d464032c5
4 changed files with 83 additions and 84 deletions
|
|
@ -189,11 +189,16 @@ const BaseSSOSettingsForm: React.FC<BaseSSOSettingsFormProps> = ({ form, onFormS
|
|||
|
||||
<Form.Item
|
||||
noStyle
|
||||
shouldUpdate={(prevValues, currentValues) => prevValues.use_role_mappings !== currentValues.use_role_mappings}
|
||||
shouldUpdate={(prevValues, currentValues) =>
|
||||
prevValues.use_role_mappings !== currentValues.use_role_mappings ||
|
||||
prevValues.sso_provider !== currentValues.sso_provider
|
||||
}
|
||||
>
|
||||
{({ getFieldValue }) => {
|
||||
const useRoleMappings = getFieldValue("use_role_mappings");
|
||||
return useRoleMappings ? (
|
||||
const provider = getFieldValue("sso_provider");
|
||||
const supportsRoleMappings = provider === "okta" || provider === "generic";
|
||||
return useRoleMappings && supportsRoleMappings ? (
|
||||
<Form.Item
|
||||
label="Group Claim"
|
||||
name="group_claim"
|
||||
|
|
@ -207,11 +212,16 @@ const BaseSSOSettingsForm: React.FC<BaseSSOSettingsFormProps> = ({ form, onFormS
|
|||
|
||||
<Form.Item
|
||||
noStyle
|
||||
shouldUpdate={(prevValues, currentValues) => prevValues.use_role_mappings !== currentValues.use_role_mappings}
|
||||
shouldUpdate={(prevValues, currentValues) =>
|
||||
prevValues.use_role_mappings !== currentValues.use_role_mappings ||
|
||||
prevValues.sso_provider !== currentValues.sso_provider
|
||||
}
|
||||
>
|
||||
{({ getFieldValue }) => {
|
||||
const useRoleMappings = getFieldValue("use_role_mappings");
|
||||
return useRoleMappings ? (
|
||||
const provider = getFieldValue("sso_provider");
|
||||
const supportsRoleMappings = provider === "okta" || provider === "generic";
|
||||
return useRoleMappings && supportsRoleMappings ? (
|
||||
<>
|
||||
<Form.Item label="Default Role" name="default_role" initialValue="Internal User">
|
||||
<Select>
|
||||
|
|
|
|||
|
|
@ -1,79 +1,66 @@
|
|||
import { Modal } from "antd";
|
||||
import { useEditSSOSettings } from "@/app/(dashboard)/hooks/sso/useEditSSOSettings";
|
||||
import { useSSOSettings } from "@/app/(dashboard)/hooks/sso/useSSOSettings";
|
||||
import React from "react";
|
||||
import DeleteResourceModal from "../../../../common_components/DeleteResourceModal";
|
||||
import NotificationsManager from "../../../../molecules/notifications_manager";
|
||||
import { updateSSOSettings } from "../../../../networking";
|
||||
import { parseErrorMessage } from "../../../../shared/errorUtils";
|
||||
import { detectSSOProvider } from "../utils";
|
||||
|
||||
interface DeleteSSOSettingsModalProps {
|
||||
isVisible: boolean;
|
||||
onCancel: () => void;
|
||||
onSuccess: () => void;
|
||||
accessToken: string | null;
|
||||
}
|
||||
|
||||
const DeleteSSOSettingsModal: React.FC<DeleteSSOSettingsModalProps> = ({
|
||||
isVisible,
|
||||
onCancel,
|
||||
onSuccess,
|
||||
accessToken,
|
||||
}) => {
|
||||
const DeleteSSOSettingsModal: React.FC<DeleteSSOSettingsModalProps> = ({ isVisible, onCancel, onSuccess }) => {
|
||||
const { data: ssoSettings } = useSSOSettings();
|
||||
const { mutateAsync: editSSOSettings, isPending: isEditingSSOSettings } = useEditSSOSettings();
|
||||
|
||||
// Handle clearing SSO settings
|
||||
const handleClearSSO = async () => {
|
||||
if (!accessToken) {
|
||||
NotificationsManager.fromBackend("No access token available");
|
||||
return;
|
||||
}
|
||||
const clearSettings = {
|
||||
google_client_id: null,
|
||||
google_client_secret: null,
|
||||
microsoft_client_id: null,
|
||||
microsoft_client_secret: null,
|
||||
microsoft_tenant: null,
|
||||
generic_client_id: null,
|
||||
generic_client_secret: null,
|
||||
generic_authorization_endpoint: null,
|
||||
generic_token_endpoint: null,
|
||||
generic_userinfo_endpoint: null,
|
||||
proxy_base_url: null,
|
||||
user_email: null,
|
||||
sso_provider: null,
|
||||
role_mappings: null,
|
||||
};
|
||||
|
||||
try {
|
||||
// Clear all SSO settings
|
||||
const clearSettings = {
|
||||
google_client_id: null,
|
||||
google_client_secret: null,
|
||||
microsoft_client_id: null,
|
||||
microsoft_client_secret: null,
|
||||
microsoft_tenant: null,
|
||||
generic_client_id: null,
|
||||
generic_client_secret: null,
|
||||
generic_authorization_endpoint: null,
|
||||
generic_token_endpoint: null,
|
||||
generic_userinfo_endpoint: null,
|
||||
proxy_base_url: null,
|
||||
user_email: null,
|
||||
sso_provider: null,
|
||||
};
|
||||
|
||||
await updateSSOSettings(accessToken, clearSettings);
|
||||
|
||||
NotificationsManager.success("SSO settings cleared successfully");
|
||||
|
||||
// Close modal and trigger success callback
|
||||
onCancel();
|
||||
onSuccess();
|
||||
} catch (error) {
|
||||
console.error("Failed to clear SSO settings:", error);
|
||||
NotificationsManager.fromBackend("Failed to clear SSO settings: " + parseErrorMessage(error));
|
||||
}
|
||||
await editSSOSettings(clearSettings, {
|
||||
onSuccess: () => {
|
||||
NotificationsManager.success("SSO settings cleared successfully");
|
||||
onCancel();
|
||||
onSuccess();
|
||||
},
|
||||
onError: (error) => {
|
||||
NotificationsManager.fromBackend("Failed to clear SSO settings: " + parseErrorMessage(error));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
<DeleteResourceModal
|
||||
isOpen={isVisible}
|
||||
title="Confirm Clear SSO Settings"
|
||||
visible={isVisible}
|
||||
onOk={handleClearSSO}
|
||||
alertMessage="This action cannot be undone."
|
||||
message="Are you sure you want to clear all SSO settings? Users will no longer be able to login using SSO after this change."
|
||||
resourceInformationTitle="SSO Settings"
|
||||
resourceInformation={[
|
||||
{ label: "Provider", value: (ssoSettings?.values && detectSSOProvider(ssoSettings?.values)) || "Generic" },
|
||||
]}
|
||||
onCancel={onCancel}
|
||||
okText="Yes, Clear"
|
||||
cancelText="Cancel"
|
||||
okButtonProps={{
|
||||
danger: true,
|
||||
style: {
|
||||
backgroundColor: "#dc2626",
|
||||
borderColor: "#dc2626",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<p>Are you sure you want to clear all SSO settings? This action cannot be undone.</p>
|
||||
<p>Users will no longer be able to login using SSO after this change.</p>
|
||||
</Modal>
|
||||
onOk={handleClearSSO}
|
||||
confirmLoading={isEditingSSOSettings}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { useSSOSettings, type SSOSettingsValues } from "@/app/(dashboard)/hooks/sso/useSSOSettings";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import { Button, Card, Descriptions, Space, Typography } from "antd";
|
||||
import { Edit, Shield, Trash2 } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
|
@ -13,12 +12,12 @@ import RedactableField from "./RedactableField";
|
|||
import RoleMappings from "./RoleMappings";
|
||||
import SSOSettingsEmptyPlaceholder from "./SSOSettingsEmptyPlaceholder";
|
||||
import SSOSettingsLoadingSkeleton from "./SSOSettingsLoadingSkeleton";
|
||||
import { detectSSOProvider } from "./utils";
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
export default function SSOSettings() {
|
||||
const { data: ssoSettings, refetch, isLoading } = useSSOSettings();
|
||||
const { accessToken } = useAuthorized();
|
||||
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
|
||||
const [isAddModalVisible, setIsAddModalVisible] = useState(false);
|
||||
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
||||
|
|
@ -27,23 +26,6 @@ export default function SSOSettings() {
|
|||
Boolean(ssoSettings?.values.microsoft_client_id) ||
|
||||
Boolean(ssoSettings?.values.generic_client_id);
|
||||
|
||||
// Determine the SSO provider based on the configuration
|
||||
const detectSSOProvider = (values: SSOSettingsValues): string | null => {
|
||||
if (values.google_client_id) return "google";
|
||||
if (values.microsoft_client_id) return "microsoft";
|
||||
if (values.generic_client_id) {
|
||||
// Check if it looks like Okta/Auth0 based on endpoints
|
||||
if (
|
||||
values.generic_authorization_endpoint?.includes("okta") ||
|
||||
values.generic_authorization_endpoint?.includes("auth0")
|
||||
) {
|
||||
return "okta";
|
||||
}
|
||||
return "generic";
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const selectedProvider = ssoSettings?.values ? detectSSOProvider(ssoSettings.values) : null;
|
||||
const isRoleMappingsEnabled = Boolean(ssoSettings?.values.role_mappings);
|
||||
|
||||
|
|
@ -233,7 +215,6 @@ export default function SSOSettings() {
|
|||
isVisible={isDeleteModalVisible}
|
||||
onCancel={() => setIsDeleteModalVisible(false)}
|
||||
onSuccess={() => refetch()}
|
||||
accessToken={accessToken}
|
||||
/>
|
||||
|
||||
<AddSSOSettingsModal
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { SSOSettingsValues } from "@/app/(dashboard)/hooks/sso/useSSOSettings";
|
||||
|
||||
/**
|
||||
* Processes SSO settings form values and transforms them into the payload format expected by the API
|
||||
* Handles role mappings transformation and field extraction
|
||||
|
|
@ -11,6 +13,7 @@ export const processSSOSettingsPayload = (formValues: Record<string, any>): Reco
|
|||
default_role,
|
||||
group_claim,
|
||||
use_role_mappings,
|
||||
sso_provider,
|
||||
...rest
|
||||
} = formValues;
|
||||
|
||||
|
|
@ -18,8 +21,9 @@ export const processSSOSettingsPayload = (formValues: Record<string, any>): Reco
|
|||
...rest,
|
||||
};
|
||||
|
||||
// Add role mappings if use_role_mappings is checked
|
||||
if (use_role_mappings) {
|
||||
// Add role mappings only if use_role_mappings is checked AND provider supports role mappings
|
||||
const supportsRoleMappings = sso_provider === "okta" || sso_provider === "generic";
|
||||
if (use_role_mappings && supportsRoleMappings) {
|
||||
// Helper function to split comma-separated string into array
|
||||
const splitTeams = (teams: string | undefined): string[] => {
|
||||
if (!teams || teams.trim() === "") return [];
|
||||
|
|
@ -52,3 +56,20 @@ export const processSSOSettingsPayload = (formValues: Record<string, any>): Reco
|
|||
|
||||
return payload;
|
||||
};
|
||||
|
||||
// Determine the SSO provider based on the configuration
|
||||
export const detectSSOProvider = (values: SSOSettingsValues): string | null => {
|
||||
if (values.google_client_id) return "google";
|
||||
if (values.microsoft_client_id) return "microsoft";
|
||||
if (values.generic_client_id) {
|
||||
// Check if it looks like Okta/Auth0 based on endpoints
|
||||
if (
|
||||
values.generic_authorization_endpoint?.includes("okta") ||
|
||||
values.generic_authorization_endpoint?.includes("auth0")
|
||||
) {
|
||||
return "okta";
|
||||
}
|
||||
return "generic";
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue