-- Lucozade Store Audit · Auth V6 -- Ejecutar una vez en Supabase SQL Editor. -- Es idempotente y NO elimina usuarios de auth.users. -- V6 usa los enlaces de recuperación nativos de Supabase Auth; -- por eso elimina la tabla y los RPC personalizados de recuperación de V5. begin; -- Objetos obsoletos de V5 (ya no son necesarios). drop function if exists public.lucozade_consume_password_reset(text, text); drop function if exists public.lucozade_issue_password_reset(uuid, text); drop function if exists public.lucozade_find_recoverable_user_by_email(text); drop table if exists public.lucozade_password_reset_tokens; -- Acceso específico a la aplicación. create table if not exists public.lucozade_access ( user_id uuid primary key references auth.users(id) on delete cascade, email text not null, full_name text, is_active boolean not null default true, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); -- Compatibilidad si la tabla venía de una versión anterior. alter table public.lucozade_access add column if not exists email text, add column if not exists full_name text, add column if not exists is_active boolean not null default true, add column if not exists created_at timestamptz not null default now(), add column if not exists updated_at timestamptz not null default now(); update public.lucozade_access set email = lower(coalesce(email, '')) where email is distinct from lower(coalesce(email, '')); alter table public.lucozade_access alter column email set not null; create index if not exists lucozade_access_email_idx on public.lucozade_access (lower(email)); create or replace function public.lucozade_set_updated_at() returns trigger language plpgsql security invoker set search_path = public as $$ begin new.email = lower(trim(new.email)); new.updated_at = now(); return new; end; $$; drop trigger if exists lucozade_access_set_updated_at on public.lucozade_access; create trigger lucozade_access_set_updated_at before update on public.lucozade_access for each row execute function public.lucozade_set_updated_at(); -- Los usuarios creados por el workflow V6 llevan app_id=lucozade-audit. -- Este trigger crea el acceso automáticamente; n8n también hace un upsert -- como segunda garantía antes de responder que el registro terminó. create or replace function public.handle_new_lucozade_user() returns trigger language plpgsql security definer set search_path = '' as $$ begin if coalesce(new.raw_user_meta_data ->> 'app_id', '') = 'lucozade-audit' then insert into public.lucozade_access ( user_id, email, full_name, is_active ) values ( new.id, lower(coalesce(new.email, '')), nullif(trim(coalesce(new.raw_user_meta_data ->> 'full_name', '')), ''), true ) on conflict (user_id) do update set email = excluded.email, full_name = excluded.full_name, is_active = true, updated_at = now(); end if; return new; end; $$; drop trigger if exists on_lucozade_auth_user_created on auth.users; create trigger on_lucozade_auth_user_created after insert on auth.users for each row execute function public.handle_new_lucozade_user(); -- Recupera accesos de usuarios Lucozade existentes que pudieran haber sido -- creados antes de instalar el trigger. insert into public.lucozade_access ( user_id, email, full_name, is_active ) select u.id, lower(coalesce(u.email, '')), nullif(trim(coalesce(u.raw_user_meta_data ->> 'full_name', '')), ''), true from auth.users as u where coalesce(u.raw_user_meta_data ->> 'app_id', '') = 'lucozade-audit' and coalesce(u.email, '') <> '' on conflict (user_id) do update set email = excluded.email, full_name = coalesce(excluded.full_name, public.lucozade_access.full_name), updated_at = now(); alter table public.lucozade_access enable row level security; drop policy if exists "Lucozade users can read their active access" on public.lucozade_access; create policy "Lucozade users can read their active access" on public.lucozade_access for select to authenticated using (auth.uid() = user_id and is_active = true); revoke all on public.lucozade_access from anon; grant usage on schema public to authenticated, service_role; grant select on public.lucozade_access to authenticated; grant select, insert, update, delete on public.lucozade_access to service_role; notify pgrst, 'reload schema'; commit; -- IMPORTANTE: -- Borrar una fila de public.lucozade_access revoca el acceso a Lucozade, -- pero NO elimina la cuenta real de Supabase Auth. -- Para eliminar totalmente una cuenta, use Authentication > Users -- o, con extremo cuidado: -- delete from auth.users where lower(email)=lower('correo@ejemplo.com');