Shyamnath's picture
Push UI dashboard and deployment files
c40c75a
import React, { useState, useEffect } from "react";
import {
Card,
Title,
Text,
Grid,
Col,
Button as TremorButton,
Callout,
TextInput,
Divider,
} from "@tremor/react";
import { message, Form } from "antd";
import { keyCreateCall } from "./networking";
import { CopyToClipboard } from "react-copy-to-clipboard";
import {
LinkOutlined,
KeyOutlined,
CopyOutlined,
ExclamationCircleOutlined,
PlusCircleOutlined
} from "@ant-design/icons";
interface SCIMConfigProps {
accessToken: string | null;
userID: string | null;
proxySettings: any;
}
const SCIMConfig: React.FC<SCIMConfigProps> = ({ accessToken, userID, proxySettings }) => {
const [form] = Form.useForm();
const [isCreatingToken, setIsCreatingToken] = useState(false);
const [tokenData, setTokenData] = useState<any>(null);
const [baseUrl, setBaseUrl] = useState("<your_proxy_base_url>");
useEffect(() => {
let url = "<your_proxy_base_url>";
if (proxySettings && proxySettings.PROXY_BASE_URL && proxySettings.PROXY_BASE_URL !== undefined) {
url = proxySettings.PROXY_BASE_URL;
} else if (typeof window !== 'undefined') {
// Use the current origin as the base URL if no proxy URL is set
url = window.location.origin;
}
setBaseUrl(url);
}, [proxySettings]);
const scimBaseUrl = `${baseUrl}/scim/v2`;
const handleCreateSCIMToken = async (values: any) => {
if (!accessToken || !userID) {
message.error("You need to be logged in to create a SCIM token");
return;
}
try {
setIsCreatingToken(true);
const formData = {
key_alias: values.key_alias || "SCIM Access Token",
team_id: null,
models: [],
allowed_routes: ["/scim/*"],
};
const response = await keyCreateCall(accessToken, userID, formData);
setTokenData(response);
message.success("SCIM token created successfully");
} catch (error) {
console.error("Error creating SCIM token:", error);
message.error("Failed to create SCIM token");
} finally {
setIsCreatingToken(false);
}
};
return (
<Grid numItems={1}>
<Card>
<div className="flex items-center mb-4">
<Title>SCIM Configuration</Title>
</div>
<Text className="text-gray-600">
System for Cross-domain Identity Management (SCIM) allows you to automatically provision and manage users and groups in LiteLLM.
</Text>
<Divider />
<div className="space-y-8">
{/* Step 1: SCIM URL */}
<div>
<div className="flex items-center mb-2">
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-blue-100 text-blue-700 mr-2">
1
</div>
<Title className="text-lg flex items-center">
<LinkOutlined className="h-5 w-5 mr-2" />
SCIM Tenant URL
</Title>
</div>
<Text className="text-gray-600 mb-3">
Use this URL in your identity provider SCIM integration settings.
</Text>
<div className="flex items-center">
<TextInput
value={scimBaseUrl}
disabled={true}
className="flex-grow"
/>
<CopyToClipboard
text={scimBaseUrl}
onCopy={() => message.success("URL copied to clipboard")}
>
<TremorButton variant="primary" className="ml-2 flex items-center">
<CopyOutlined className="h-4 w-4 mr-1" />
Copy
</TremorButton>
</CopyToClipboard>
</div>
</div>
{/* Step 2: SCIM Token */}
<div>
<div className="flex items-center mb-2">
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-blue-100 text-blue-700 mr-2">
2
</div>
<Title className="text-lg flex items-center">
<KeyOutlined className="h-5 w-5 mr-2" />
Authentication Token
</Title>
</div>
<Callout title="Using SCIM" color="blue" className="mb-4">
You need a SCIM token to authenticate with the SCIM API. Create one below and use it in your SCIM provider configuration.
</Callout>
{!tokenData ? (
<div className="bg-gray-50 p-4 rounded-lg">
<Form
form={form}
onFinish={handleCreateSCIMToken}
layout="vertical"
>
<Form.Item
name="key_alias"
label="Token Name"
rules={[{ required: true, message: "Please enter a name for your token" }]}
>
<TextInput placeholder="SCIM Access Token" />
</Form.Item>
<Form.Item>
<TremorButton
variant="primary"
type="submit"
loading={isCreatingToken}
className="flex items-center"
>
<KeyOutlined className="h-4 w-4 mr-1" />
Create SCIM Token
</TremorButton>
</Form.Item>
</Form>
</div>
) : (
<Card className="border border-yellow-300 bg-yellow-50">
<div className="flex items-center mb-2 text-yellow-800">
<ExclamationCircleOutlined className="h-5 w-5 mr-2" />
<Title className="text-lg text-yellow-800">Your SCIM Token</Title>
</div>
<Text className="text-yellow-800 mb-4 font-medium">
Make sure to copy this token now. You will not be able to see it again.
</Text>
<div className="flex items-center">
<TextInput
value={tokenData.token}
className="flex-grow mr-2 bg-white"
type="password"
disabled={true}
/>
<CopyToClipboard
text={tokenData.token}
onCopy={() => message.success("Token copied to clipboard")}
>
<TremorButton variant="primary" className="flex items-center">
<CopyOutlined className="h-4 w-4 mr-1" />
Copy
</TremorButton>
</CopyToClipboard>
</div>
<TremorButton
className="mt-4 flex items-center"
variant="secondary"
onClick={() => setTokenData(null)}
>
<PlusCircleOutlined className="h-4 w-4 mr-1" />
Create Another Token
</TremorButton>
</Card>
)}
</div>
</div>
</Card>
</Grid>
);
};
export default SCIMConfig;