Règles de Sécurité (RLS)
Les règles de sécurité vous permettent de définir des politiques de sécurité au niveau des lignes (RLS) pour vos tables PostgreSQL directement dans vos définitions de collection. Lorsque le schéma Drizzle est généré, Rebase crée les instructions CREATE POLICY correspondantes.
const postsCollection: EntityCollection = { slug: "posts", table: "posts", properties: { /* ... */ }, securityRules: [ { operation: "select", access: "public" }, { operations: ["insert", "update", "delete"], ownerField: "author_id" } ]};Comment cela fonctionne
Section intitulée « Comment cela fonctionne »- Vous définissez des
securityRulessur une collection rebase schema generatecrée un schéma Drizzle avec RLS activérebase db pushourebase db migrateapplique les politiques à PostgreSQL- Chaque requête est automatiquement filtrée par le contexte de l’utilisateur actuel
L’identité de l’utilisateur authentifié est disponible en SQL via :
| Fonction | Renvoie |
|---|---|
auth.uid() | L’ID de l’utilisateur actuel |
auth.roles() | ID de rôles d’application séparés par des virgules |
auth.jwt() | Revendications JWT complètes en JSONB |
Ceux-ci sont définis automatiquement par transaction par le backend Rebase.
Raccourcis Pratiques
Section intitulée « Raccourcis Pratiques »Accès basé sur le propriétaire
Section intitulée « Accès basé sur le propriétaire »Le modèle le plus simple — les utilisateurs ne peuvent accéder qu’aux lignes qu’ils possèdent :
securityRules: [ { operation: "all", ownerField: "user_id" }]Ceci génère : USING (user_id = auth.uid())
Accès Public
Section intitulée « Accès Public »Permettre à quiconque (y compris les utilisateurs non authentifiés) de lire :
securityRules: [ { operation: "select", access: "public" }]Ceci génère : USING (true)
Accès Authentifié
Section intitulée « Accès Authentifié »Permettre à tout utilisateur authentifié :
securityRules: [ { operation: "select", access: "authenticated" }]Accès basé sur les rôles
Section intitulée « Accès basé sur les rôles »Restreindre les opérations à des rôles spécifiques :
securityRules: [ { operation: "all", roles: ["admin"] }, { operation: "select", roles: ["editor", "viewer"] }]Expressions SQL Brutes
Section intitulée « Expressions SQL Brutes »Pour une logique complexe, utilisez using et withCheck :
securityRules: [ { operation: "select", using: "EXISTS (SELECT 1 FROM org_members WHERE org_members.org_id = {org_id} AND org_members.user_id = auth.uid())" }]using— Filtre les lignes existantes visibles (s’applique à SELECT, UPDATE, DELETE)withCheck— Valide les nouvelles valeurs de ligne (s’applique à INSERT, UPDATE)
Les références de colonnes utilisent la syntaxe {column_name} qui est résolue en colonne entièrement qualifiée par la table.
Combiner les raccourcis et le SQL
Section intitulée « Combiner les raccourcis et le SQL »Mélangez les raccourcis pratiques avec du SQL brut :
securityRules: [ // Les administrateurs peuvent tout faire { operation: "all", roles: ["admin"], using: "true" }, // Les utilisateurs réguliers ne peuvent voir que leurs propres lignes { operation: "select", ownerField: "user_id" }, // Les utilisateurs peuvent insérer, mais uniquement pour eux-mêmes { operation: "insert", withCheck: "{user_id} = auth.uid()" }, // Les lignes verrouillées ne peuvent pas être mises à jour { operation: "update", mode: "restrictive", using: "{is_locked} = false" }]Permissif vs Restrictif
Section intitulée « Permissif vs Restrictif »PostgreSQL a deux modes de politique :
- Permissif (par défaut) — Plusieurs politiques permissives sont combinées avec un OU. Si l’une d’elles passe, l’accès est accordé.
- Restrictif — Les politiques restrictives sont combinées avec un ET. Toutes doivent passer.
securityRules: [ // Permissif : les propriétaires peuvent accéder à leurs lignes { operation: "all", ownerField: "user_id" }, // Restrictif : mais les lignes verrouillées ne peuvent pas être mises à jour { operation: "update", mode: "restrictive", using: "{is_locked} = false", withCheck: "{is_locked} = false" }]Opérations
Section intitulée « Opérations »| Opération | Équivalent SQL | Description |
|---|---|---|
"select" | SELECT | Lire les lignes |
"insert" | INSERT | Créer de nouvelles lignes |
"update" | UPDATE | Modifier les lignes existantes |
"delete" | DELETE | Supprimer les lignes |
"all" | Toutes les opérations ci-dessus | Raccourci pour toutes les opérations |
Vous pouvez également utiliser operations (au pluriel) pour appliquer une règle à plusieurs opérations :
{ operations: ["insert", "update", "delete"], ownerField: "author_id" }Interface complète de SecurityRule
Section intitulée « Interface complète de SecurityRule »interface SecurityRule { name?: string; // Nom de politique lisible par l'homme operation?: SecurityOperation; // Opération unique operations?: SecurityOperation[]; // Opérations multiples mode?: "permissive" | "restrictive"; // Par défaut : "permissive" access?: "public" | "authenticated"; ownerField?: string; // Colonne contenant l'ID de l'utilisateur propriétaire roles?: string[]; // Rôles d'application auxquels cette politique s'applique using?: string; // Expression SQL brute USING withCheck?: string; // Expression SQL brute WITH CHECK}Exemples
Section intitulée « Exemples »Plateforme de Blog
Section intitulée « Plateforme de Blog »securityRules: [ // Tout le monde peut lire les publications publiées { operation: "select", access: "public", using: "{status} = 'published'" }, // Les auteurs peuvent voir leurs propres brouillons { operation: "select", ownerField: "author_id" }, // Les auteurs peuvent créer et modifier leurs propres publications { operations: ["insert", "update"], ownerField: "author_id" }, // Seuls les administrateurs peuvent supprimer { operation: "delete", roles: ["admin"] }]SaaS Multi-Locataire
Section intitulée « SaaS Multi-Locataire »securityRules: [ { operation: "all", using: "EXISTS (SELECT 1 FROM org_members WHERE org_members.org_id = {org_id} AND org_members.user_id = auth.uid())" }]Accès Anonyme (Insertions Publiques)
Section intitulée « Accès Anonyme (Insertions Publiques) »Un besoin courant est de permettre aux utilisateurs non authentifiés de soumettre des données — formulaires de contact, inscriptions à la newsletter, applications publiques. Rebase offre un modèle clair pour cela.
Recommandé : access: "public" avec withCheck
Section intitulée « Recommandé : access: "public" avec withCheck »const contactMessagesCollection: EntityCollection = { slug: "contact_messages", securityRules: [ // Tout le monde peut soumettre un message de contact { operation: "insert", access: "public", withCheck: "true" }, // Seuls les administrateurs peuvent lire, modifier ou supprimer des messages { operations: ["select", "update", "delete"], roles: ["admin"] } ], properties: { /* ... */ }};Le raccourci access: "public" génère une politique qui autorise l’opération sans nécessiter d’authentification.
Pour la Capture de Leads / Inscriptions
Section intitulée « Pour la Capture de Leads / Inscriptions »const leadSignupsCollection: EntityCollection = { slug: "lead_magnet_signups", securityRules: [ // Autoriser les insertions anonymes { operation: "insert", access: "public", withCheck: "true" }, // Les administrateurs peuvent consulter toutes les inscriptions { operation: "select", roles: ["admin"] } ], properties: { /* ... */ }};Comment Fonctionnent les Requêtes Anonymes
Section intitulée « Comment Fonctionnent les Requêtes Anonymes »Lorsqu’une requête arrive sans jeton JWT, le backend Rebase définit les variables de session PostgreSQL à :
| Variable | Valeur |
|---|---|
app.user_id | 'anonymous' |
app.user_roles | '' (vide) |
Cela signifie que :
auth.uid()renvoie'anonymous'auth.roles()renvoie une chaîne vide- Les politiques
access: "public"passent car elles génèrentUSING (true)/WITH CHECK (true) - Les politiques
access: "authenticated"échouent car elles vérifient un véritable ID d’utilisateur - Les politiques
ownerFieldéchouent car aucune ligne n’aurauser_id = 'anonymous'(sauf si explicitement défini)
Avancé : SQL Brut pour l’Anonyme
Section intitulée « Avancé : SQL Brut pour l’Anonyme »Si vous avez besoin d’un contrôle plus granulaire, utilisez du SQL brut :
securityRules: [ { operation: "insert", withCheck: "auth.uid() = 'anonymous' OR auth.uid() IS NOT NULL" }]Prochaines Étapes
Section intitulée « Prochaines Étapes »- Relations — Clés étrangères et jointures
- Callbacks d’Entité — Hooks de cycle de vie
- Fonctions Personnalisées — Points d’API personnalisés