-- ============================================================
-- Gustito Express — CANDADO ANTI-ESCALADA en perfiles
-- ------------------------------------------------------------
-- Problema (critico): la policy `perfiles_propio_update` permite al usuario
-- actualizar su propia fila y solo valida `id = auth.uid()`. No restringe QUE
-- columnas cambian, y no habia trigger que protegiera `rol`/`restaurante_id`.
-- Resultado: cualquier usuario autenticado podia hacer un PATCH directo a
-- PostgREST (perfiles?id=eq.<yo>) poniendose rol='admin' (o rol='dueno' +
-- restaurante_id de otro negocio) y con eso leer/escribir TODO (pedidos,
-- pagos, PII de clientes, etc.). Confirmado en produccion 2026-07-11.
--
-- Fix: trigger BEFORE UPDATE que bloquea el cambio de `rol` y `restaurante_id`
-- cuando lo intenta el rol de PostgREST (anon/authenticated) y NO es admin.
-- Los cambios legitimos siguen funcionando porque:
--   * crear_restaurante() y handle_new_user() son SECURITY DEFINER (corren como
--     el owner postgres) -> current_user NO es authenticated/anon -> permitido.
--   * un admin real (fn_es_admin()) -> permitido.
--   * el usuario normal editando nombre/telefono (sin tocar rol) -> permitido.
--
-- IMPORTANTE: el trigger es SECURITY INVOKER a proposito. Si fuera DEFINER,
-- current_user siempre seria el owner y el chequeo nunca bloquearia.
-- ============================================================

create or replace function public.fn_perfiles_lock_rol()
returns trigger
language plpgsql
security invoker
set search_path = public
as $$
begin
  if (new.rol is distinct from old.rol
      or new.restaurante_id is distinct from old.restaurante_id)
     and current_user in ('authenticated', 'anon')
     and not public.fn_es_admin()
  then
    raise exception 'No autorizado: no puedes cambiar rol ni restaurante_id de tu perfil';
  end if;
  return new;
end;
$$;

drop trigger if exists trg_perfiles_lock_rol on public.perfiles;
create trigger trg_perfiles_lock_rol
  before update on public.perfiles
  for each row execute function public.fn_perfiles_lock_rol();
