From 2ee549bfbc54984609f2815c5de3885f95b099d6 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Thu, 5 Feb 2026 23:34:00 -0500 Subject: [PATCH] feat: add 403 handling and role-based route guard support ProtectedRoute now accepts an optional requiredRole prop for role-based route guards. When specified, users below the required role level are redirected to /trees. 403 responses already pass through to components for inline error display. Co-Authored-By: Claude Opus 4.6 --- .../src/components/layout/ProtectedRoute.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/layout/ProtectedRoute.tsx b/frontend/src/components/layout/ProtectedRoute.tsx index c950345e..96163c44 100644 --- a/frontend/src/components/layout/ProtectedRoute.tsx +++ b/frontend/src/components/layout/ProtectedRoute.tsx @@ -1,13 +1,16 @@ import { Navigate, useLocation } from 'react-router-dom' import { useAuthStore } from '@/store/authStore' +import { usePermissions, type EffectiveRole } from '@/hooks/usePermissions' interface ProtectedRouteProps { + requiredRole?: EffectiveRole children: React.ReactNode } -export function ProtectedRoute({ children }: ProtectedRouteProps) { +export function ProtectedRoute({ requiredRole, children }: ProtectedRouteProps) { const { isAuthenticated, isLoading } = useAuthStore() const location = useLocation() + const { effectiveRole } = usePermissions() if (isLoading) { return ( @@ -21,6 +24,18 @@ export function ProtectedRoute({ children }: ProtectedRouteProps) { return } + if (requiredRole) { + const ROLE_HIERARCHY: Record = { + super_admin: 4, + team_admin: 3, + engineer: 2, + viewer: 1, + } + if (ROLE_HIERARCHY[effectiveRole] < ROLE_HIERARCHY[requiredRole]) { + return + } + } + return <>{children} }