Fonction d'insertion de profil
Automatiser la création d’un profil utilisateur lors de l’inscription
Notions théoriques
Qu’est-ce qu’une fonction stockée ?
Une fonction stockée (ou procédure stockée) est un morceau de code SQL qui est enregistré dans la base de données et qui peut être exécuté automatiquement ou manuellement.
Dans PostgreSQL, ces fonctions peuvent être écrites en PL/pgSQL (le langage procédural de PostgreSQL).
Les fonctions stockées permettent d’automatiser des actions répétitives ou critiques, comme :
- insérer des données liées dans plusieurs tables,
- effectuer des vérifications complexes,
- mettre à jour des champs automatiquement.
Qu’est-ce qu’un trigger ?
Un trigger (déclencheur) est un mécanisme qui exécute automatiquement une fonction lorsqu’un événement spécifique se produit sur une table :
AFTER INSERT
→ après une insertion,BEFORE UPDATE
→ avant une mise à jour,AFTER DELETE
→ après une suppression, etc.
Un trigger est toujours lié à une table et à un événement (INSERT, UPDATE, DELETE).
Pourquoi utiliser un trigger ?
Pourquoi utiliser un trigger pour les profils utilisateurs ?
Dans Supabase, la table auth.users
est gérée automatiquement par le système d’authentification.
Mais pour stocker des informations supplémentaires sur chaque utilisateur (comme un username
ou un avatar_url
), il faut utiliser une table personnalisée : profiles
.
Plutôt que d’ajouter manuellement une ligne dans profiles
à chaque inscription, il est possible d’automatiser cette étape avec un trigger.
Fonctionnement attendu
- Un utilisateur s’inscrit via Supabase Auth.
- Une ligne est automatiquement ajoutée dans
auth.users
. - Le trigger détecte l’insertion.
- Le trigger appelle une fonction stockée.
- Cette fonction insère automatiquement une ligne dans
profiles
.
Structure attendue de la table profiles
create table public.profiles (
id uuid references auth.users on delete cascade primary key,
username text unique,
avatar_url text,
created_at timestamp with time zone default timezone('utc', now()) not null,
constraint username_length check (char_length(username) >= 3)
);
Le champ id
doit être le même que celui de auth.users
. Il est utilisé comme clé primaire et clé étrangère.
Exemple de fonction PL/pgSQL
create or replace function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id)
values (new.id);
return new;
end;
$$ language plpgsql security definer;
Cette fonction insère une ligne dans profiles
avec le même id
que celui du nouvel utilisateur.
Création du trigger associé
create trigger on_auth_user_created
after insert on auth.users
for each row
execute procedure public.handle_new_user();
Ce trigger s’exécute après chaque insertion dans auth.users
, et appelle la fonction handle_new_user()
.
Bonnes pratiques cyber
- Tester les triggers dans un environnement isolé avant de les utiliser en production.
- Limiter les privilèges d’exécution aux rôles autorisés.
- Vérifier les effets de bord : un trigger mal conçu peut provoquer des boucles infinies ou des erreurs silencieuses.
Utiliser SECURITY DEFINER
dans la fonction pour exécuter la fonction avec les droits de son créateur.
Exemple pratique
Créer une fonction qui insère automatiquement un profil
Il est possible de créer une fonction stockée simple pour insérer automatiquement une ligne dans la table profiles
à chaque nouvelle inscription.
- Créer la table
profiles
si elle n’existe pas :
create table public.profiles (
id uuid references auth.users on delete cascade primary key,
username text unique,
avatar_url text,
created_at timestamp with time zone default timezone('utc', now()) not null,
constraint username_length check (char_length(username) >= 3)
);
- Créer la fonction :
create or replace function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id)
values (new.id);
return new;
end;
$$ language plpgsql security definer;
- Créer le trigger :
create trigger on_auth_user_created
after insert on auth.users
for each row
execute procedure public.handle_new_user();
- Tester le fonctionnement :
- Aller dans l’onglet Auth de Supabase.
- Créer un nouvel utilisateur via l’interface.
- Vérifier que la table
profiles
contient automatiquement une nouvelle ligne avec le bonid
.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Objectif du TP
Créer une procédure stockée et un trigger pour insérer automatiquement un profil utilisateur dans la table profiles
à chaque inscription via Supabase Auth.
Étape 1 : Vérifier que la table profiles
existe avec la bonne structure
Vérifier dans l’interface SQL de Supabase si la table profiles
est déjà présente avec les colonnes suivantes : id
, username
, avatar_url
, created_at
.
Si elle n’existe pas, l’ajouter avec la commande suivante :
create table public.profiles (
id uuid references auth.users on delete cascade primary key,
username text unique,
avatar_url text,
created_at timestamp with time zone default timezone('utc', now()) not null,
constraint username_length check (char_length(username) >= 3)
);
Une solution
Vous devez être connecté pour voir le contenu.
Étape 2 : Écrire la fonction stockée en PL/pgSQL
Créer une fonction nommée handle_new_user
dans le schéma public
. Cette fonction sera appelée par un trigger et insèrera automatiquement une ligne dans la table profiles
avec l’id
de l’utilisateur nouvellement inscrit.
create or replace function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id)
values (new.id);
return new;
end;
$$ language plpgsql security definer;
Une solution
Vous devez être connecté pour voir le contenu.
Étape 3 : Créer le trigger lié à la table auth.users
Associer la fonction à un trigger qui s’exécutera automatiquement après chaque insertion dans auth.users
.
create trigger on_auth_user_created
after insert on auth.users
for each row
execute procedure public.handle_new_user();
Une solution
Vous devez être connecté pour voir le contenu.
Étape 4 : Tester l’automatisation via l’inscription d’un utilisateur
Aller dans l’onglet Auth du projet Supabase. Ajouter un utilisateur manuellement avec un email et un mot de passe.
Une fois l’utilisateur ajouté, ouvrir l’éditeur SQL et exécuter la requête suivante :
select * from public.profiles order by created_at desc;
Vérifier que le nouvel utilisateur a bien une ligne correspondante dans profiles
.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 5 : Sécuriser la fonction et le trigger
Vérifier que la fonction utilise bien security definer
.
Restreindre l’accès à la fonction si nécessaire, en limitant son exécution à un rôle spécifique (par exemple, un rôle système ou un rôle d’admin).
Optionnel : tester le comportement de la procédure dans un projet de test ou dans un environnement isolé.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 6 : Supprimer et recréer un utilisateur pour tester le trigger à nouveau
- Supprimer un utilisateur via l’interface Auth.
- Réinscrire un utilisateur avec un nouvel email.
- Vérifier que la table
profiles
a bien une nouvelle ligne.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 7 : Documenter dans un fichier SQL toutes les étapes précédentes
Créer un fichier trigger_profiles.sql
contenant toutes les requêtes nécessaires pour :
- créer la table
profiles
(si besoin), - créer la fonction
handle_new_user
, - créer le trigger
on_auth_user_created
.
Une solution
Vous devez être connecté pour voir le contenu.
Étape 8 : Vérifier l’état des tables via DBeaver
- Se connecter à la base distante avec DBeaver.
- Rechercher les tables
auth.users
etpublic.profiles
. - Vérifier que les données sont bien synchronisées.
- Confirmer que le trigger fonctionne même depuis une interface externe.
Une solution
Vous devez être connecté pour voir le contenu.