Files
photobooth-qr/supabase/migrations/20260916090600_expire_events_job.sql
T
KevinLecou 9b1461978b Ajoute la V1 fonctionnelle : upload invité, galerie admin, QR code, backend Supabase
Schéma dédié `photobooth` (jamais exposé via PostgREST, accès exclusivement
via fonctions SECURITY DEFINER dans public) avec RLS, policies Storage sur
bucket privé event-photos, Edge Functions admin-gallery et expire-events,
et job pg_cron d'expiration J+7. Le tout déployé et testé en conditions
réelles sur le projet Supabase kevin-lecou-hub avant relecture sécurité
(faille d'abus sur insert_public_photo corrigée en cours de route).

Côté front : page upload invité (compression + HEIC + RGPD), galerie admin
avec export ZIP, générateur de QR code autonome. Workflow n8n de purge
Storage J+7 fourni (à activer manuellement côté n8n).
2026-09-16 11:32:31 +02:00

82 lines
3.2 KiB
PL/PgSQL

-- Migration : job d'expiration J+7 (côté base de données)
-- Réf. : docs/decisions.md (suppression à J+7 à partir de date_evenement,
-- dans tous les cas, même si le ZIP a été téléchargé),
-- docs/rgpd.md (politique de conservation).
--
-- Renommée `pq_expire_events` (2026-09-15) -> `public.expire_events`
-- (2026-09-16), body mis à jour pour référencer photobooth.events /
-- photobooth.photos.
--
-- Périmètre de cette migration : UNIQUEMENT la base de données (statut de
-- l'event + suppression des lignes photobooth.photos). La suppression des
-- FICHIERS réels dans Supabase Storage (bucket event-photos) ne peut pas se
-- faire en SQL pur — traitée par l'Edge Function
-- `supabase/functions/expire-events/index.ts`, qui appelle
-- public.get_expired_event_ids() (cf. 20260916090400_create_public_functions.sql)
-- pour savoir quels dossiers purger. Déclenchement de cette Edge Function
-- NON TRANCHÉ définitivement (cf. rapport de tâche du 2026-09-15, toujours
-- valable : option pg_cron+pg_net vs cron n8n, recommandation n8n par
-- défaut) — inchangé par le passage au schéma photobooth.
--
-- ⚠️ Ne pas appliquer depuis cet agent (Kévin applique lui-même).
-- ---------------------------------------------------------------------------
-- Fonction public.expire_events()
-- ---------------------------------------------------------------------------
-- Pour chaque event actif dont expire_at est dépassé :
-- - supprime les lignes photobooth.photos associées (métadonnées) ;
-- - passe statut à 'expire'.
-- Idempotent : si rejouée alors qu'aucun event n'est éligible, ne fait rien.
create or replace function public.expire_events()
returns void
language plpgsql
security definer
set search_path = public, photobooth, pg_temp
as $$
begin
delete from photobooth.photos
where event_id in (
select id
from photobooth.events
where statut = 'actif'
and expire_at is not null
and now() >= expire_at
);
update photobooth.events
set statut = 'expire'
where statut = 'actif'
and expire_at is not null
and now() >= expire_at;
end;
$$;
comment on function public.expire_events() is
'Job quotidien (pg_cron) : marque statut=''expire'' et supprime les lignes photobooth.photos des events dont expire_at est dépassé. Ne supprime PAS les fichiers Storage (cf. Edge Function expire-events + public.get_expired_event_ids()). Exécutée par pg_cron (rôle postgres), pas de grant anon/authenticated.';
-- Aucun grant à anon/authenticated/service_role : effet de bord destructeur
-- global, appelée uniquement par pg_cron.
revoke all on function public.expire_events() from public, anon, authenticated, service_role;
-- ---------------------------------------------------------------------------
-- Planification pg_cron
-- ---------------------------------------------------------------------------
create extension if not exists pg_cron with schema extensions;
do $$
begin
if exists (select 1 from cron.job where jobname = 'expire_events_daily') then
perform cron.unschedule('expire_events_daily');
end if;
end;
$$;
-- Tous les jours à 03:00 UTC (créneau creux).
select cron.schedule(
'expire_events_daily',
'0 3 * * *',
$$select public.expire_events();$$
);