From 7fe6b10788fb033ea0517041c5fafabb46d78178 Mon Sep 17 00:00:00 2001 From: fuomag9 <1580624+fuomag9@users.noreply.github.com> Date: Mon, 6 Apr 2026 00:58:22 +0200 Subject: [PATCH] Add E2E tests for untested pages and enforce role-based access control Allow non-admin users (user/viewer) to access / and /profile while blocking admin-only pages. The dashboard layout now uses requireUser() instead of requireAdmin(), and the sidebar filters nav items by role. Non-admin users see a minimal welcome page without stat cards. New test files (86 tests across 7 files): - dashboard, users, groups, api-docs, portal, link-account specs - role-access spec with full RBAC coverage for all 3 roles Co-Authored-By: Claude Opus 4.6 (1M context) --- app/(dashboard)/DashboardLayoutClient.tsx | 29 +- app/(dashboard)/layout.tsx | 4 +- app/(dashboard)/page.tsx | 18 +- tests/e2e/api-docs.spec.ts | 38 +++ tests/e2e/dashboard.spec.ts | 50 ++++ tests/e2e/groups.spec.ts | 109 +++++++ tests/e2e/link-account.spec.ts | 42 +++ tests/e2e/portal.spec.ts | 50 ++++ tests/e2e/role-access.spec.ts | 337 ++++++++++++++++++++++ tests/e2e/users.spec.ts | 80 +++++ 10 files changed, 740 insertions(+), 17 deletions(-) create mode 100644 tests/e2e/api-docs.spec.ts create mode 100644 tests/e2e/dashboard.spec.ts create mode 100644 tests/e2e/groups.spec.ts create mode 100644 tests/e2e/link-account.spec.ts create mode 100644 tests/e2e/portal.spec.ts create mode 100644 tests/e2e/role-access.spec.ts create mode 100644 tests/e2e/users.spec.ts diff --git a/app/(dashboard)/DashboardLayoutClient.tsx b/app/(dashboard)/DashboardLayoutClient.tsx index b521400f..2f8a0290 100644 --- a/app/(dashboard)/DashboardLayoutClient.tsx +++ b/app/(dashboard)/DashboardLayoutClient.tsx @@ -21,21 +21,22 @@ type User = { name?: string | null; email?: string | null; image?: string | null; + role?: string; }; const NAV_ITEMS = [ - { href: "/", label: "Overview", icon: LayoutDashboard }, - { href: "/proxy-hosts", label: "Proxy Hosts", icon: ArrowLeftRight }, - { href: "/l4-proxy-hosts", label: "L4 Proxy Hosts", icon: Cable }, - { href: "/access-lists", label: "Access Lists", icon: KeyRound }, - { href: "/groups", label: "Groups", icon: Users }, - { href: "/users", label: "Users", icon: UserCog }, - { href: "/certificates", label: "Certificates", icon: ShieldCheck }, - { href: "/waf", label: "WAF", icon: ShieldOff }, - { href: "/analytics", label: "Analytics", icon: BarChart2 }, - { href: "/audit-log", label: "Audit Log", icon: History }, - { href: "/api-docs", label: "API Docs", icon: FileJson2 }, - { href: "/settings", label: "Settings", icon: Settings }, + { href: "/", label: "Overview", icon: LayoutDashboard, adminOnly: false }, + { href: "/proxy-hosts", label: "Proxy Hosts", icon: ArrowLeftRight, adminOnly: true }, + { href: "/l4-proxy-hosts", label: "L4 Proxy Hosts", icon: Cable, adminOnly: true }, + { href: "/access-lists", label: "Access Lists", icon: KeyRound, adminOnly: true }, + { href: "/groups", label: "Groups", icon: Users, adminOnly: true }, + { href: "/users", label: "Users", icon: UserCog, adminOnly: true }, + { href: "/certificates", label: "Certificates", icon: ShieldCheck, adminOnly: true }, + { href: "/waf", label: "WAF", icon: ShieldOff, adminOnly: true }, + { href: "/analytics", label: "Analytics", icon: BarChart2, adminOnly: true }, + { href: "/audit-log", label: "Audit Log", icon: History, adminOnly: true }, + { href: "/api-docs", label: "API Docs", icon: FileJson2, adminOnly: true }, + { href: "/settings", label: "Settings", icon: Settings, adminOnly: true }, ] as const; function ThemeToggle() { @@ -59,6 +60,8 @@ function NavContent({ pathname, user, onNavigate }: { onNavigate?: () => void; }) { const router = useRouter(); + const isAdmin = user.role === "admin"; + const visibleItems = NAV_ITEMS.filter((item) => !item.adminOnly || isAdmin); return (
@@ -74,7 +77,7 @@ function NavContent({ pathname, user, onNavigate }: { {/* Nav items */}