feat(ui): make LiteAdmin enterprise-only (#44399)

This commit is contained in:
tin-berri 2026-10-03 11:07:54 -07:00 • committed by GitHub
parent f0abe1bea1
commit 4732647de2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 61 additions and 5 deletions

View file

@ -204,7 +204,7 @@ const UserDropdown: React.FC<UserDropdownProps> = ({ onLogout, variant = "navbar
aria-label="Toggle hide bouncing icon"
/>
</div>
{canUseLiteAdmin && (
{premiumUser === true && canUseLiteAdmin && (
<div className="flex w-full items-center justify-between gap-2">
<span className="text-muted-foreground">Hide LiteAdmin</span>
<Switch

View file

@ -248,7 +248,7 @@ const SidebarAccountMenu: React.FC<SidebarAccountMenuProps> = ({ onLogout, colla
/>
</div>
))}
{canUseLiteAdmin && (
{premiumUser === true && canUseLiteAdmin && (
<div className="flex h-[38px] items-center justify-between gap-3 px-3">
<span className="text-[13px] text-foreground">Hide LiteAdmin</span>
<Switch

View file

@ -63,13 +63,18 @@ function deferred<T>() {
return { promise, resolve };
}
function session(role = "proxy_admin", user = "first-admin") {
function session(
role = "proxy_admin",
user = "first-admin",
license: { premium_user?: boolean | null | string } = { premium_user: true },
) {
const encode = (value: object) =>
btoa(JSON.stringify(value)).replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_");
const claims = {
key: `sk-session-${user}`,
user_id: user,
user_role: role,
...license,
auth_header_name: "X-Gateway-Session",
exp: Date.now() / 1000 + 3600,
};
@ -197,7 +202,7 @@ describe("LiteAdmin in the gateway", () => {
it.each([
["sidebar", SidebarAccountMenu],
["navbar", UserDropdown],
] as const)("persists Hide LiteAdmin from the %s account menu", async (_name, Menu) => {
] as const)("persists Hide LiteAdmin only for enterprise users in the %s account menu", async (_name, Menu) => {
gateway([]);
const user = userEvent.setup();
const view = renderWidget(Menu);
@ -219,6 +224,57 @@ describe("LiteAdmin in the gateway", () => {
expect(savedToggle).toBeChecked();
await user.click(savedToggle);
expect(await screen.findByRole("button", { name: "LiteAdmin" })).toBeInTheDocument();
for (const premiumUser of [false, null, undefined, "true"]) {
session("proxy_admin", "first-admin", { premium_user: premiumUser });
restored.refresh();
expect(screen.getByRole("switch", { name: "Toggle hide all prompts" })).toBeInTheDocument();
expect(screen.queryByRole("switch", { name: "Toggle hide LiteAdmin" })).not.toBeInTheDocument();
}
});
it.each([false, null, undefined, "true"])(
"does not expose LiteAdmin when premium_user is %s",
async (premiumUser) => {
session("proxy_admin", "first-admin", { premium_user: premiumUser });
const requests = gateway([]);
const { client } = renderWidget();
await screen.findByText("Session ready");
await waitFor(() => expect(client.isFetching()).toBe(0));
expect(screen.queryByRole("button", { name: "LiteAdmin" })).not.toBeInTheDocument();
for (const modifiers of [{ metaKey: true }, { ctrlKey: true }]) {
expect(fireEvent.keyDown(document, { key: "j", ...modifiers })).toBe(true);
expect(screen.queryByRole("complementary", { name: "LiteAdmin" })).not.toBeInTheDocument();
}
expect(requests.every((request) => request.url.endsWith("/litellm-ui-config"))).toBe(true);
},
);
it("removes an open panel and shortcuts when enterprise access is lost and restores it closed", async () => {
const requests = gateway([]);
const view = renderWidget();
await openWidget();
fireEvent.change(screen.getByPlaceholderText("Ask LiteAdmin…"), { target: { value: "Previous enterprise draft" } });
await waitFor(() => expect(view.client.isFetching()).toBe(0));
const requestCount = requests.length;
session("proxy_admin", "first-admin", { premium_user: false });
view.refresh();
expect(screen.queryByRole("button", { name: "LiteAdmin" })).not.toBeInTheDocument();
expect(screen.queryByRole("complementary", { name: "LiteAdmin" })).not.toBeInTheDocument();
for (const modifiers of [{ metaKey: true }, { ctrlKey: true }]) {
expect(fireEvent.keyDown(document, { key: "j", ...modifiers })).toBe(true);
expect(screen.queryByRole("complementary", { name: "LiteAdmin" })).not.toBeInTheDocument();
}
expect(requests).toHaveLength(requestCount);
session();
view.refresh();
expect(await screen.findByRole("button", { name: "LiteAdmin" })).toHaveAttribute("aria-expanded", "false");
expect(screen.queryByRole("complementary", { name: "LiteAdmin" })).not.toBeInTheDocument();
fireEvent.keyDown(document, { key: "j", ctrlKey: true });
expect(await screen.findByRole("complementary", { name: "LiteAdmin" })).toBeInTheDocument();
expect(screen.getByPlaceholderText("Ask LiteAdmin…")).toHaveValue("");
});
it("isolates Hide LiteAdmin by admin and gateway and reacts to another tab clearing it", async () => {

View file

@ -30,7 +30,7 @@ const LiteAdminContext = createContext<LiteAdminState | null>(null);
function useLiteAdminSession() {
const auth = useAuthorized();
const [disabled] = useDisableLiteAdmin(auth.userId);
const sessionReady = !auth.isLoading && auth.isAuthorized;
const sessionReady = !auth.isLoading && auth.isAuthorized && auth.premiumUser === true;
const writableAdmin = !auth.isViewOnly && isProxyAdminRole(auth.userRole);
const allowed = sessionReady && writableAdmin && !disabled;
if (!allowed || !auth.token || !auth.accessToken) return null;