---
title: "Supabase RLS-i testimine: 30 õigust 87-st ei teinud midagi"
description: "Supabase RLS-i testid poliitika kaupa ei näe seda, mida kasutaja näeb. Rollipõhine tõestus tootmise koopia peal leidis 87 õiguse seast 30, mis ei teinud midagi."
url: "https://madsalt.tech/et/blog/how-to-test-supabase-rls/"
author: "Denys Zaichenko"
language: "et"
published: 2026-10-14
---

# Supabase RLS-i testimine: 30 õigust 87-st ei teinud midagi

Lühidalt

Testige Supabase'i row level security't (reataseme turvet) nii, nagu liige sellega kokku puutub: logige sisse iga rolli liikmena, tehke päris toiming ühe õigusega enne väljas ja siis sees ning kontrollige, et tulemus muutub. Tootmisrakenduses, kus oli viis muudetavat rolli, selgus nii, et 30 neist 87 õiguse märkeruudust, mida administraator sai salvestada, ei muutnud andmebaasis mitte midagi. Poliitikapõhine test seda ei näe, sest see testib teie kirjutatud poliitikat, mitte ruutu ekraanil.

Olen Denys, full-stack- ja AI-insener. Selle aasta alguses ehitasin audiitorfirmale Supabase'i peale projekti- ja ajaarvestuse rakenduse, kus iga ligipääsureegel elab andmebaasis. Allpool kirjeldan meetodit, millega neid reegleid tõestan, mida see leidis ja mida selle käitamine maksab.

## Miks poliitikatestidest ei piisa, et Supabase RLS-i testida?

Poliitikatest vastab küsimusele "kas see poliitika teeb seda, mida kirjutasin?". Teie kasutajad küsivad midagi muud: "kui ma võtan sellel rollil selle linnukese maha, kas nad saavad seda ikka teha?". Väikeses rakenduses on vastus mõlemale sama. Rakenduses, mille seadete lehel muudavad administraatorid õiguste maatriksit, lähevad vastused lahku.

Rakenduses oli 41 tabelit, kus RLS oli sisse lülitatud, ja 402 `CREATE POLICY` lauset 255 migratsioonis. Administraatori ekraanil oli maatriks, kus valdkonnad (projektid, ülesanded, tööajatabelid, failid ja nii edasi) olid vastamisi toimingutega (vaatamine, loomine, muutmine, arhiveerimine), üks veerg iga rolli kohta. Iga salvestatud ruut oli lubadus administraatorile. Miski ei kontrollinud, et andmebaas seda lubadust peab.

