---
title: "How to enable RLS in Supabase: čo vráti po každom kroku"
description: "How to enable RLS in Supabase z dashboardu alebo SQL, vyskúšané lokálne: čo po každom kroku dostane verejný kľúč, dvaja používatelia a tajný kľúč."
url: "https://madsalt.tech/sk/blog/how-to-enable-rls-in-supabase/"
author: "Denys Zaichenko"
author_url: "https://madsalt.tech/sk/about/"
language: "sk"
published: 2026-11-04
---

# How to enable RLS in Supabase: čo vráti po každom kroku

TL;DR

RLS v Supabase zapnete jedným príkazom na tabuľku, `alter table public.todos enable row level security;`, alebo voľbou „Enable RLS“ v dashboarde. Tabuľky vytvorené v SQL editore alebo migráciou ho v predvolenom stave nemajú. Hneď po zapnutí tabuľka skôr stíchne, než aby kričala. V mojom lokálnom teste dostal verejný kľúč aj dvaja prihlásení používatelia pri select, update a delete `200 []` a zlyhal len insert, s `42501`. Tajný kľúč stále videl všetky 3 riadky. Obyčajný pohľad (view) nad tabuľkou stále vydal všetky 3 riadky verejnému kľúču. Od 30. októbra 2026 navyše nová tabuľka potrebuje grant, než sa k nej niečo dostane, takže zapnite RLS a napíšte politiky v tej istej migrácii ako grant.

