Skip to content

Politiques RLS

Présentation

Row Level Security (RLS) est un mécanisme de sécurité natif de PostgreSQL qui filtre automatiquement les données selon l'utilisateur authentifié. Toutes les tables de BTP Chantier Pro ont RLS activé.

Principe de fonctionnement

Sans RLS, un utilisateur authentifié pourrait accéder à toutes les données de la base. Avec RLS, chaque requête est automatiquement filtrée selon des règles définies par table.

Le flux est le suivant :

  1. L'utilisateur envoie une requête avec son JWT
  2. Supabase vérifie le JWT et identifie l'utilisateur via auth.uid()
  3. PostgreSQL applique les politiques RLS avant de retourner les données
  4. Seules les données autorisées sont retournées

Fonction utilitaire

Une fonction utilitaire vérifie si un utilisateur est membre d'une organisation.

CREATE OR REPLACE FUNCTION est_membre_org(p_user_id uuid)
RETURNS boolean AS $$
  SELECT EXISTS (
    SELECT 1 FROM membres_organisation
    WHERE user_id = p_user_id
    AND statut = 'actif'
  );
$$ LANGUAGE sql SECURITY DEFINER;

Politiques par table

Table chantiers

Un utilisateur accède aux chantiers dont il est propriétaire ou membre de l'organisation.

CREATE POLICY "acces chantiers" ON chantiers
USING (
  user_id = auth.uid()
  OR est_membre_org(auth.uid())
);

Table employes

CREATE POLICY "acces employes" ON employes
USING (
  chantier_id IN (
    SELECT id FROM chantiers
    WHERE user_id = auth.uid()
    OR est_membre_org(auth.uid())
  )
);

Table presences

CREATE POLICY "acces presences" ON presences
USING (
  chantier_id IN (
    SELECT id FROM chantiers
    WHERE user_id = auth.uid()
    OR est_membre_org(auth.uid())
  )
)
WITH CHECK (
  chantier_id IN (
    SELECT id FROM chantiers
    WHERE user_id = auth.uid()
    OR est_membre_org(auth.uid())
  )
);

Table depenses

CREATE POLICY "acces depenses" ON depenses
USING (
  chantier_id IN (
    SELECT id FROM chantiers
    WHERE user_id = auth.uid()
    OR est_membre_org(auth.uid())
  )
)
WITH CHECK (
  chantier_id IN (
    SELECT id FROM chantiers
    WHERE user_id = auth.uid()
    OR est_membre_org(auth.uid())
  )
);

Vérification des politiques

Pour vérifier les politiques actives sur une table :

SELECT policyname, cmd, qual
FROM pg_policies
WHERE tablename = 'nom_de_la_table';

Erreurs courantes

new row violates row-level security policy

Cette erreur apparaît lors d'un INSERT refusé par la politique WITH CHECK. Vérifier que WITH CHECK est bien défini sur la table.

permission denied for table

Les droits GRANT ne sont pas accordés au rôle authenticated. Exécuter :

GRANT ALL ON nom_de_la_table TO authenticated;

Bonnes pratiques

  • Toujours définir USING et WITH CHECK pour les tables recevant des insertions
  • Tester les politiques avec un compte utilisateur standard
  • Ne jamais désactiver RLS sur une table en production
  • Documenter chaque nouvelle politique

BTP Chantier Pro