Zum Inhalt springen

Sicherheitsregeln (RLS)

Sicherheitsregeln ermöglichen es Ihnen, Row Level Security (RLS)-Richtlinien für Ihre PostgreSQL-Tabellen direkt in Ihren Sammlungsdefinitionen zu definieren. Wenn das Drizzle-Schema generiert wird, erstellt Rebase die entsprechenden CREATE POLICY-Anweisungen.

const postsCollection: EntityCollection = {
slug: "posts",
table: "posts",
properties: { /* ... */ },
securityRules: [
{ operation: "select", access: "public" },
{ operations: ["insert", "update", "delete"], ownerField: "author_id" }
]
};
  1. Sie definieren securityRules für eine Sammlung
  2. rebase schema generate erstellt ein Drizzle-Schema mit aktivierter RLS
  3. rebase db push oder rebase db migrate wendet die Richtlinien auf PostgreSQL an
  4. Jede Abfrage wird automatisch nach dem Kontext des aktuellen Benutzers gefiltert

Die Identität des authentifizierten Benutzers ist in SQL verfügbar über:

FunktionRückgabewert
auth.uid()Die ID des aktuellen Benutzers
auth.roles()Kommagetrennte App-Rollen-IDs
auth.jwt()Vollständige JWT-Claims als JSONB

Diese werden vom Rebase-Backend automatisch pro Transaktion gesetzt.

Das einfachste Muster — Benutzer können nur auf Zeilen zugreifen, die sie besitzen:

securityRules: [
{ operation: "all", ownerField: "user_id" }
]

Dies erzeugt: USING (user_id = auth.uid())

Jedem (einschließlich nicht authentifizierten Benutzern) das Lesen erlauben:

securityRules: [
{ operation: "select", access: "public" }
]

Dies erzeugt: USING (true)

Jedem authentifizierten Benutzer erlauben:

securityRules: [
{ operation: "select", access: "authenticated" }
]

Operationen auf bestimmte Rollen beschränken:

securityRules: [
{ operation: "all", roles: ["admin"] },
{ operation: "select", roles: ["editor", "viewer"] }
]

Für komplexe Logik verwenden Sie using und 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 — Filtert, welche bestehenden Zeilen sichtbar sind (gilt für SELECT, UPDATE, DELETE)
  • withCheck — Validiert neue Zeilenwerte (gilt für INSERT, UPDATE)

Spaltenreferenzen verwenden die {column_name}-Syntax, die zu der vollständig tabellenqualifizierten Spalte aufgelöst wird.

Mischen Sie praktische Shortcuts mit rohem SQL:

securityRules: [
// Admins können alles tun
{ operation: "all", roles: ["admin"], using: "true" },
// Reguläre Benutzer können nur ihre eigenen Zeilen sehen
{ operation: "select", ownerField: "user_id" },
// Benutzer können einfügen, aber nur für sich selbst
{ operation: "insert", withCheck: "{user_id} = auth.uid()" },
// Gesperrte Zeilen können nicht aktualisiert werden
{ operation: "update", mode: "restrictive", using: "{is_locked} = false" }
]

PostgreSQL hat zwei Richtlinienmodi:

  • Permissiv (Standard) — Mehrere permissive Richtlinien werden miteinander verknüpft (OR). Wenn eine davon erfolgreich ist, wird der Zugriff gewährt.
  • Restriktiv — Restriktive Richtlinien werden miteinander verknüpft (AND). Alle müssen erfolgreich sein.
securityRules: [
// Permissiv: Eigentümer können auf ihre Zeilen zugreifen
{ operation: "all", ownerField: "user_id" },
// Restriktiv: aber gesperrte Zeilen können nicht aktualisiert werden
{ operation: "update", mode: "restrictive", using: "{is_locked} = false", withCheck: "{is_locked} = false" }
]
OperationSQL-ÄquivalentBeschreibung
"select"SELECTZeilen lesen
"insert"INSERTNeue Zeilen erstellen
"update"UPDATEBestehende Zeilen ändern
"delete"DELETEZeilen entfernen
"all"Alle oben genanntenAbkürzung für alle Operationen

