From 887e619f2e390353e2f433d7eff2fb15b2df5f90 Mon Sep 17 00:00:00 2001 From: Marcos Reifonas Date: Thu, 20 Aug 2026 14:07:15 +0000 Subject: [PATCH] feat(auth): enforce strict admin role checks for configuration and management routes --- src/config/routeConfig.ts | 4 +-- .../useUserPermissions/useUserPermissions.tsx | 17 +++++-------- src/hooks/useUserRole.tsx | 25 +++++++++++-------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/config/routeConfig.ts b/src/config/routeConfig.ts index 2cd29fa..8df0154 100644 --- a/src/config/routeConfig.ts +++ b/src/config/routeConfig.ts @@ -229,13 +229,13 @@ export const routeConfig: RouteDefinition[] = [ { path: '/configuracoes', component: () => import('@/pages/Configuracoes'), - guard: 'resource', + guard: 'admin', resourceKey: 'configuracoes-gerais', }, { path: '/admin/theme-customization', component: () => import('@/pages/ThemeCustomizationPage'), - guard: 'resource', + guard: 'admin', resourceKey: 'theme-customization', }, diff --git a/src/hooks/useUserPermissions/useUserPermissions.tsx b/src/hooks/useUserPermissions/useUserPermissions.tsx index 3ae4bc9..9b3d01f 100644 --- a/src/hooks/useUserPermissions/useUserPermissions.tsx +++ b/src/hooks/useUserPermissions/useUserPermissions.tsx @@ -2,7 +2,6 @@ import { useState, useEffect, useCallback } from 'react'; import { supabase } from '@/integrations/supabase/client'; import { useAuth } from '@/hooks/useAuth'; -import { useUserRole } from '@/hooks/useUserRole'; import { toast } from 'sonner'; import type { UserPermissions, @@ -14,7 +13,6 @@ import type { export function useUserPermissions() { const { user } = useAuth(); - const { isAdmin } = useUserRole(); const [userPermissions, setUserPermissions] = useState({ can_admin: false, can_create_update_delete: false, @@ -88,10 +86,9 @@ export function useUserPermissions() { loadUserPermissions(); }, [loadUserPermissions]); - // Check if user has access to a resource const hasAccess = useCallback((resourceKey?: string): boolean => { // Admin always has access - if (isAdmin) { + if (userPermissions.can_admin) { console.log(`✅ Admin access granted for resource: ${resourceKey || 'general'}`); return true; } @@ -124,7 +121,7 @@ export function useUserPermissions() { const hasFunctionalAccess = Object.values(userPermissions).some(Boolean); console.log(`🔄 Fallback functional access for ${resourceKey}: ${hasFunctionalAccess}`, userPermissions); return hasFunctionalAccess; - }, [isAdmin, userPermissions, resourcePermissions]); + }, [userPermissions, resourcePermissions]); // Check if user can access a specific route const canAccessRoute = useCallback((route: string): boolean => { @@ -148,10 +145,9 @@ export function useUserPermissions() { return hasAccess(); }, [hasAccess]); - // Get permission level for a specific resource const getResourcePermission = useCallback((resourceKey: ResourceKey): PermissionLevel => { // Admin always has full permissions - if (isAdmin) return 'can_admin'; + if (userPermissions.can_admin) return 'can_admin'; // Check specific resource permission if (resourcePermissions[resourceKey]) { @@ -165,7 +161,7 @@ export function useUserPermissions() { if (userPermissions.can_view_only) return 'can_view_only'; return 'no_access'; - }, [isAdmin, userPermissions, resourcePermissions]); + }, [userPermissions, resourcePermissions]); // Check if user can perform a specific action on a resource const canPerformActionByResource = useCallback(( @@ -190,9 +186,8 @@ export function useUserPermissions() { } }, [getResourcePermission]); - // Generic permission check for functional permissions const canPerformAction = useCallback((action: ActionType): boolean => { - if (isAdmin) return true; + if (userPermissions.can_admin) return true; switch (action) { case 'admin': @@ -208,7 +203,7 @@ export function useUserPermissions() { default: return false; } - }, [isAdmin, userPermissions]); + }, [userPermissions]); // Set specific resource permission const setResourcePermission = useCallback(async ( diff --git a/src/hooks/useUserRole.tsx b/src/hooks/useUserRole.tsx index 59e3564..cc3e5d5 100644 --- a/src/hooks/useUserRole.tsx +++ b/src/hooks/useUserRole.tsx @@ -1,14 +1,17 @@ // Hook que retorna role/permissões do usuário -// Migrado pra Logto: não depende mais do Supabase -// Qualquer usuário autenticado via Logto tem acesso Total +// Migrado pra consumir as permissões reais do banco via useUserPermissions import { useAuth } from '@/hooks/useAuth'; +import { useUserPermissions } from '@/hooks/useUserPermissions'; import type { UserRole, AppRole } from '@/hooks/useUserPermissions/types'; export type AccessLevel = 'Total' | 'Parcial' | 'Restrita'; export const useUserRole = () => { - const { user, loading } = useAuth(); + const { user, loading: authLoading } = useAuth(); + const { userPermissions, loading: permsLoading } = useUserPermissions(); + + const loading = authLoading || permsLoading; // Sem usuário = sem permissão if (!user) { @@ -18,18 +21,20 @@ export const useUserRole = () => { isGerencia: false, isDiretoria: false, role: 'user' as UserRole, - loading: false, + loading, error: null, }; } - // Com usuário autenticado via Logto = Total + // Com usuário autenticado + validações do json de privilégios do DB + const isAdminCheck = Boolean(userPermissions.can_admin); + return { - accessLevel: 'Total' as AccessLevel, - isAdmin: true, - isGerencia: true, - isDiretoria: true, - role: 'admin' as UserRole, + accessLevel: isAdminCheck ? 'Total' : 'Parcial' as AccessLevel, + isAdmin: isAdminCheck, + isGerencia: isAdminCheck, // fallback para componentes legados + isDiretoria: isAdminCheck, // fallback para componentes legados + role: (isAdminCheck ? 'admin' : 'user') as UserRole, loading, error: null, };