Supabase — open-source BaaS
Auth (OAuth, OTP, magic link), Row Level Security (RLS), Storage (transformacje obrazów), Realtime (Presence), Edge Functions i pgvector.
6 modułów Supabase — opis i bezpieczeństwo
Auth, Database, Storage, Realtime, Edge Functions i Vector — co oferuje i jak zapewnić bezpieczeństwo.
| Moduł | Opis | Bezpieczeństwo |
|---|---|---|
| Auth | Email, OAuth, OTP, magic link | RLS + JWT |
| Database | PostgreSQL z wszystkimi features | RLS policies, service_role |
| Storage | Pliki + transformacje obrazów | Storage RLS policies |
| Realtime | Postgres Changes, Broadcast, Presence | RLS na Postgres Changes |
| Edge Functions | Deno runtime, globalne | service_role tylko server-side |
| Vector | pgvector — semantic search, RAG | RLS jak normalna tabela |
Często zadawane pytania
Co to jest Supabase i jak skonfigurować Auth z providerami?
Supabase: open-source Firebase alternatywa. PostgreSQL pod spodem. Auth, Storage, Realtime, Edge Functions wbudowane. Self-hosted lub hosted (supabase.com). Klient: npm install @supabase/supabase-js. import {createClient} from '@supabase/supabase-js'. const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY). Auth — Email/Password: await supabase.auth.signUp({email, password}). await supabase.auth.signInWithPassword({email, password}). await supabase.auth.signOut(). OAuth providers: await supabase.auth.signInWithOAuth({provider: 'google', options: {redirectTo: window.location.origin + '/auth/callback'}}). Providers: Google, GitHub, Discord, Twitter, Apple, Facebook. Email OTP (magic link): await supabase.auth.signInWithOtp({email: user@example.com}). Phone OTP: await supabase.auth.signInWithOtp({phone: '+48123456789'}). Session: await supabase.auth.getSession(). await supabase.auth.getUser(). supabase.auth.onAuthStateChange((event, session) => {...}). SSR (Next.js): @supabase/ssr package. createServerClient() dla Server Components. createBrowserClient() dla Client Components. cookies handler. Middleware dla refresh. Next.js cookies() API. Token refresh automatyczny. Row Level Security (RLS): SQL policies na tablicach. Tylko odpowiednie wiersze zwracane. auth.uid() — ID zalogowanego użytkownika. USING (user_id = auth.uid()). Bezpieczeństwo bez serwera aplikacji.
Row Level Security (RLS) — bezpieczeństwo na poziomie bazy danych?
RLS: PostgreSQL feature. Filtrowanie wierszy per user. Działa z anonKey — bezpieczne. Włączenie RLS: ALTER TABLE posts ENABLE ROW LEVEL SECURITY. Bez policies — nikt nie ma dostępu. Policy — SELECT: CREATE POLICY 'Users can view own posts' ON posts FOR SELECT USING (auth.uid() = user_id). Policy — INSERT: CREATE POLICY 'Users can insert own posts' ON posts FOR INSERT WITH CHECK (auth.uid() = user_id). Policy — UPDATE: CREATE POLICY 'Users can update own posts' ON posts FOR UPDATE USING (auth.uid() = user_id). Policy — DELETE: similarly. Public read: CREATE POLICY 'Public posts are viewable' ON posts FOR SELECT USING (published = true). Admin bypass: service_role key — omija RLS. Używaj tylko po stronie serwera. Nigdy nie eksponuj service_role. RLS z joins: Policies na każdej tabeli osobno. Recursive policies dla nested data. Pomocnicy: auth.uid() — current user ID. auth.role() — 'anon', 'authenticated', 'service_role'. auth.jwt() -> jsonb — cały JWT. Custom claims: supabase.auth.updateUser({data: {role: 'admin'}}). auth.jwt()->>'role' w policy. Testowanie RLS: Supabase Studio — impersonuj użytkownika. SELECT SET LOCAL role = 'authenticated'. Sprawdź co widzi. TypeScript types: npx supabase gen types typescript. Types dla tabel i columns. database.types.ts. Supabase(() => database.types.ts).
Storage — przechowywanie plików z Supabase?
Supabase Storage: S3-compatible (MinIO pod spodem). Buckety (publiczne/prywatne). Transformacje obrazów wbudowane (resize, format). Upload pliku: const {data, error} = await supabase.storage.from('avatars').upload(userId + '/avatar.jpg', file, {upsert: true, contentType: 'image/jpeg'}). data.path — ścieżka w bucket. Download URL: supabase.storage.from('avatars').getPublicUrl(path). URL publiczny (bucket musi być publiczny). Signed URL (prywatne): const {data} = await supabase.storage.from('private').createSignedUrl(path, 3600). 3600 sekund = 1 godzina. Transformacje obrazów: supabase.storage.from('avatars').getPublicUrl(path, {transform: {width: 200, height: 200, resize: 'cover', format: 'webp', quality: 80}}). Automatyczne WebP, resize. Oszczędność bandwidth. RLS na Storage: CREATE POLICY 'Avatar access' ON storage.objects FOR SELECT USING (bucket_id = 'avatars' AND auth.uid()::text = (storage.foldername(name))[1]). foldername() — folder w ścieżce. Delete: supabase.storage.from('bucket').remove([path1, path2]). List: supabase.storage.from('bucket').list(folder). Obsługa błędów: StorageError. Check error.message. Limity: 50MB per file (hosted). Zwiększ na self-hosted. Resumable uploads dla dużych plików. TUS protocol. Storage hooks (Edge Functions): on_upload, on_delete triggers. Auto-generate thumbnails. Virus scanning. Watermarking.
Realtime — subskrypcje i broadcasting w Supabase?
Supabase Realtime: WebSocket-based. Postgres Changes — zmiany w DB. Broadcast — własne eventy. Presence — kto jest online. Postgres Changes: supabase.channel('posts-channel').on('postgres_changes', {event: 'INSERT', schema: 'public', table: 'posts', filter: 'user_id=eq.' + userId}, (payload) => { console.log('New post:', payload.new) }).subscribe(). Events: INSERT, UPDATE, DELETE, * (all). Filter: eq, neq, lt, gt, lte, gte, in. RLS respektowane — użytkownik widzi tylko swoje. Broadcast (custom events): const channel = supabase.channel('room:123'). channel.on('broadcast', {event: 'cursor'}, (payload) => { updateCursor(payload.payload) }). channel.subscribe(). channel.send({type: 'broadcast', event: 'cursor', payload: {x: 100, y: 200}}). Presence (who is online): channel.on('presence', {event: 'sync'}, () => { const state = channel.presenceState(). console.log('Online:', state) }). channel.subscribe(async (status) => { await channel.track({user_id: userId, online_at: new Date().toISOString()}) }). channel.untrack(). Collaborative features: cursor sharing z Presence. Live updates z Postgres Changes. Chat z Broadcast. Typing indicators. Cleanup: channel.unsubscribe(). supabase.removeChannel(channel). Skalowanie: Supabase multiplexuje przez jeden WebSocket. Max connections per project plan. Fly.io dla self-hosted Realtime. Broadcast rate limits.
Edge Functions, Vector i zaawansowane wzorce Supabase?
Edge Functions: Deno runtime. Globalny deployment. TypeScript natywny. supabase functions new my-function. serve(async (req) => { const {data} = await req.json(). return new Response(JSON.stringify({result: data}), {headers: {'Content-Type': 'application/json'}}) }). Wewnętrzny dostęp do DB: createClient z service_role w Edge Function. Nie eksponuj service_role na frontend. Trigger przez Webhooks: Database webhooks. POST do Edge Function przy INSERT/UPDATE. Automatyzacja na zdarzeniach DB. Supabase Vector (pgvector): CREATE EXTENSION vector. Kolumna embedding vector(1536). cosine_similarity, l2_distance. Semantic search: SELECT *, 1 - (embedding cosine_distance query_embedding) AS similarity FROM documents ORDER BY similarity DESC LIMIT 5. Embedding przy INSERT: Edge Function generuje embedding. OpenAI text-embedding-3-small. Wstawia do DB. Supabase AI (wbudowane): supabase.functions.invoke('generate-embedding', {body: {text}}) lub własna Edge Function. vecs Python client dla vector ops. SQL Querying: supabase.from('posts').select('*, author(name)').eq('published', true).order('created_at', {ascending: false}).limit(10). Full-text search: .textSearch('content', query, {type: 'websearch'}). PostgreSQL full text wbudowany. Cron Jobs (pg_cron): schedule funkcji SQL. Cleanup starych wierszy. Aggregate calculations. Supabase CLI: supabase start — lokalny serwer. supabase db push — apply migrations. supabase gen types typescript. supabase db diff — sprawdź zmiany. Migration workflow.
Powiązane artykuły
Skontaktuj się z nami
Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.
Wyślij zapytanie
Telefon
+48 790 814 814
Pon-Pt: 9:00 - 18:00
adam@fotz.pl
Odpowiadamy w ciągu 24h
Adres
Plac Wolności 16
61-739 Poznań
Godziny pracy
Wolisz porozmawiać?
Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.
Zadzwoń teraz