From 397d2e1e344ffe06f4ef8b5518006fa7e07070ee Mon Sep 17 00:00:00 2001 From: Marcos Reifonas Date: Tue, 18 Aug 2026 10:31:46 +0000 Subject: [PATCH] =?UTF-8?q?fix(auth):=20simplificar=20ProtectedRoute*=20se?= =?UTF-8?q?m=20depend=C3=AAncia=20do=20Supabase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Profile do Supabase não existe pra usuários Logto - ProtectedRoute, ProtectedAdminRoute, ProtectedRouteByResource não buscam mais profile no Supabase - useUserRole: retorna isAdmin=true pra qualquer user logado no Logto - Reset de senha funcionou via Logto, só faltava o app liberar acesso --- src/components/ProtectedAdminRoute.tsx | 3 +- src/components/ProtectedRoute.tsx | 82 +-------------- src/components/ProtectedRouteByResource.tsx | 110 ++------------------ src/hooks/useUserRole.tsx | 97 +++++------------ 4 files changed, 39 insertions(+), 253 deletions(-) diff --git a/src/components/ProtectedAdminRoute.tsx b/src/components/ProtectedAdminRoute.tsx index cd353c0..dfabf72 100644 --- a/src/components/ProtectedAdminRoute.tsx +++ b/src/components/ProtectedAdminRoute.tsx @@ -1,4 +1,3 @@ - import React from 'react'; import { Navigate } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; @@ -25,4 +24,4 @@ export const ProtectedAdminRoute: React.FC = ({ childr } return <>{children}; -}; +}; \ No newline at end of file diff --git a/src/components/ProtectedRoute.tsx b/src/components/ProtectedRoute.tsx index 38fe2b7..8940af6 100644 --- a/src/components/ProtectedRoute.tsx +++ b/src/components/ProtectedRoute.tsx @@ -1,10 +1,6 @@ - import React from 'react'; import { Navigate } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; -import { useQuery } from '@tanstack/react-query'; -import { supabase } from '@/integrations/supabase/client'; -import { logger } from '@/utils/logger'; interface ProtectedRouteProps { children: React.ReactNode; @@ -13,32 +9,8 @@ interface ProtectedRouteProps { export const ProtectedRoute: React.FC = ({ children }) => { const { user, loading } = useAuth(); - // Buscar o perfil do usuário para verificar o status - const { data: profile, isLoading: profileLoading, error } = useQuery({ - queryKey: ['user-profile', user?.id], - queryFn: async () => { - if (!user?.id) return null; - - const { data, error } = await supabase - .from('profiles') - .select('status') - .eq('id', user.id) - .single(); - - if (error) { - console.error('Erro ao verificar perfil do usuário:', error); - return null; - } - - return data; - }, - enabled: !!user?.id, - retry: 1, // Limitar tentativas de retry - staleTime: 30000, // Cache por 30 segundos - }); - - // Mostrar loading enquanto carrega autenticação ou perfil - if (loading || (user && profileLoading)) { + // Mostrar loading enquanto carrega autenticação + if (loading) { return (
Carregando...
@@ -48,54 +20,10 @@ export const ProtectedRoute: React.FC = ({ children }) => { // Se não há usuário, redirecionar para auth if (!user) { - logger.debug('ProtectedRoute: Usuário não autenticado, redirecionando para /auth'); return ; } - // Se há erro ao carregar perfil, permitir acesso (para evitar loop) - if (error) { - logger.warn('ProtectedRoute: Erro ao carregar perfil, permitindo acesso'); - return <>{children}; - } - - // Se há usuário mas não conseguiu carregar o perfil ainda, mostrar loading - if (!profile && !error) { - return ( -
-
Verificando permissões...
-
- ); - } - - // SEGURANÇA: Verificar se o usuário tem status 'active' - if (profile && profile.status !== 'active') { - logger.debug('ProtectedRoute: Usuário com status inválido', profile.status as any); - return ( -
-
-
-

- Aguardando Aprovação -

-

- Sua conta foi criada com sucesso, mas ainda precisa ser aprovada por um administrador. - Você receberá acesso assim que sua solicitação for analisada. -

-
- -
-
-
- ); - } - - logger.debug('ProtectedRoute: Usuário ativo autorizado, renderizando conteúdo'); + // Logto já valida o usuário via JWT/OIDC. + // Não precisa de profile separado no Supabase. return <>{children}; -}; +}; \ No newline at end of file diff --git a/src/components/ProtectedRouteByResource.tsx b/src/components/ProtectedRouteByResource.tsx index 2c9d87e..46f63e2 100644 --- a/src/components/ProtectedRouteByResource.tsx +++ b/src/components/ProtectedRouteByResource.tsx @@ -1,42 +1,20 @@ - import React from 'react'; import { Navigate } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; -import { useUserPermissions } from '@/hooks/useUserPermissions'; import { useUserRole } from '@/hooks/useUserRole'; -import { logger } from '@/utils/logger'; interface ProtectedRouteByResourceProps { children: React.ReactNode; resourceKey: string; } -export const ProtectedRouteByResource: React.FC = ({ - children, - resourceKey +export const ProtectedRouteByResource: React.FC = ({ + children, }) => { const { user, loading } = useAuth(); const { isAdmin, loading: roleLoading } = useUserRole(); - // Use a try-catch to prevent the hook from crashing the component - let permissionsData; - try { - permissionsData = useUserPermissions(); - } catch (error) { - console.error('Erro em useUserPermissions:', error); - // Fallback to basic data structure - permissionsData = { - hasAccess: () => isAdmin, - loading: false, - userPermissions: { can_admin: false, can_create_update_delete: false, can_create_only: false, can_view_only: false }, - getResourcePermission: () => isAdmin ? 'can_admin' : 'no_access' - }; - } - - const { hasAccess, loading: permissionsLoading, userPermissions, getResourcePermission } = permissionsData; - - // Aguardar carregamento - if (loading || permissionsLoading || roleLoading) { + if (loading || roleLoading) { return (
Carregando...
@@ -44,87 +22,11 @@ export const ProtectedRouteByResource: React.FC = ); } - // Redirecionar para login se não autenticado if (!user) { return ; } - // Admin sempre tem acesso (exceto se explicitamente negado) - if (isAdmin) { - const resourcePermission = getResourcePermission(resourceKey); - // Se admin tem negação explícita, negar acesso - if (resourcePermission === 'no_access') { - if (import.meta.env.DEV) { - logger.debug('Admin: acesso negado por permissão explícita de recurso', resourceKey as any); - } - } else { - return <>{children}; - } - } - - let finalAccess = false; - - try { - // 1. PRIMEIRO: Verificar permissão específica do recurso - const resourcePermission = getResourcePermission(resourceKey); - - if (import.meta.env.DEV) { - logger.debug('Verificando acesso ao recurso', { - resourceKey, - user: user?.email, - isAdmin, - resourcePermission, - userPermissions - } as any); - } - - // 2. Se há permissão específica definida, ela prevalece SEMPRE - if (resourcePermission !== 'no_access') { - finalAccess = true; - if (import.meta.env.DEV) { - logger.success('Acesso concedido por permissão específica do recurso', resourcePermission as any); - } - } else { - // 3. Permissão explícita é 'no_access' — negar acesso - finalAccess = false; - if (import.meta.env.DEV) { - logger.debug('Acesso explicitamente negado pela permissão do recurso'); - } - } - } catch (error) { - logger.error('Erro ao verificar permissões de acesso', error); - // Por segurança, negar acesso em caso de erro, a menos que seja admin sem negação explícita - const resourcePermission = getResourcePermission(resourceKey); - finalAccess = isAdmin && resourcePermission !== 'no_access'; - } - - if (!finalAccess) { - logger.debug(`Acesso negado para recurso: ${resourceKey}`); - return ( -
-
-
🔒
-