Supabase dokumenteerib standardsed tööriistad hästi: [pgTAP testid](https://supabase.com/docs/guides/database/extensions/pgtap) ja [testiabilised](https://supabase.com/docs/guides/local-development/testing/pgtap-extended) võimaldavad luua kasutajaid, nendeks ümber lülituda ja kontrollida, mida nad lugeda saavad. Kasutage neid. Allolev meetod tuleb nende peale: seda juhib maatriks, mida administraator näeb, mitte poliitikate nimekiri.

## Kuidas maatriksi tõestus töötab?

Igast maatriksi ruudust saab sond. Sond logib sisse rolli liikmena, teeb ühe päris toimingu ja salvestab tulemuse. Ta teeb seda kaks korda: kord ruut väljas ja kord ruut sees, kõik muu samaks jäädes. Kui tulemus muutub, on ruut jõus. Kui ei muutu, ei tee ruut midagi, ükskõik kui veenvalt see ekraanil välja näeb.

1. **Üks ruut maatriksis**. Näide: Standard Member · Ülesanded · Loomine
2. **Ruut väljas: tegutse rolli liikmena**. Loo ülesanne sama teed pidi, mida kasutab rakendus. Salvesta tulemus.
3. **Ruut sees: korda sama toimingut**. Sama kasutaja, samad andmed. Muutus ainult ruut.
4. **Võrdle kahte tulemust**. Otsus sõltub ainult sellest, mida andmebaas tegi.
- **Tulemus muutus**. Jõus. Väljas keelatud, sees lubatud.
- **Mõlemal korral sama**. Ei tee midagi. Ekraan lubab kontrolli, mida pole olemas.
- **Ekraan ja andmebaas ei ole ühel meelel**. Viga. Leht näitab nuppu, mille andmebaas tagasi lükkab, või vastupidi.

*Joonis 1. Iga otsus tuleb kahest päris tulemusest, mitte kunagi koodi lugemisest.*

"Tulemus" tähendab siin seda, mida õiguse kasutaja teeb: poliitika tagastab ridu või lükkab kirjutamise tagasi, andmebaasi funktsioon tõstab vea, trigger blokeerib või edge function vastab 403. Üks ruut võib valvata mitut neist, nii et 87 ruutu vajasid 279 kontrolli rolli kohta. Iga kontroll lõppes ühega neist otsustest:

| Otsus                              | Kontrolle rolli kohta | Mida see tähendab                                              |
| ---------------------------------- | --------------------- | -------------------------------------------------------------- |
| Mõju                               | 227                   | Tulemus pöördus koos ruuduga                                   |
| Surnud                             | 30                    | Tulemus jäi samaks, olgu ruut väljas või sees                  |
| Kättesaamatu                       | 19                    | Roll ei pääse toiminguni üldse, tõestatud eraldi               |
| Edge function                      | 1                     | Jõustab edge function, kontrollitud üle HTTP                   |
| Ainult ekraanil                    | 1                     | Muudab ainult seda, mida leht näitab, kaetud front-end testiga |
| Ekraan ja andmebaas on ühel meelel | 1                     | See, mida leht pakub, vastab sellele, mida andmebaas lubab     |
| Kukkus läbi                        | 0                     | Kontroll, mille tulemus ei vastanud ootusele                   |

## Mida tõestus leidis?

Käivitus 15. septembril 2026 kattis kõik viis rolli, mida administraator saab muuta (Admin, Senior, Standard, Restricted ja kloonitud kohandatud roll). Tulemused olid kõigi rollide puhul samad.

![87 õiguse ruutu, mida administraator sai salvestada. Selle järgi, mis iga ruutu tegelikult jõustas. Sama kõigi viie rolli puhul. Jõustab andmebaas: 55; Jõustatakse mujal: 1 edge function, 1 ekraan: 2; Ei muutnud midagi: 30.](https://madsalt.tech/charts/et/how-to-test-supabase-rls.svg)

*Joonis 2. 87 õiguse ruutu, mida administraator sai salvestada, selle järgi, mis neid tegelikult jõustas. Sama tulemus kõigi viie rolli puhul.*

Ükski neist 30-st ei lasknud kedagi sisse. 29 puhul ei lugenud ükski poliitika, funktsioon ega trigger seda ruutu kunagi; viimane kaotas tähtsuse pärast seda, kui üks poliitika ümber kirjutati. See on ikkagi päris probleem: administraator, kes võtab rollil "Kustutamine" linnukese maha, usub, et roll ei saa kustutada. Peitsime kõik 30 ära, selle asemel et neid tööle ühendada, sest iga ühendamine oleks vajanud tooteotsust, ja ruut, mis ei tee midagi, ei peaks otsuse tegemise ajal ekraanil olema.

Sama töö tõi välja veel neli viga:

| Mis oli valesti                                                                                   | Kuidas see välja tuli                                    | Parandus                                                  |
| ------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------- |
| 30 ruutu ei teinud midagi                                                                         | Surnud otsus, sama tulemus väljas ja sees                | Maatriksist peidetud                                      |
| Kolm andmebaasi funktsiooni lasid toimingu läbi, kui ülesandel polnud vastutajat                  | Sond, mis oleks pidanud olema keelatud, lubati läbi      | Funktsioonid keelavad nüüd, kui väärtus puudub            |
| Tööajatabeli mustandiks lähtestamine sõltus valest ruudust                                        | Ekraan ja andmebaas ei olnud ühe rolli puhul ühel meelel | Seotud taasavamise õigusega, kuhu see kuulub              |
| Liige nägi uusi õigusi alles pärast lehe uuesti laadimist                                         | Andmebaas oli muutunud, leht mitte                       | Õigused värskenevad iga 60 sekundi järel ja akna fookusel |
| Veeru vaikeväärtus rikkus oma check-piirangut, nii et sisestused ilma selle veeruta ebaõnnestusid | Leidis paranduse turvaülevaatus sama töö käigus          | Vaikeväärtus muudetud väärtuseks, mida piirang lubab      |

Puuduva vastutaja viga oli see, mis loeb. Kaitsed olid PL/pgSQL-is kirjutatud nii:

```sql
if not (has_permission or assignee_id = auth.uid()) then
  raise exception 'forbidden';
end if;
```

Kui `assignee_id` on null, on `assignee_id = auth.uid()` null, `false or null` on null, `not null` on endiselt null ja `if` käsitleb nulli kui väära. Erind ei käivitu kunagi. Tootmises ei olnud ühelgi ülesandel vastutajat määratud, nii et see ei olnud äärejuhtum: see puudutas iga ülesannet, mis jäi ulatusse. Parandus mähib tingimuse `coalesce(…, false)` sisse, nii et puuduv väärtus keelab, ja see läks välja esimesena, omaette, enne ülejäänud partiid.

## Kuidas seda tootmise koopia vastu käitada?

Tõestus skeemi peal, mis tootmisest erineb, ei tõesta tootmise kohta midagi. Testikeskkond töötab kohalikus Supabase'i pinus, eraldi andmebaasis, mis on tootmise skeemi koopia koos ülevaatusel olevate migratsioonidega. Enne iga käivitust võrdleb see mõlema kohaliku andmebaasi sõrmejälge: 799 rida, mis kirjeldavad tabeleid, poliitikaid, funktsioone ja õigusi. Iga erinevus peatab käivituse.

1. **Tootmise skeem**. Kopeeritud ühte usaldusväärsesse masinasse. See ei lähe kunagi hostitud CI-käitajasse.
2. **Kohalik pinu: rakenduse andmebaas**. Seda teenindavad kohalik API ja auth, seda kasutavad end-to-end kontrollid.
3. **Kohalik pinu: isoleeritud tõestuse andmebaas**. Sama skeem, kasutab ainult maatriksi tõestus.
4. **Sõrmejälje kontroll**. 799 rida andmebaasi kohta. Iga erinevus peatab käivituse enne ühtki sondi.
5. **Sondid käivad iga rolli nimel**. Päris sisseloginud liikmetena, samu teid pidi, mida kasutab rakendus.
6. **Jälgi ei jää**. Ridade arv lõpus peab võrduma ridade arvuga alguses.

*Joonis 3. Tõestus loeb ainult siis, kui andmebaas, millel see käis, vastab tootmisele.*

Kaks detaili tegid testikeskkonnast usaldusväärse:

- **Kõigepealt lõhkuge see meelega.** Enne kui rohelist käivitust usaldasin, asendasin ühe insert-poliitika sellisega, mis lubab kõike, ja käivitasin tõestuse uuesti. See pidi minema punaseks nende ruutude peal, mida see poliitika valvab. Testikeskkond, mis jääb katkise poliitikaga roheliseks, on dekoratsioon.
- **Kontrollige ka salvestatud olekut.** Esimene läbimine alustab iga rolli puhtalt lähtepunktilt. Teine läbimine alustab iga rolli praegusest salvestatud maatriksist, sest ruut võib käituda teisiti nende ruutude kõrval, mille administraator on päriselt märkinud.

## Kuidas hoida see pärast väljalaset rohelisena?

Kord käivitatud tõestus vananeb järgmise migratsiooniga. Nüüd käib tõestus enne iga pushi, mis puudutab migratsioone, auth-koodi või maatriksit ennast.

1. **git push**. Muudatus puudutab migratsioone, authi või maatriksit.
2. **Pre-push hook: maatriksi tõestus**. Käib lokaalselt tõestuse andmebaasi vastu. Punane blokeerib pushi.
3. **Push jõuab maini**. Deploy käib tavapäraselt.
4. **Isehostitud CI käivitus**. Sama tõestus uuesti masinas, kus on tootmise skeemi koopia.

*Joonis 4. Blokeeriv värav on lokaalne, sest tootmise skeemi koopia jääb ühte masinasse.*

Tõestus on 135 testi 11 failis, samas projektis on nende kõrval umbes 3 100 tavalist ühiktesti.

## Mis ei töötanud?

- **Hostitud CI ei suutnud seda käitada.** Tõestus vajab tootmise skeemi koopiat ja ma ei tahtnud seda hostitud käitajasse. Seega on blokeeriv värav pre-push hook ja CI isehostitud masinas on teine kontroll, mida deploy ei oota.
- **Fikseeritud ridade arv läks katki.** Esimene "jälgi ei jää" kontroll võrdles fikseeritud arvudega. Järgmine täiesti õigustatud migratsioon lisas ühe õiguse rea ja muutis selle punaseks. Nüüd võrdleb see ridade arvu lõpus ridade arvuga alguses.
- **Vahele jäetud ei ole läbitud.** End-to-end kontrollid vajavad kohalikku edge-käituskeskkonda. Kui see maas on, jäetakse need vahele, ja vahelejätmist on lihtne lugeda roheliseks.
- **Koormatud sülearvutis on see aeglane.** Rollipõhised läbimised vajasid koormatud masinas pikemaid ajalõppe.
- **See tõestab seda, mida sondid kirjeldavad.** Ruut, millele keegi sondi ei kirjutanud, raporteeritakse kattevahena, mitte turvalisena.

## Kuidas seda oma Supabase'i rakenduses korrata

1. Pange kirja iga õigus, mida ekraan lubab kellelgi salvestada: roll × valdkond × toiming. See nimekiri on spetsifikatsioon, mitte teie poliitikad.
2. Märkige iga ruudu juurde päris toiming, mida see peaks kontrollima, ja kuidas keeldumine välja paistab (ridu pole, viga, 403).
3. Ehitage andmebaas, mis vastab tootmisele, ja võtke sellest sõrmejälg, et skeemi triiv käivituse peataks.
4. Käivitage iga toiming sisseloginud liikmena, ruut enne väljas ja siis sees, ning võrrelge.
5. Lõhkuge üks poliitika meelega ja veenduge, et tõestus läheb punaseks.
6. Peitke või ühendage tööle iga ruut, mis midagi ei tee, ja tehke tõestusest värav enne pushi.

Kui teie rakenduses on RLS juba olemas, kuid te pole kindel, et see teeb seda, mida seadete ekraan ütleb, töötab sama meetod olemasoleva koodibaasi auditina, mis on [projekti päästmise](https://madsalt.tech/et/services/project-rescue/) esimene samm. Projektist, mille taga need numbrid on, kirjutasin [audiitorfirma ajaarvestuse juhtumis](https://madsalt.tech/et/work/audit-firm-time-tracking/).

Pole kindel, kas teie RLS vastab seadete ekraanile?

Võrdlen hea meelega märkmeid selle kohta, kuidas te seda testite. Ilma müügijututa.

[Võtke ühendust](https://madsalt.tech/et/#contact)
