/** * Allow proxy admin to add other people to view global spend * Use this to avoid sharing master key with others */ import React, { useState, useEffect } from "react"; import { Typography } from "antd"; import { useRouter } from "next/navigation"; import { Button as Button2, Modal, Form, Input, Select as Select2, InputNumber, message, } from "antd"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { Select, SelectItem, Subtitle } from "@tremor/react"; import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow, Card, Icon, Button, Col, Text, Grid, Callout, Divider, } from "@tremor/react"; import { PencilAltIcon } from "@heroicons/react/outline"; import OnboardingModal from "./onboarding_link"; import { InvitationLink } from "./onboarding_link"; interface AdminPanelProps { searchParams: any; accessToken: string | null; setTeams: React.Dispatch>; showSSOBanner: boolean; premiumUser: boolean; } import { useBaseUrl } from "./constants"; import { userUpdateUserCall, Member, userGetAllUsersCall, User, setCallbacksCall, invitationCreateCall, getPossibleUserRoles, addAllowedIP, getAllowedIPs, deleteAllowedIP, } from "./networking"; const AdminPanel: React.FC = ({ searchParams, accessToken, showSSOBanner, premiumUser, }) => { const [form] = Form.useForm(); const [memberForm] = Form.useForm(); const { Title, Paragraph } = Typography; const [value, setValue] = useState(""); const [admins, setAdmins] = useState(null); const [invitationLinkData, setInvitationLinkData] = useState(null); const [isInvitationLinkModalVisible, setIsInvitationLinkModalVisible] = useState(false); const [isAddMemberModalVisible, setIsAddMemberModalVisible] = useState(false); const [isAddAdminModalVisible, setIsAddAdminModalVisible] = useState(false); const [isUpdateMemberModalVisible, setIsUpdateModalModalVisible] = useState(false); const [isAddSSOModalVisible, setIsAddSSOModalVisible] = useState(false); const [isInstructionsModalVisible, setIsInstructionsModalVisible] = useState(false); const [isAllowedIPModalVisible, setIsAllowedIPModalVisible] = useState(false); const [isAddIPModalVisible, setIsAddIPModalVisible] = useState(false); const [isDeleteIPModalVisible, setIsDeleteIPModalVisible] = useState(false); const [allowedIPs, setAllowedIPs] = useState([]); const [ipToDelete, setIPToDelete] = useState(null); const router = useRouter(); const [possibleUIRoles, setPossibleUIRoles] = useState >>(null); const isLocal = process.env.NODE_ENV === "development"; if (isLocal != true) { console.log = function() {}; } const baseUrl = useBaseUrl(); const all_ip_address_allowed = "All IP Addresses Allowed"; let nonSssoUrl = baseUrl; nonSssoUrl += "/fallback/login"; const handleShowAllowedIPs = async () => { try { if (premiumUser !== true) { message.error( "This feature is only available for premium users. Please upgrade your account." ) return } if (accessToken) { const data = await getAllowedIPs(accessToken); setAllowedIPs(data && data.length > 0 ? data : [all_ip_address_allowed]); } else { setAllowedIPs([all_ip_address_allowed]); } } catch (error) { console.error("Error fetching allowed IPs:", error); message.error(`Failed to fetch allowed IPs ${error}`); setAllowedIPs([all_ip_address_allowed]); } finally { if (premiumUser === true) { setIsAllowedIPModalVisible(true); } } }; const handleAddIP = async (values: { ip: string }) => { try { if (accessToken) { await addAllowedIP(accessToken, values.ip); // Fetch the updated list of IPs const updatedIPs = await getAllowedIPs(accessToken); setAllowedIPs(updatedIPs); message.success('IP address added successfully'); } } catch (error) { console.error("Error adding IP:", error); message.error(`Failed to add IP address ${error}`); } finally { setIsAddIPModalVisible(false); } }; const handleDeleteIP = async (ip: string) => { setIPToDelete(ip); setIsDeleteIPModalVisible(true); }; const confirmDeleteIP = async () => { if (ipToDelete && accessToken) { try { await deleteAllowedIP(accessToken, ipToDelete); // Fetch the updated list of IPs const updatedIPs = await getAllowedIPs(accessToken); setAllowedIPs(updatedIPs.length > 0 ? updatedIPs : [all_ip_address_allowed]); message.success('IP address deleted successfully'); } catch (error) { console.error("Error deleting IP:", error); message.error(`Failed to delete IP address ${error}`); } finally { setIsDeleteIPModalVisible(false); setIPToDelete(null); } } }; const handleAddSSOOk = () => { setIsAddSSOModalVisible(false); form.resetFields(); }; const handleAddSSOCancel = () => { setIsAddSSOModalVisible(false); form.resetFields(); }; const handleShowInstructions = (formValues: Record) => { handleAdminCreate(formValues); handleSSOUpdate(formValues); setIsAddSSOModalVisible(false); setIsInstructionsModalVisible(true); // Optionally, you can call handleSSOUpdate here with the formValues }; const handleInstructionsOk = () => { setIsInstructionsModalVisible(false); }; const handleInstructionsCancel = () => { setIsInstructionsModalVisible(false); }; const roles = ["proxy_admin", "proxy_admin_viewer"]; // useEffect(() => { // if (router) { // const { protocol, host } = window.location; // const baseUrl = `${protocol}//${host}`; // setBaseUrl(baseUrl); // } // }, [router]); useEffect(() => { // Fetch model info and set the default selected model const fetchProxyAdminInfo = async () => { if (accessToken != null) { const combinedList: any[] = []; const response = await userGetAllUsersCall( accessToken, "proxy_admin_viewer" ); console.log("proxy admin viewer response: ", response); const proxyViewers: User[] = response["users"]; console.log(`proxy viewers response: ${proxyViewers}`); proxyViewers.forEach((viewer: User) => { combinedList.push({ user_role: viewer.user_role, user_id: viewer.user_id, user_email: viewer.user_email, }); }); console.log(`proxy viewers: ${proxyViewers}`); const response2 = await userGetAllUsersCall( accessToken, "proxy_admin" ); const proxyAdmins: User[] = response2["users"]; proxyAdmins.forEach((admins: User) => { combinedList.push({ user_role: admins.user_role, user_id: admins.user_id, user_email: admins.user_email, }); }); console.log(`proxy admins: ${proxyAdmins}`); console.log(`combinedList: ${combinedList}`); setAdmins(combinedList); const availableUserRoles = await getPossibleUserRoles(accessToken); setPossibleUIRoles(availableUserRoles); } }; fetchProxyAdminInfo(); }, [accessToken]); const handleMemberUpdateOk = () => { setIsUpdateModalModalVisible(false); memberForm.resetFields(); form.resetFields(); }; const handleMemberOk = () => { setIsAddMemberModalVisible(false); memberForm.resetFields(); form.resetFields(); }; const handleAdminOk = () => { setIsAddAdminModalVisible(false); memberForm.resetFields(); form.resetFields(); }; const handleMemberCancel = () => { setIsAddMemberModalVisible(false); memberForm.resetFields(); form.resetFields(); }; const handleAdminCancel = () => { setIsAddAdminModalVisible(false); setIsInvitationLinkModalVisible(false); memberForm.resetFields(); form.resetFields(); }; const handleMemberUpdateCancel = () => { setIsUpdateModalModalVisible(false); memberForm.resetFields(); form.resetFields(); }; // Define the type for the handleMemberCreate function type HandleMemberCreate = (formValues: Record) => Promise; const addMemberForm = (handleMemberCreate: HandleMemberCreate) => { return (
<>
Add member
); }; const modifyMemberForm = ( handleMemberUpdate: HandleMemberCreate, currentRole: string, userID: string ) => { return (
<>
Update role
); }; const handleMemberUpdate = async (formValues: Record) => { try { if (accessToken != null && admins != null) { message.info("Making API Call"); const response: any = await userUpdateUserCall( accessToken, formValues, null ); console.log(`response for team create call: ${response}`); // Checking if the team exists in the list and updating or adding accordingly const foundIndex = admins.findIndex((user) => { console.log( `user.user_id=${user.user_id}; response.user_id=${response.user_id}` ); return user.user_id === response.user_id; }); console.log(`foundIndex: ${foundIndex}`); if (foundIndex == -1) { console.log(`updates admin with new user`); admins.push(response); // If new user is found, update it setAdmins(admins); // Set the new state } message.success("Refresh tab to see updated user role"); setIsUpdateModalModalVisible(false); } } catch (error) { console.error("Error creating the key:", error); } }; const handleMemberCreate = async (formValues: Record) => { try { if (accessToken != null && admins != null) { message.info("Making API Call"); const response: any = await userUpdateUserCall( accessToken, formValues, "proxy_admin_viewer" ); console.log(`response for team create call: ${response}`); // Checking if the team exists in the list and updating or adding accordingly // Give admin an invite link for inviting user to proxy const user_id = response.data?.user_id || response.user_id; invitationCreateCall(accessToken, user_id).then((data) => { setInvitationLinkData(data); setIsInvitationLinkModalVisible(true); }); const foundIndex = admins.findIndex((user) => { console.log( `user.user_id=${user.user_id}; response.user_id=${response.user_id}` ); return user.user_id === response.user_id; }); console.log(`foundIndex: ${foundIndex}`); if (foundIndex == -1) { console.log(`updates admin with new user`); admins.push(response); // If new user is found, update it setAdmins(admins); // Set the new state } form.resetFields(); setIsAddMemberModalVisible(false); } } catch (error) { console.error("Error creating the key:", error); } }; const handleAdminCreate = async (formValues: Record) => { try { if (accessToken != null && admins != null) { message.info("Making API Call"); const user_role: Member = { role: "user", user_email: formValues.user_email, user_id: formValues.user_id, }; const response: any = await userUpdateUserCall( accessToken, formValues, "proxy_admin" ); // Give admin an invite link for inviting user to proxy const user_id = response.data?.user_id || response.user_id; invitationCreateCall(accessToken, user_id).then((data) => { setInvitationLinkData(data); setIsInvitationLinkModalVisible(true); }); console.log(`response for team create call: ${response}`); // Checking if the team exists in the list and updating or adding accordingly const foundIndex = admins.findIndex((user) => { console.log( `user.user_id=${user.user_id}; response.user_id=${user_id}` ); return user.user_id === response.user_id; }); console.log(`foundIndex: ${foundIndex}`); if (foundIndex == -1) { console.log(`updates admin with new user`); admins.push(response); // If new user is found, update it setAdmins(admins); // Set the new state } form.resetFields(); setIsAddAdminModalVisible(false); } } catch (error) { console.error("Error creating the key:", error); } }; const handleSSOUpdate = async (formValues: Record) => { if (accessToken == null) { return; } let payload = { environment_variables: { PROXY_BASE_URL: formValues.proxy_base_url, GOOGLE_CLIENT_ID: formValues.google_client_id, GOOGLE_CLIENT_SECRET: formValues.google_client_secret, }, }; setCallbacksCall(accessToken, payload); }; console.log(`admins: ${admins?.length}`); return (
Admin Access {showSSOBanner && ( Requires SSO Setup )}
Proxy Admin: Can create keys, teams, users, add models, etc.{" "}
Proxy Admin Viewer: Can just view spend. They cannot create keys, teams or grant users access to new models.{" "}
Member Name Role {admins ? admins.map((member: any, index: number) => ( {member["user_email"] ? member["user_email"] : member["user_id"] ? member["user_id"] : null} {" "} {possibleUIRoles?.[member?.user_role]?.ui_label || "-"} setIsUpdateModalModalVisible(true)} /> {modifyMemberForm( handleMemberUpdate, member["user_role"], member["user_id"] )} )) : null}
{addMemberForm(handleAdminCreate)} {addMemberForm(handleMemberCreate)}
✨ Security Settings
<>
Save

Follow these steps to complete the SSO setup:

1. DO NOT Exit this TAB 2. Open a new tab, visit your proxy base url 3. Confirm your SSO is configured correctly and you can login on the new Tab 4. If Step 3 is successful, you can close this tab
Done
setIsAllowedIPModalVisible(false)} footer={[ , ]} > IP Address Action {allowedIPs.map((ip, index) => ( {ip} {ip !== all_ip_address_allowed && ( )} ))}
setIsAddIPModalVisible(false)} footer={null} >
Add IP Address
setIsDeleteIPModalVisible(false)} onOk={confirmDeleteIP} footer={[ , ]} >

Are you sure you want to delete the IP address: {ipToDelete}?

If you need to login without sso, you can access{" "} {nonSssoUrl}{" "}
); }; export default AdminPanel;