Sie können auch operations (Plural) verwenden, um eine Regel auf mehrere Operationen anzuwenden:

{ operations: ["insert", "update", "delete"], ownerField: "author_id" }
interface SecurityRule {
name?: string; // Menschlich lesbarer Richtlinienname
operation?: SecurityOperation; // Einzelne Operation
operations?: SecurityOperation[]; // Mehrere Operationen
mode?: "permissive" | "restrictive"; // Standard: "permissive"
access?: "public" | "authenticated";
ownerField?: string; // Spalte, die die Benutzer-ID des Eigentümers enthält
roles?: string[]; // App-Rollen, für die diese Richtlinie gilt
using?: string; // Roher SQL USING-Ausdruck
withCheck?: string; // Roher SQL WITH CHECK-Ausdruck
}
securityRules: [
// Jeder kann veröffentlichte Beiträge lesen
{ operation: "select", access: "public", using: "{status} = 'published'" },
// Autoren können ihre eigenen Entwürfe sehen
{ operation: "select", ownerField: "author_id" },
// Autoren können ihre eigenen Beiträge erstellen und bearbeiten
{ operations: ["insert", "update"], ownerField: "author_id" },
// Nur Admins können löschen
{ operation: "delete", roles: ["admin"] }
]
securityRules: [
{
operation: "all",
using: "EXISTS (SELECT 1 FROM org_members WHERE org_members.org_id = {org_id} AND org_members.user_id = auth.uid())"
}
]

Ein häufiges Bedürfnis ist es, nicht authentifizierten Benutzern das Übermitteln von Daten zu ermöglichen — Kontaktformulare, Newsletter-Anmeldungen, öffentliche Anwendungen. Rebase bietet hierfür ein klares Muster.

const contactMessagesCollection: EntityCollection = {
slug: "contact_messages",
securityRules: [
// Jeder kann eine Kontaktanfrage senden
{
operation: "insert",
access: "public",
withCheck: "true"
},
// Nur Admins können Nachrichten lesen, aktualisieren oder löschen
{ operations: ["select", "update", "delete"], roles: ["admin"] }
],
properties: { /* ... */ }
};

Der access: "public"-Shortcut generiert eine Richtlinie, die die Operation ohne Authentifizierung ermöglicht.

const leadSignupsCollection: EntityCollection = {
slug: "lead_magnet_signups",
securityRules: [
// Anonyme Einfügungen erlauben
{ operation: "insert", access: "public", withCheck: "true" },
// Admins können alle Anmeldungen einsehen
{ operation: "select", roles: ["admin"] }
],
properties: { /* ... */ }
};

Wenn eine Anfrage ohne JWT-Token eingeht, setzt das Rebase-Backend die PostgreSQL-Sitzungsvariablen auf:

VariableWert
app.user_id'anonymous'
app.user_roles'' (leer)

Das bedeutet:

  • auth.uid() gibt 'anonymous' zurück
  • auth.roles() gibt eine leere Zeichenkette zurück
  • access: "public"-Richtlinien werden erfolgreich ausgeführt, da sie USING (true) / WITH CHECK (true) generieren
  • access: "authenticated"-Richtlinien schlagen fehl, da sie eine echte Benutzer-ID prüfen
  • ownerField-Richtlinien schlagen fehl, da keine Zeile user_id = 'anonymous' haben wird (es sei denn, dies ist explizit festgelegt)

Wenn Sie eine feinere Kontrolle benötigen, verwenden Sie rohes SQL:

securityRules: [
{
operation: "insert",
withCheck: "auth.uid() = 'anonymous' OR auth.uid() IS NOT NULL"
}
]