O login funcionou normalmente, mas a tela mostra pedidos, perfis ou notas de outros usuários misturados com os seus. Isso é um vazamento de dados, então é o bug de maior prioridade para corrigir. A causa quase sempre é a mesma: o servidor não filtra por "de quem é esta linha" e envia tudo para o navegador.
Does this match your symptom?
- Você está logado na sua própria conta, mas a lista contém dados de outras pessoas
- Trocar o
idnumérico na URL abre a página de detalhes de outra pessoa - No começo estava tudo bem, mas com mais usuários eles passaram a ver os dados uns dos outros
Why it happens
Três causas comuns para quem não é desenvolvedor:
- O RLS (Row Level Security) do Supabase está desativado — as tabelas do schema
publicpodem ser lidas por completo pela API, a menos que o RLS esteja ativado. - A consulta não tem a condição "só as minhas" — falta um
WHERE user_id = ..., ou as regras do Firebase ficaram em modo de teste (if true). - Filtrar só no React (lado do cliente) — todas as linhas, inclusive as de outras pessoas, já chegaram ao navegador e você apenas as escondeu na tela. Abra a aba Network do DevTools e estão todas lá. This is not security.
30-second diagnosis
No navegador: F12 → aba Network → clique na requisição que carrega a lista → Response.
Se a resposta JSON contiver linhas de outros usuários, o servidor está enviando elas, então você precisa corrigir no servidor (abaixo). Editar só o React não resolve.
Fix A — If you use Supabase
- Confirme que a tabela tem uma coluna
user_id(se faltar, adicione uma colunauuidque guarde o id deauth.users). - Rode isto no SQL Editor do painel (troque
todospelo nome da sua tabela):
-- 1) Turn RLS on
alter table todos enable row level security;
-- 2) Auto-fill the owner id on new rows (optional)
alter table todos alter column user_id set default auth.uid();
-- 3) Read only my rows
create policy "select own rows" on todos
for select to authenticated
using ( auth.uid() = user_id );
-- 4) Insert only as myself
create policy "insert own rows" on todos
for insert to authenticated
with check ( auth.uid() = user_id );
-- 5) Update only my rows
create policy "update own rows" on todos
for update to authenticated
using ( auth.uid() = user_id )
with check ( auth.uid() = user_id );
-- 6) Delete only my rows
create policy "delete own rows" on todos
for delete to authenticated
using ( auth.uid() = user_id );
- Salve, faça login com outra conta e teste de novo. Agora as linhas dos outros usuários somem completamente da resposta.
> Observação: depois que o RLS é ativado, nada fica visível até você adicionar políticas — isso é esperado. As políticas acima são o que restaura o "só as minhas".
Fix B — If you use Firebase (Firestore)
No console do Firebase, vá em Firestore Database → Rules, substitua a regra de modo de teste (allow read, write: if true;) pela regra de dono e clique em Publish:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /todos/{docId} {
allow read, update, delete: if request.auth != null
&& request.auth.uid == resource.data.uid;
allow create: if request.auth != null
&& request.auth.uid == request.resource.data.uid;
}
}
}
Você também precisa filtrar a consulta para os seus próprios dados. As regras do Firestore não são filtros: uma consulta ampla demais não é cortada silenciosamente — ela é rejeitada de vez.
import { collection, query, where, getDocs } from "firebase/firestore";
const q = query(
collection(db, "todos"),
where("uid", "==", auth.currentUser.uid) // only mine
);
const snap = await getDocs(q);
(Se os seus dados são indexados pelo id do usuário no caminho do documento, use match /users/{userId} com allow read, write: if request.auth.uid == userId;.)
Fix C — If you have your own backend (Express, etc.)
Force a consulta com o userId obtido da sessão/token de login. Never trust an id sent by the client — ele pode ser trocado.
// use the value from the session only
const rows = await db.query(
"select * from todos where user_id = $1",
[req.user.id] // NOT req.body / req.query id
);
The one line to remember
Um filtro no lado do cliente (React) serve para organizar a tela, não para segurança. Só o servidor (RLS, regras de segurança, WHERE) de fato estanca o vazamento.
