Iniciaste sesión sin problemas, pero la pantalla muestra pedidos, perfiles o notas de otros usuarios mezclados con los tuyos. Esto es una fuga de datos, así que es el error más prioritario que hay que arreglar. La causa casi siempre es la misma: el servidor no filtra por "de quién es esta fila" y envía todo al navegador.

Does this match your symptom?

  • Tienes la sesión iniciada en tu propia cuenta, pero la lista contiene datos de otras personas
  • Al cambiar el id numérico en la URL se abre la página de detalle de otra persona
  • Al principio iba bien, pero al tener más usuarios podían ver los datos de los demás

Why it happens

Tres causas habituales para quienes no son desarrolladores:

  1. El RLS (Row Level Security) de Supabase está desactivado — las tablas del esquema public se pueden leer por completo a través de la API salvo que se active el RLS.
  2. La consulta no tiene la condición "solo lo mío" — falta un WHERE user_id = ..., o las reglas de Firebase quedaron en modo de prueba (if true).
  3. Filtrar solo en React (lado del cliente) — todas las filas, incluidas las de otras personas, ya llegaron al navegador y solo las ocultaste en pantalla. Abre la pestaña Network de las DevTools y ahí están todas. This is not security.

30-second diagnosis

En el navegador: F12 → pestaña Network → haz clic en la petición que carga la lista → Response.

Si la respuesta JSON contiene filas de otros usuarios, el servidor las está enviando, así que tienes que arreglarlo en el servidor (más abajo). Editar solo React no lo soluciona.

Fix A — If you use Supabase

  1. Asegúrate de que la tabla tenga una columna user_id (si falta, añade una columna uuid que guarde el id de auth.users).
  2. Ejecuta esto en el SQL Editor del panel (reemplaza todos por el nombre de tu tabla):
sql

-- 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 );
  1. Guarda, inicia sesión con otra cuenta y vuelve a probar. Ahora las filas de otros usuarios desaparecen por completo de la respuesta.

> Nota: una vez activado el RLS, no se ve nada hasta que añadas políticas — es lo esperado. Las políticas de arriba son las que restauran el "solo lo mío".

Fix B — If you use Firebase (Firestore)

En la consola de Firebase ve a Firestore Database → Rules, reemplaza la regla de modo de prueba (allow read, write: if true;) por la regla de propietario y pulsa Publish:

text

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;
    }
  }
}

También debes filtrar la consulta a tus propios datos. Las reglas de Firestore no son filtros: una consulta demasiado amplia no se recorta en silencio, se rechaza directamente.

js

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);

(Si tus datos están indexados por el id de usuario en la ruta del documento, usa match /users/{userId} con allow read, write: if request.auth.uid == userId;.)

Fix C — If you have your own backend (Express, etc.)

Fuerza la consulta con el userId tomado de la sesión/token de inicio de sesión. Never trust an id sent by the client — se puede cambiar.

js

// 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

Un filtro del lado del cliente (React) sirve para ordenar la pantalla, no para la seguridad. Solo el servidor (RLS, reglas de seguridad, WHERE) detiene realmente la fuga.