CaveSB SupabasePièce 5/7Intermédiaire

Row Level Security

Activer la RLS sur une table, écrire des politiques de lecture et d'écriture et comprendre pourquoi elle est indispensable avec une clé publique.

Ce que tu vas apprendre

  • Pourquoi une table exposée sans RLS est ouverte à tout le monde.
  • Activer la RLS et écrire une politique par opération.
  • Lier chaque recette à son auteur pour que lui seul puisse la modifier.

Le danger

La clé publishable est dans ton site. N'importe qui peut la copier et appeler l'API de ton projet avec elle, sans passer par ton site.

Sans protection, cette personne peut lire, modifier ou vider ta table recettes. La seule barrière est la base elle-même.

Row Level Security (RLS) est cette barrière. Quand elle est activée, une ligne n'est accessible que si une règle l'autorise.

Active la RLS sur chaque table exposée. Une table sans RLS, avec la clé publique, est une porte ouverte.

Activer la RLS

Le Table Editor du tableau de bord l'active à la création d'une table. En SQL, c'est à toi :

alter table recettes enable row level security;

Une fois activée et sans aucune politique, la table refuse tout. Un select renvoie une liste vide, un insert est rejeté.

C'est le bon point de départ : tu ouvres ensuite uniquement ce qui doit l'être.

Une politique

Une politique (policy) est une règle attachée à une table. Elle précise l'opération, le rôle concerné et la condition. Voici la lecture ouverte à tous les visiteurs :

create policy "Tout le monde peut lire les recettes"
on recettes for select
to anon, authenticated
using ( true );

Les rôles sont anon (visiteur sans compte) et authenticated (connecté). La condition using filtre les lignes déjà présentes. Ici true laisse tout passer.

Lier une recette à son auteur

Pour qu'un utilisateur ne touche qu'à ses recettes, la table doit savoir à qui appartient chaque ligne :

alter table recettes
  add column user_id uuid references auth.users (id);

La colonne user_id pointe vers la table des comptes. Le client la remplit avec l'identifiant de la personne connectée, lu dans user.sub (cours 04) :

await supabase
  .from('recettes')
  .insert({ titre: 'Crêpes', user_id: user.value?.sub })

La politique d'insertion ci-dessous vérifie que cette valeur est bien la tienne : tricher est impossible.

Écrire, modifier, supprimer

Une politique par opération, réservée aux connectés :

create policy "Ajouter ses recettes"
on recettes for insert
to authenticated
with check ( (select auth.uid()) = user_id );

create policy "Modifier ses recettes"
on recettes for update
to authenticated
using ( (select auth.uid()) = user_id )
with check ( (select auth.uid()) = user_id );

create policy "Supprimer ses recettes"
on recettes for delete
to authenticated
using ( (select auth.uid()) = user_id );

Deux mots à distinguer :

ClauseTesteS'applique à
usingLes lignes qui existent déjàselect, update, delete
with checkLes lignes écrites ou modifiéesinsert, update

Écrire (select auth.uid()) plutôt que auth.uid() seul est une recommandation de la documentation : Postgres calcule la valeur une fois par requête.

Un update a aussi besoin d'une politique de lecture qui laisse voir la ligne. Ici la politique de lecture ouverte à tous la fournit.

Tester

  1. Ouvre le site sans être connecté : tu vois les recettes, mais un insert échoue.
  2. Connecte-toi avec un compte A et ajoute une recette : elle apparaît avec ton user_id.
  3. Connecte-toi avec un compte B et tente de supprimer la recette de A : la suppression ne touche aucune ligne.

Le troisième test est le plus important. Il prouve que la règle tient même si quelqu'un contourne ton interface.

La clé secrète

La clé secrète appartient au rôle service_role, qui contourne la RLS. Aucune politique ne la retient.

Elle ne doit donc jamais figurer dans une page, un composant ou un fichier du dépôt. Supabase la refuse d'ailleurs si une requête vient d'un navigateur.

Une clé secrète publiée sur GitHub donne un accès total à tes données. Révoque-la aussitôt dans Settings, API Keys.

À retenir

  • La clé publishable est publique : la RLS est ce qui protège réellement les données.
  • Active la RLS sur chaque table exposée, avec alter table ... enable row level security.
  • Sans politique, une table avec RLS refuse tout.
  • Écris une politique par opération (select, insert, update, delete) et limite-la au rôle utile.
  • using teste les lignes existantes, with check les lignes écrites.
  • Compare toujours à auth.uid() pour que chacun ne touche qu'à ses lignes.
  • La clé secrète contourne la RLS : serveur uniquement, jamais commitée.

Pour aller plus loin

Sources officielles

Ensuite

Projet
Lignes de code
Niveau
Cave
Appartement
Supabase
Pièce
5/7
Plan n°
supabase/05.row-level-security
Lignes de code · fiches rédigées à partir des documentations officielles, sources citées en bas de chaque page.