Ir para o conteúdo

Autenticação, Perfis, Permissões e RLS

Sistema: Drexies Agro | Responsável: Equipe de Dados Sonar

Esta página documenta as camadas de autenticação, autorização e segurança de acesso identificadas no código da Drexies Agro.

Escopo da análise

O comportamento descrito foi verificado no frontend, nas Edge Functions e nas migrations locais. As migrations não comprovam, isoladamente, quais políticas estão efetivamente implantadas no Supabase remoto.


Camadas de controle de acesso

Camada Finalidade Implementação identificada
Autenticação Confirmar a identidade e manter a sessão Supabase Auth e AuthContext
Autorização por perfil Diferenciar Administrador Global, Administrador e Usuário user_roles, contexto de autenticação e verificações administrativas
Autorização por tela Exibir menu e permitir rotas funcionais selecionadas telas_permitidas, AppSidebar e ProtectedRoute
Restrição territorial/organizacional Limitar concessionárias e filiais concessionarias_permitidas, filiais_permitidas e filtros do frontend
Segurança no banco Restringir leitura e escrita independentemente da interface Políticas RLS, funções e gatilhos PostgreSQL
Operações privilegiadas Administrar contas usando credencial de serviço Edge Function manage-users
flowchart LR
    C[Credenciais] --> A[Supabase Auth]
    A --> S[Sessão]
    S --> P[user_profiles e user_roles]
    P --> F[Permissões do frontend]
    P --> R[Políticas RLS]
    F --> T[Menu, rotas e telas]
    R --> D[Dados autorizados no PostgreSQL]

Interface não substitui RLS

Ocultar um item do menu, redirecionar uma rota ou filtrar dados no navegador melhora a experiência, mas não constitui, isoladamente, segurança do banco. A proteção efetiva das tabelas depende das políticas RLS e das verificações executadas no backend.


Supabase Auth e sessão

O login usa supabase.auth.signInWithPassword, com e-mail e senha. O cliente Supabase mantém a sessão no armazenamento configurado pelo projeto, persiste a sessão e renova o token automaticamente.

O AuthContext acompanha as mudanças de autenticação por onAuthStateChange. Na inicialização, também existe uma leitura de contingência por getSession caso o evento inicial não seja recebido dentro do tempo previsto no código.

Após identificar o usuário autenticado, a aplicação consulta:

  • user_profiles, usando auth_user_id;
  • user_roles, usando user_id.

Se nenhum papel for retornado, o contexto usa user como fallback técnico. O perfil e o papel carregados alimentam o menu, as rotas e as abas de Configurações.

Ponto a validar — papel ausente

Confirmar se é intencional utilizar user como fallback técnico para um usuário autenticado que possua perfil, mas não possua papel correspondente em user_roles. O código comprova o fallback, mas não determina qual deveria ser o comportamento funcional esperado nessa situação.

Usuários ativos e inativos

O campo ativo pertence a user_profiles. Quando o contexto carrega um perfil inativo, executa signOut e limpa o estado autenticado da aplicação.

Ponto a validar

Confirmar o comportamento esperado quando uma identidade autenticada não possui registro correspondente em user_profiles, pois a verificação de inatividade depende da existência do perfil.


Perfis de usuário

Perfil Identificador técnico Comportamento comprovado no frontend
Administrador Global global_admin É considerado administrador, possui acesso integral às telas do menu, à Gestão de usuários e à Auditoria
Administrador admin Possui acesso integral às telas do menu e à Gestão de usuários; não recebe acesso à aba Auditoria pelo frontend
Usuário user Tem o menu e as rotas funcionais condicionados por telas_permitidas e os dados de algumas telas filtrados pelo escopo organizacional

No contexto da aplicação:

isAdmin = role igual a admin ou global_admin
isGlobalAdmin = role igual a global_admin

Ponto a validar — matriz de perfis

Confirmar a matriz completa de leitura, criação, alteração, exclusão, aprovação e administração para cada perfil. O frontend e as migrations comprovam controles específicos, mas não formam, por si só, uma matriz funcional completa de todas as ações.


Proteção de rotas

ProtectedRoute

As seguintes rotas usam ProtectedRoute:

Rota Área
/dashboard Potencial de Mercado
/visao-macro Regiões
/visao-micro Produtores
/estrutura-comercial Custo Operacional
/configuracoes Configurações
/redefinir-senha Alteração de senha autenticada

O componente aplica o seguinte fluxo:

  1. enquanto a autenticação está carregando, apresenta um indicador de carregamento;
  2. sem usuário autenticado, redireciona para /login;
  3. administradores passam pela restrição de telas sem filtragem;
  4. para usuário comum com telas_permitidas preenchida, verifica a chave correspondente à rota;
  5. se a tela não estiver autorizada, redireciona para a primeira tela permitida reconhecida ou usa /dashboard como fallback.

