Skip to content
10 changes: 10 additions & 0 deletions frontend/src/app/token-router/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PermissionGuard } from '@/components/auth/permission-guard';
import TokenRouterPage from '@/components/pages/token-router';

export default function Page() {
return (
<PermissionGuard scope="routers:list">
<TokenRouterPage />
</PermissionGuard>
);
}
13 changes: 12 additions & 1 deletion frontend/src/components/auth/permission-guard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ import { useGlobal } from '@/contexts/global-context';
import { useMenuAuth } from '@/hooks/use-menu-auth';

interface PermissionGuardProps {
scope: 'monitor:view' | 'logs:list' | 'models:register';
scope:
| 'monitor:view'
| 'logs:list'
| 'models:register'
| 'routers:list'
| 'routers:read'
| 'routers:write'
| 'routers:operate';
children: React.ReactNode;
}

Expand Down Expand Up @@ -41,6 +48,10 @@ export function PermissionGuard({ scope, children }: PermissionGuardProps) {
'monitor:view': auth.hasMonitorView,
'logs:list': auth.hasLogsList,
'models:register': auth.canRegisterModel,
'routers:list': auth.hasRouterList,
'routers:read': auth.hasRouterRead,
'routers:write': auth.canWriteRouters,
'routers:operate': auth.canOperateRouters,
};

if (scopeMap[scope]) {
Expand Down
31 changes: 29 additions & 2 deletions frontend/src/components/layout/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
Globe,
BotIcon,
Rocket,
Route,
Monitor,
ScrollText,
ShieldCheck,
Expand Down Expand Up @@ -147,7 +148,15 @@ export function Sidebar() {
const [collapsed, setCollapsed] = useState(false);
const branding = getBrandingFromEnv();
const { clusterVersion, clusterAuth, clusterUIConfig } = useGlobal();
const { isAdmin, usersManagePage, canAccessKeysPage, hasLogsList, hasMonitorView, canRegisterModel } = useMenuAuth();
const {
isAdmin,
usersManagePage,
canAccessKeysPage,
hasLogsList,
hasMonitorView,
canRegisterModel,
canAccessRouterPage,
} = useMenuAuth();
const [token, setToken] = useState<string | undefined>();
const showLoginOut = useMemo(
() => Boolean(clusterAuth?.auth && token && token !== NO_AUTH),
Expand Down Expand Up @@ -197,6 +206,13 @@ export function Sidebar() {
Icon: Layers,
Extra: ChevronRight,
},
{
path: '/token-router',
name: t('menu.tokenRouter'),
Icon: Route,
Extra: ChevronRight,
show: !clusterUIConfig?.auth_advanced || canAccessRouterPage,
},
{
path: '/register-model',
name: t('menu.registerModel'),
Expand Down Expand Up @@ -307,7 +323,18 @@ export function Sidebar() {
items: group.items.filter(({ show = true }) => show),
}))
.filter(({ items }) => items.length > 0);
}, [clusterUIConfig, locale, t, usersManagePage, canAccessKeysPage, isAdmin, hasLogsList, hasMonitorView, canRegisterModel]);
}, [
clusterUIConfig,
locale,
t,
usersManagePage,
canAccessKeysPage,
isAdmin,
hasLogsList,
hasMonitorView,
canRegisterModel,
canAccessRouterPage,
]);

return (
<div
Expand Down
Loading
Loading