Wann du es brauchst
Die App speichert neue Nutzerdaten in Supabase, zum Beispiel Notizen, Favoriten oder Tagebucheinträge, und zeigt sie auf einem Screen an.
Regeln
- Die App enthält den Publishable Key, daher trennt nur RLS die Zeilen eines Nutzers von denen anderer. Jede neue Tabelle aktiviert RLS in der Migration, die sie anlegt.
- Migrationen sind append-only: Ändere nie eine bereits angewendete.
- Jede neue Policy hat einen pgTAP-Test, der erlaubten Zugriff belegt und den Rest ablehnt.
- Supabase wird nur aus einem Repository in
dataaufgerufen, hinter einer Schnittstelle indomain.
Schritte
Lege
supabase/migrations/<timestamp>_<name>.sqlmit einem Zeitstempel nach dem letzten an, nach dem Vorbild vonpush_devices:create table public.notes ( id uuid primary key default gen_random_uuid(), user_id uuid not null default auth.uid() references auth.users(id) on delete cascade, body text not null check (char_length(body) between 1 and 2000), created_at timestamptz not null default now() ); create index notes_user_id_idx on public.notes (user_id); alter table public.notes enable row level security; create policy "notes_select_own" on public.notes for select to authenticated using ((select auth.uid()) = user_id); create policy "notes_insert_own" on public.notes for insert to authenticated with check ((select auth.uid()) = user_id); create policy "notes_delete_own" on public.notes for delete to authenticated using ((select auth.uid()) = user_id); revoke all on public.notes from anon;Füge nur die Operationen hinzu, die die App braucht: Hier können Nutzer eine Notiz nicht bearbeiten.
Braucht ein Schreibvorgang Regeln, die eine Policy nicht ausdrücken kann, etwa einen Eigentümerwechsel oder die Prüfung anderer Tabellen, entziehe direkte Schreibrechte und biete eine
security definer-Funktion mitset search_path = ''und einer Prüfung aufauth.uid()an, wieregister_push_device.Lege
supabase/tests/database/<name>_rls.test.sqlnach dem Vorbild vonpush_devices_rls.test.sqlan: zwei Nutzer inauth.users,set local role authenticated,request.jwt.claim.subabwechselnd auf jeden Nutzer gesetzt. Prüfe, dass ein Nutzer nur seine eigenen Zeilen sieht und ändert, dass das Schreiben einer Zeile für jemand anderen mit42501fehlschlägt und dassanonnichts erhält.Führe lokal
supabase db resetundsupabase test dbaus.Definiere in
lib/features/<feature>/domaindas Modell mitfromJsonund eineabstract interface classfür das Repository, wieProfileRepository. Implementiere sie indatamitSupabaseClient, wieSupabaseProfileRepository: Ohne Sitzung wirf einen Fehler, statt die Abfrage auszuführen.Stelle das Repository in
applicationüber einenProviderbereit, dersupabaseClientProviderliest, wieprofileRepositoryProvider, und füge die Provider hinzu, die der Screen beobachtet. Für den Screen folge dem Playbook „Einen Screen mit Route und State hinzufügen“.Füge Dart-Tests für das Mapping des Modells und für die Provider mit einem Fake-Repository hinzu; die Tests nutzen kein Netzwerk.
Trage Tabelle, Eigentümer und Regel in die Tabelle in
DATABASE.mdein.
Fertig, wenn
- die Prüfbefehle erfolgreich sind;
supabase test dbeinschließlich des neuen Tests erfolgreich ist;- die Tabelle RLS aktiviert hat und nur die Policies, die die App braucht;
DATABASE.mddie Tabelle aufführt.