As chaves mapeadas são dashboard, visao-macro, visao-micro e estrutura-comercial. Configurações e redefinição de senha não fazem parte desse mapa e, no código atual, exigem autenticação, mas não uma entrada em telas_permitidas.

AdminRoute

AdminRoute está efetivamente utilizado na rota /admin/users. Ele:

  • redireciona visitantes sem sessão para /login;
  • redireciona usuários não administradores para /dashboard;
  • permite administradores e administradores globais.

A rota autorizada redireciona para /configuracoes?tab=usuarios.


Permissões de tela e menu

O menu lateral possui quatro áreas funcionais controladas por chave:

Chave Item do menu
dashboard Potencial de Mercado
visao-macro Regiões
visao-micro Produtores
estrutura-comercial Custo Operacional

Para administradores, todos esses itens são exibidos. Para usuários comuns com uma lista preenchida, somente os itens presentes em telas_permitidas aparecem.

O item Configurações é exibido separadamente para usuários autenticados e não é filtrado por telas_permitidas. As funções disponíveis dentro da página são controladas por perfil.

Ponto a validar — lista vazia

No frontend analisado, telas_permitidas ausente ou vazia faz o usuário comum visualizar e acessar todas as quatro telas funcionais. Confirmar se esse comportamento permissivo representa a regra oficial ou se uma lista vazia deveria significar ausência de acesso.


Restrição por concessionária e filial

O perfil armazena:

  • concessionarias_permitidas;
  • filiais_permitidas.

Essas listas podem ser mantidas na Gestão de usuários. Para usuários não administradores, o código aplica os valores como filtros nos dados do Google Sheets usados em Potencial de Mercado e Produtores. Administradores ignoram esses filtros no frontend.

Quando uma lista territorial está preenchida, somente valores correspondentes permanecem nos dados filtrados. A tela de gestão também restringe a seleção de filiais às concessionárias escolhidas.

Limite do controle territorial

A restrição identificada é aplicada no frontend sobre os dados carregados da planilha. Não foi comprovada uma política RLS equivalente baseada em concessionária ou filial para todas as tabelas do Supabase. Portanto, ela não deve ser descrita como isolamento territorial integral no banco.

Ponto a validar

Confirmar o comportamento oficial de listas vazias de concessionárias e filiais e verificar em quais telas, consultas e tabelas o escopo organizacional precisa ser aplicado.


Configurações, usuários e auditoria

Área Acesso no frontend
Geral Qualquer usuário autenticado
Gestão de usuários Administrador ou Administrador Global
Auditoria Somente Administrador Global

Se uma aba não autorizada for solicitada por parâmetro da URL, a página seleciona ou retorna para a aba Geral.

Gestão de usuários

A interface de usuários consulta user_profiles e user_roles. Ela permite manter nome, situação, papel, concessionárias, filiais e telas permitidas, conforme os controles disponíveis para o administrador.

Criação, exclusão e redefinição administrativa de senha utilizam a Edge Function manage-users. Atualizações de perfil e papel também usam as tabelas correspondentes, sujeitas às políticas e aos gatilhos do banco.

Auditoria

Os registros são mantidos em drexies_audit_log. A aba de Auditoria é apresentada somente ao Administrador Global no frontend.

As migrations mais recentes analisadas substituem políticas anteriores e criam uma política de leitura para administradores globais. Usuários autenticados podem inserir os próprios eventos quando atendem à política definida.

Evolução das migrations

Como migrations sucessivas criam, removem e substituem políticas, a regra vigente deve ser avaliada pelo estado final aplicado ao ambiente, não por uma migration isolada.


Edge Function manage-users

A função exige o cabeçalho de autorização, valida o usuário chamador no Supabase Auth e consulta user_roles. Apenas admin ou global_admin podem prosseguir.

Ação Comportamento identificado
create Exige e-mail e senha, cria usuário confirmado e envia nome/papel como metadados
delete Exige user_id, impede autoexclusão e exclui pela API administrativa
reset_password Exige user_id e nova senha e atualiza a credencial administrativamente

A Edge Function usa a chave de service_role para operações privilegiadas. Essa chave não é exposta ao frontend pelo fluxo analisado.

Validação em mais de uma camada

A proteção visual da tela não é a única barreira desse fluxo: manage-users repete a verificação do usuário e do papel no backend antes de usar privilégios administrativos.


Contas protegidas

O código contém proteção especial para conta identificada por e-mail:

  • a interface impede que outros administradores editem a conta;
  • manage-users impede sua exclusão;
  • a função is_protected_user identifica a conta no banco;
  • gatilhos sobre user_roles mantêm o papel global_admin e impedem sua remoção;
  • gatilhos sobre user_profiles impedem exclusão e preservam campos de acesso quando outro usuário tenta alterá-los;
  • quando a própria conta altera o perfil, o campo ativo permanece verdadeiro.