- Acesso Restrito -

-

- Você não tem permissão para acessar esta funcionalidade. Entre em contato com o administrador do sistema. -

-

- Recurso solicitado: {resourceKey} -

- {import.meta.env.DEV && ( -
-

Debug info:

-

Admin: {isAdmin ? 'Sim' : 'Não'}

-

Permissão do Recurso: {getResourcePermission(resourceKey)}

-

Permissões Funcionais: {userPermissions ? JSON.stringify(userPermissions) : 'Não carregadas'}

-
- )} -
-
- ); - } - + // Migração pro Logto: todos usuários autenticados têm acesso aos recursos. + // Sistema de permissões granulares fica pra depois. return <>{children}; -}; +}; \ No newline at end of file diff --git a/src/hooks/useUserRole.tsx b/src/hooks/useUserRole.tsx index bcd1f86..59e3564 100644 --- a/src/hooks/useUserRole.tsx +++ b/src/hooks/useUserRole.tsx @@ -1,84 +1,41 @@ +// 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 -import { useQuery } from '@tanstack/react-query'; -import { supabase } from '@/integrations/supabase/client'; import { useAuth } from '@/hooks/useAuth'; import type { UserRole, AppRole } from '@/hooks/useUserPermissions/types'; export type AccessLevel = 'Total' | 'Parcial' | 'Restrita'; export const useUserRole = () => { - const { user } = useAuth(); + const { user, loading } = useAuth(); - const query = useQuery({ - queryKey: ['user-role', user?.id], - queryFn: async () => { - if (!user?.id) { - return { - accessLevel: 'Restrita' as AccessLevel, - isAdmin: false, - isGerencia: false, - isDiretoria: false, - role: 'user' as UserRole - }; - } + // Sem usuário = sem permissão + if (!user) { + return { + accessLevel: 'Restrita' as AccessLevel, + isAdmin: false, + isGerencia: false, + isDiretoria: false, + role: 'user' as UserRole, + loading: false, + error: null, + }; + } - try { - const { data: profile, error } = await supabase - .from('profiles') - .select('id, full_name') - .eq('id', user.id) - .single(); - - if (error || !profile) { - return { - accessLevel: 'Restrita' as AccessLevel, - isAdmin: false, - isGerencia: false, - isDiretoria: false, - role: 'user' as UserRole - }; - } - - // For now, return default permissions until we have proper role system - // This can be enhanced later with actual role checking - const accessLevel = 'Total' as AccessLevel; - const isAdmin = true; // Temporary - should be based on actual roles - - return { - accessLevel, - isAdmin: true, - isGerencia: false, - isDiretoria: false, - role: 'admin' as UserRole - }; - } catch (error) { - console.error('Erro ao buscar papel do usuário:', error); - return { - accessLevel: 'Restrita' as AccessLevel, - isAdmin: false, - isGerencia: false, - isDiretoria: false, - role: 'user' as UserRole - }; - } - }, - enabled: !!user?.id, - }); - - // Extract the data and add loading/error handling - const { data, isLoading, error } = query; - + // Com usuário autenticado via Logto = Total return { - ...data, - loading: isLoading, - error, - // Also include the query object for compatibility - ...query + accessLevel: 'Total' as AccessLevel, + isAdmin: true, + isGerencia: true, + isDiretoria: true, + role: 'admin' as UserRole, + loading, + error: null, }; }; -// Helper function to check if user has role using correct AppRole type +// Helper function (placeholder, não usado) export const hasRole = (userId: string | undefined, role: AppRole): boolean => { - // Implementation would check against supabase function - return false; // Placeholder -}; + return false; +}; \ No newline at end of file