---
title: "Supabase raw_user_meta_data: registrácia sa stala Ownerom"
description: "Trigger handle_new_user bral role_id z raw_user_meta_data, ktoré nastavuje prehliadač. Ako sa ktokoľvek stal Ownerom, oprava cez pozvánky, kontrola za minútu."
url: "https://madsalt.tech/sk/notes/supabase-raw-user-meta-data-role/"
author: "Denys Zaichenko"
language: "sk"
published: 2026-10-18
---

# Supabase raw_user_meta_data: registrácia sa stala Ownerom

TL;DR

`raw_user_meta_data` obsahuje to, čo prehliadač odovzdal do `supabase.auth.signUp()`. V jednej produkčnej aplikácii z neho trigger `handle_new_user` čítal rolu nového používateľa, takže sa ktokoľvek mohol zaregistrovať s id roly Owner a prevziať účet. Oprava: rola pochádza z tabuľky, ktorú zapisuje iba server, vyplnenej skôr, než sa pozvánka odošle.

Stalo sa to v [sledovaní času pre audítorskú firmu](https://madsalt.tech/sk/work/audit-firm-time-tracking/), aplikácii na Supabase, kde každé pravidlo prístupu žije v databáze. Chyba sedela v triggeri, ktorý vytvára profil pre každého nového používateľa.

## Čo trigger robil?

Zjednodušene vyzeral takto:

```sql
create function public.handle_new_user()
returns trigger
language plpgsql
security definer set search_path = ''
as $$
declare
  _role_id uuid := (new.raw_user_meta_data ->> 'role_id')::uuid;
begin
  insert into public.profiles (id, full_name, role_id)
  values (new.id, new.raw_user_meta_data ->> 'full_name', _role_id);
  return new;
end;
$$;
```

Pozvánkový tok sem vkladal správne `role_id`, takže pri bežnom použití to fungovalo. Lenže `raw_user_meta_data` sú `options.data` registrácie a čo v nich bude, rozhoduje prehliadač:

```js
await supabase.auth.signUp({
  email: 'me@example.com',
  password: '...',
  options: { data: { role_id: '<owner role uuid>' } },
})
```

Kontrola oprávnení vracala pre vlastníkov true skôr, než sa pozrela na čokoľvek iné, takže toto jediné pole dávalo plnú kontrolu nad účtom. Samotný [sprievodca Users](https://supabase.com/docs/guides/auth/users) od Supabase hovorí, že metadáta používateľa sa nesmú používať v politikách RLS ani v autorizačnej logike, pretože ich používateľ môže upraviť bez akejkoľvek kontroly.

![Odkiaľ sa vzala rola nového používateľa. Trigger handle_new_user pred opravou a po nej. Pred: ktokoľvek, kto sa zaregistruje: signUp options.data → raw_user_meta_data → handle_new_user → Rola Owner; Po: iba pozvaní ľudia: Funkcia pozvánky → pending_invites → handle_new_user → Rola pozvaného.](https://madsalt.tech/charts/sk/supabase-raw-user-meta-data-role.svg)

*Z registračného triggera produkčnej aplikácie na Supabase, jún 2026.*

## Čo to opravilo?

Rola sa odteraz berie zo súkromnej tabuľky, na ktorú klient nesiahne:

```sql
create table private.pending_invites (
  email text primary key,
  role_id uuid,
  invited_by uuid,
  created_at timestamptz default now()
);
revoke all on table private.pending_invites from anon, authenticated;
```

Funkcia pozvánky beží na serveri a kontroluje oprávnenie pozývajúceho. Najprv zapíše čakajúcu pozvánku a až potom vytvorí odkaz. Trigger vyhľadá rolu podľa e-mailu a riadok zmaže. Meno sa stále berie z metadát, čo je v poriadku: sú to údaje na zobrazenie.

Na poradí záleží. Pozvánka vytvorí používateľa okamžite: [sprievodca Users](https://supabase.com/docs/guides/auth/users) od Supabase uvádza, že pozvanie nového e-mailu vytvorí nepotvrdeného používateľa. Trigger sa spustí v tom okamihu, takže čakajúci riadok už musí existovať.

## Ako skontrolovať vlastnú aplikáciu?

Otvorte svoju funkciu `handle_new_user` alebo akýkoľvek trigger na `auth.users` a vyhľadajte `raw_user_meta_data`. Meno a avatar odtiaľ sú v poriadku. Rola, firma, plán, tenant alebo čokoľvek iné, čo udeľuje prístup, musí pochádzať z tabuľky alebo z `raw_app_meta_data`, ktoré používateľ meniť nemôže.

Potom to vyskúšajte: zaregistrujte sa cez API s `role_id` alebo `role: 'admin'` v `options.data`. Nový účet nesmie dostať nič navyše.

Takáto kontrola je prvým krokom mojej [metódy testovania RLS](https://madsalt.tech/sk/blog/how-to-test-supabase-rls/). Pri multi-tenant aplikáciách sa pozrite aj na [čo RLS prehliadne u používateľa v dvoch org](https://madsalt.tech/sk/notes/supabase-rls-user-in-two-organizations/). Ďalšie kontroly, ktoré spúšťam pri každej aplikácii na Supabase, sú v mojom [checkliste bezpečnosti aplikácie z Lovable](https://madsalt.tech/sk/blog/lovable-app-security-checklist/). Prvé, na čo sa v dashboarde pozerám, je [ktoré schémy Data API vystavuje](https://madsalt.tech/sk/notes/supabase-exposed-schemas/). [Kontrola zabezpečenia Supabase](https://madsalt.tech/sk/tools/supabase-security-check/) pokrýva roly, granty, politiky a nastavenia autentifikácie podľa 46 pravidiel OWASP Top 10:2025, nie to, čo trigger kopíruje z metadát pri registrácii, takže táto kontrola zostáva ručná.
