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).
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
-- 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();$$
|
||||
);
|
||||
Reference in New Issue
Block a user