Prevádzkujem bezplatnú [Kontrolu zabezpečenia Supabase](https://madsalt.tech/sk/tools/supabase-security-check/) a „RLS disabled“ je nález, ktorý je vysvetlený najhoršie. Väčšina návodov hovorí, že po zapnutí RLS sa „tabuľka stane neprístupnou“. Pri čítaní to platí, pri zápisoch to klame. Preto som postavil jednu tabuľku na lokálnom Supabase stacku a po každom z krokov nižšie jej posielal všetky druhy požiadaviek: ako verejný kľúč, ako dvaja prihlásení používatelia a ako tajný kľúč.

## Čo je RLS v Supabase?

RLS (row-level security) je funkcia Postgresu, ktorá filtruje riadky podľa požiadavky. Supabase mení každú požiadavku z `supabase-js` na dopyt do databázy, ktorý beží ako rola: `anon` pre verejný kľúč (anon, publishable), `authenticated` pre prihláseného používateľa. Pri zapnutom RLS Postgres kontroluje vaše politiky pre každý riadok a vracia, mení alebo maže len tie riadky, ktoré politika povolí. Pri vypnutom RLS sa každá rola s grantom na tabuľku dostane ku všetkým riadkom.

Tajný kľúč (service role) je iný. Jeho rola má `BYPASSRLS`, takže sa naň RLS nikdy nevzťahuje. Preto patrí len na server. Rozdiel medzi oboma kľúčmi je v článku [Supabase anon key vs service role key: čo ktorý otvorí](https://madsalt.tech/sk/blog/supabase-anon-key-vs-service-role-key/).

## Ako zapnúť RLS v Supabase?

Tromi spôsobmi, podľa toho, ako tabuľka vznikla:

- **Pri vytváraní tabuľky v Table Editore** nechajte zaškrtnuté „Enable Row Level Security (RLS)“. V [zdrojovom kóde dashboardu](https://github.com/supabase/supabase/commit/33bd798d142183e162c25debcc50c8c711e68f66) je označené „Recommended“ a pri vypnutí sa zobrazí varovanie, že tabuľka bude verejne čitateľná a zapisovateľná.
- **Pri existujúcej tabuľke** [sprievodca zabezpečením API](https://supabase.com/docs/guides/api/securing-your-api) od Supabase hovorí: otvorte Database, potom Policies a pri tabuľke zvoľte „Enable RLS“.
- **V SQL**, v SQL editore alebo v migrácii:

```sql
alter table public.todos enable row level security;
```

Sprievodca Supabase výslovne uvádza, že tabuľky vytvorené v dashboarde majú RLS zapnuté v predvolenom stave a tabuľky vytvorené v SQL editore alebo iným nástrojom nie. Ak schému tvoríte migráciami alebo AI nástrojom, skontrolujte každú tabuľku.

## Čo sa stane hneď po zapnutí RLS?

Nič nehlási chybu okrem insertu. Vytvoril som `public.todos` so stĺpcom vlastníka (`user_id uuid default auth.uid()`), udelil jej práva rolám API tak, ako to robili staršie projekty, a pridal tri riadky: dva patriace používateľovi A a jeden používateľovi B. Potom som zapol RLS bez akejkoľvek politiky:

| Požiadavka              | Verejný kľúč     | Používateľ A     | Používateľ B     | Tajný kľúč          |
| ----------------------- | ---------------- | ---------------- | ---------------- | ------------------- |
| Select                  | 200, 0 riadkov   | 200, 0 riadkov   | 200, 0 riadkov   | 200, 3 riadky       |
| Insert vlastného riadku | 401, chyba 42501 | 403, chyba 42501 | 403, chyba 42501 | 201, riadok vložený |
| Update riadku           | 200, 0 riadkov   | 200, 0 riadkov   | 200, 0 riadkov   | 200, 1 riadok       |
| Delete riadku           | 200, 0 riadkov   | 200, 0 riadkov   | 200, 0 riadkov   | 200, 1 riadok       |

Chyba insertu znie `new row violates row-level security policy`. Update a delete odpovedia `200` s prázdnym poľom, takže aplikácia, ktorá nekontroluje vrátené riadky, hlási „uložené“, aj keď sa nič neuložilo. Po zapnutí RLS si zápisy načítajte späť, alebo si vyžiadajte počet cez `Prefer: count=exact`.

Pred RLS, s rovnakými grantmi, mohol verejný kľúč prečítať všetky 3 riadky, vkladať a meniť alebo mazať ľubovoľný riadok. Používateľ A mohol upraviť a zmazať riadok používateľa B a svoje riadky odovzdať používateľovi B.

## Ako tabuľku znova sprevádzkovať?

Napíšte politiku pre každú operáciu. Obvyklá sada pre vlastné riadky:

```sql
create policy "own select" on public.todos for select to authenticated
  using ((select auth.uid()) = user_id);
create policy "own insert" on public.todos for insert to authenticated
  with check ((select auth.uid()) = user_id);
create policy "own update" on public.todos for update to authenticated
  using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id);
create policy "own delete" on public.todos for delete to authenticated
  using ((select auth.uid()) = user_id);
```

S týmito politikami videl používateľ A svoje 2 riadky a používateľ B svoj 1. Verejný kľúč stále videl 0. Keď sa A pokúsil vložiť riadok patriaci B alebo presunúť vlastný riadok k B, odpoveď bola `403, 42501`. Toto odmietnutie pochádza z `with check` pri update. Keď sa A pokúsil zmeniť alebo zmazať riadok používateľa B, odpoveď bola `200, 0 rows`. Ďalšie vzory (verejné profily, tímy, MFA) sú v článku [Supabase RLS policy: príklady otestované cez API](https://madsalt.tech/sk/blog/supabase-rls-policy-examples/).

Jeden detail z tajného kľúča: riadok, ktorý vložil, dostal `user_id = null`, pretože `auth.uid()` za týmto kľúčom nemá žiadneho používateľa. RLS sa preskočilo, ale predvolená hodnota neurobila to, čo naznačuje názov stĺpca.

## Čo čítal verejný kľúč v jednotlivých krokoch?

![Riadky prečítané verejným kľúčom, z 3. Jedna tabuľka Supabase s 3 riadkami, po každom kroku. Nová tabuľka, bez grantu, RLS off (chyba 42501): 0; Grant pridaný, RLS off: 3; RLS on, bez politiky: 0; RLS on, vlastné politiky: 0; Obyčajný view nad tabuľkou: 3; View so security_invoker: 0.](https://madsalt.tech/charts/sk/how-to-enable-rls-in-supabase.svg)

*Obrázok 1. Lokálny Supabase stack (CLI 2.109.1, Postgres 17.6), 28. októbra 2026.*

Dva kroky vyzradia všetko: grant bez RLS a obyčajný view nad tabuľkou so správnymi politikami. Ďalšie dve sekcie vysvetľujú oba.

## Potrebujete RLS aj po zmene grantov z 30. októbra?

Áno. Od 30. októbra 2026 Supabase už nedáva novým tabuľkám v `public` automatické granty pre role API, pri nových aj existujúcich projektoch. Môj lokálny stack sa už tak správa. Čerstvo vytvorená tabuľka s vypnutým RLS odpovedala `42501` všetkým rolám, vrátane tajného kľúča, takže nič neuniklo. Podrobnosti sú v článku [Supabase 30. októbra: zmena grantov a čo prestane fungovať](https://madsalt.tech/sk/blog/supabase-october-30-grant-change/).

Grant sa však vráti, hneď ako aplikácia tabuľku potrebuje, a od tej chvíle je RLS jediné, čo stojí medzi verejným kľúčom a všetkými riadkami. Preto dajte všetko do jednej migrácie, v tomto poradí:

```sql
create table public.todos (...);
alter table public.todos enable row level security;
create policy "own select" on public.todos ...;
grant select, insert, update, delete on table public.todos to authenticated;
```

Udeľte grant len rolám, ktoré tabuľku potrebujú. Keď som roli `anon` odobral všetko, select verejného kľúča sa zmenil z `200 []` na `401, 42501`. Grant je prvý zámok, RLS druhý.

## Prečo view stále prepúšťa riadky?

Pretože view beží s právami svojho vlastníka, a v Supabase je to `postgres`, ktorý RLS obchádza. Pri platných politikách pre vlastné riadky na `todos` vrátil obyčajný `create view public.todos_view as select * from public.todos` všetky 3 riadky verejnému kľúču aj používateľovi B.

Po vytvorení znova s `with (security_invoker = true)` vrátil rovnaký view verejnému kľúču 0 riadkov, A 2 a B 1, presne ako tabuľka:

```sql
create view public.todos_view with (security_invoker = true) as
  select * from public.todos;
```

Advisor Supabase označuje obyčajný druh ako `security_definer_view`; čo to znamená a ako to opraviť, je v [poznámke o Supabase view security definer](https://madsalt.tech/sk/notes/supabase-security-definer-view/).

## Ako zapnúť RLS na každej novej tabuľke automaticky?

Event triggerom. [Sprievodca event triggermi](https://supabase.com/docs/guides/database/postgres/event-triggers) od Supabase uvádza funkciu `rls_auto_enable()` a trigger `ensure_rls`, ktorý beží po `create table`, `create table as` a `select into` v `public`. Nainštaloval som ho tak, ako je zverejnený, a dostal:

- Tabuľka vytvorená potom príkazom `create table` mala RLS zapnuté bez akéhokoľvek `alter`. Verejný kľúč dostal `200 []` pri select a `401` pri insert.
- Tabuľka vytvorená príkazom `create table as select` tiež mala RLS zapnuté.
- Tabuľka vytvorená pred triggerom zostala vypnutá. Trigger nepôsobí spätne.

Bez triggera mala druhá tabuľka vytvorená vedľa chránenej RLS vypnuté, a hneď ako dostala grant, verejný kľúč ju voľne čítal aj zapisoval. Pokrýva tiež len `public`; ostatné vystavené schémy potrebujú vlastný riadok vo funkcii.

## Pomáha FORCE ROW LEVEL SECURITY?

Nie pri rolách, o ktoré by ste sa báli. `alter table ... force row level security` spôsobí, že sa RLS uplatní aj na vlastníka tabuľky. V Supabase majú `postgres` aj `service_role` `BYPASSRLS`, takže vlastník po `force` stále napočítal 3 riadky, tajný kľúč stále videl všetko a view vlastnený `postgres` stále prepúšťal. Zmenilo to len rolu vlastníka, ktorú som vytvoril bez `BYPASSRLS`: 2 riadky pred, 0 po.

## Ako skontrolovať vlastný projekt?

- V SQL editore vypíšte tabuľky v `public` s vypnutým RLS:

```sql
select c.relname as table_name
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public'
  and c.relkind in ('r', 'p')
  and not c.relrowsecurity
order by 1;
```

- Advisor v dashboarde hlási to isté ako `rls_disabled_in_public`; čo tá chyba znamená, je v [poznámke o RLS disabled in public](https://madsalt.tech/sk/notes/supabase-rls-disabled-in-public/).
- Bezplatná [Kontrola zabezpečenia Supabase](https://madsalt.tech/sk/tools/supabase-security-check/) číta váš projekt len na čítanie a vypíše tabuľky s vypnutým RLS, ku ktorým API dosiahne, views obchádzajúce RLS a politiky, ktoré povoľujú všetkým, ku každému s opravným SQL.
- Skener nemôže vedieť, ktoré riadky komu patria. Aby ste to dokázali, pošlite požiadavky ako dvaja používatelia, ako je uvedené vyššie. Celá metóda pre aplikáciu s rolami je v článku [Ako testovať Supabase RLS: 30 z 87 oprávnení nerobilo nič](https://madsalt.tech/sk/blog/how-to-test-supabase-rls/).

## Ako som testoval

- Supabase CLI 2.109.1 na notebooku: Postgres 17.6, PostgREST 14.14, Auth 2.192.0. Dvaja používatelia prihlásení heslom a lokálne publishable a secret kľúče.
- Jedna tabuľka, `public.todos`, pred každou požiadavkou znovu naplnená rovnakými 3 riadkami. Každý krok bol aplikovaný ako SQL a každá požiadavka išla cez REST API, so zaznamenaným stavovým kódom a telom.
- Granty pre kroky 2 až 5 boli pridané ručne, aby zodpovedali projektu vytvorenému pred 30. októbrom 2026.

**Limity.** Jeden lokálny stack, vymyslené dáta, 28. októbra 2026. Kroky v dashboarde sú citované z dokumentácie Supabase, nie preklikané. Tabuľky vytvorené vlastnou rolou dashboardu môžu mať iné predvolené granty. To som netestoval, rovnako ako Storage, Realtime alebo GraphQL.

Nie ste si istí, že sú vaše tabuľky zamknuté?

Rád sa pozriem na schému spolu s vami. Bez ponuky.

[Ozvite sa](https://madsalt.tech/sk/#contact)