Os privilégios de execução das funções de proteção são revogados de PUBLIC, anon e authenticated em migration posterior.

Ponto a validar — ambiente publicado

Confirmar quais contas protegidas e gatilhos estão realmente configurados no Supabase remoto. Evitar registrar identificadores pessoais adicionais nesta documentação.


Logout

Logout manual

O menu do usuário oferece a ação Sair, que chama supabase.auth.signOut. A mudança de autenticação limpa o usuário, a sessão, o perfil e o papel mantidos pelo contexto; rotas protegidas passam a redirecionar para o login.

Logout automático por inatividade

O AuthContext configura logout após duas horas sem interação. O temporizador é reiniciado por eventos de clique, teclado, entrada, alteração, rolagem, movimento do mouse, toque, ponteiro e foco. O processamento desses eventos possui limitação técnica de 15 segundos para evitar reinicializações excessivas.

Ao atingir o limite, a aplicação executa signOut e direciona o navegador para /login.


Estruturas relacionadas a acesso

Estrutura Papel na segurança
auth.users Identidade e credenciais gerenciadas pelo Supabase Auth
user_profiles Perfil, estado ativo e escopos de tela e território
user_roles Associação entre usuário e papel
drexies_audit_log Eventos de auditoria persistidos
get_my_profile() Retorna o perfil do usuário autenticado
has_role() Verifica papel sem depender de consulta direta do frontend
is_active_authenticated() Verifica se a identidade autenticada está ativa
is_protected_user() Identifica conta protegida
guard_user_profile_self_update() Restringe campos alteráveis pelo próprio usuário
guard_protected_user_role() Protege o papel da conta especial
guard_protected_user_profile() Protege o perfil da conta especial
handle_new_user() Cria perfil e papel quando uma identidade é criada

Padrões de RLS identificados nas migrations

As migrations locais habilitam RLS em tabelas do sistema e apresentam os seguintes padrões:

Padrão Exemplos identificados
Leitura pelo próprio usuário Perfil e papel associados ao auth.uid()
Administração por papel Leitura e manutenção de perfis e papéis por administradores
Usuário autenticado e ativo Leitura de diversas estruturas operacionais e resultados AgRisk por is_active_authenticated()
Dados do próprio usuário Potenciais personalizados, itens personalizados, comissões e itens de manejo do plano vinculados ao usuário
Acesso de serviço Escrita administrativa das Edge Functions com service_role, especialmente em integrações
Auditoria Inserção do próprio evento e leitura restrita conforme a política mais recente
Conta protegida Gatilhos que impedem exclusão ou alteração indevida de perfil e papel

Há migrations que revisam políticas antigas, inclusive substituindo regras amplas por regras baseadas em usuário ativo ou propriedade do registro.

Ponto a validar — matriz RLS

Elaborar e validar uma matriz final por tabela e operação (SELECT, INSERT, UPDATE e DELETE) a partir do banco remoto. O histórico local contém políticas criadas, removidas e substituídas ao longo do tempo.


Interface versus segurança no banco

Controle Camada Pode ser considerado segurança efetiva do banco?
Ocultar item do menu Frontend Não
Redirecionar rota Frontend Não
Filtrar concessionária ou filial no navegador Frontend Não, isoladamente
Validar papel dentro de Edge Function Backend Sim, para a operação protegida pela função
Aplicar RLS à tabela PostgreSQL Sim, conforme a política efetivamente implantada
Usar gatilho de proteção PostgreSQL Sim, conforme a função e o gatilho implantados

Uma operação sensível deve depender de controles do backend e do banco, mesmo quando a interface já esconde a ação.


Pontos a validar

  1. Confirmar se telas_permitidas vazia deve conceder todas as telas aos usuários comuns, como ocorre no frontend atual.
  2. Construir a matriz final de RLS por tabela e operação a partir das políticas efetivamente implantadas.
  3. Confirmar as contas protegidas configuradas no ambiente publicado.
  4. Comparar funções, gatilhos, enum de papéis e políticas locais com o Supabase remoto.
  5. Validar a matriz completa de ações permitidas para Administrador Global, Administrador e Usuário.
  6. Definir o comportamento para identidade autenticada sem user_profiles correspondente.
  7. Confirmar o significado de listas vazias de concessionárias e filiais e a abrangência territorial esperada.
  8. Verificar se o escopo territorial precisa ser imposto por RLS ou backend, além dos filtros atuais do frontend.
  9. Confirmar se é intencional utilizar user como fallback técnico para um usuário autenticado que possua perfil, mas não possua papel correspondente em user_roles.

Referências