|
| 1 | +-- ═══════════════════════════════════════════════════════════════════════════════ |
| 2 | +-- Migration 022: Explicit GRANT statements for Supabase Data API access |
| 3 | +-- ═══════════════════════════════════════════════════════════════════════════════ |
| 4 | +-- |
| 5 | +-- WHY: Starting May 30 2026 (new projects) and October 30 2026 (existing projects), |
| 6 | +-- Supabase no longer auto-grants Data API access to tables in the "public" schema. |
| 7 | +-- Without explicit GRANTs, PostgREST / supabase-js / GraphQL will return "42501" |
| 8 | +-- permission errors on any table created after the cutoff date. |
| 9 | +-- |
| 10 | +-- This migration retroactively adds explicit GRANTs to ALL existing public tables |
| 11 | +-- so the transition is seamless. It is idempotent (safe to re-run). |
| 12 | +-- Each GRANT is wrapped in a safety check so missing tables are silently skipped. |
| 13 | +-- ═══════════════════════════════════════════════════════════════════════════════ |
| 14 | + |
| 15 | +DO $$ |
| 16 | +DECLARE |
| 17 | + tbl TEXT; |
| 18 | + all_tables TEXT[] := ARRAY[ |
| 19 | + -- Core HR |
| 20 | + 'employees', |
| 21 | + 'departments', |
| 22 | + 'leave_requests', |
| 23 | + 'leave_balances', |
| 24 | + 'attendance_records', |
| 25 | + 'audit_logs', |
| 26 | + -- Payroll |
| 27 | + 'employee_salaries', |
| 28 | + 'payslips', |
| 29 | + 'payroll_runs', |
| 30 | + 'payroll_deductions', |
| 31 | + 'employee_expenses', |
| 32 | + -- ATS / Recruitment |
| 33 | + 'jobs', |
| 34 | + 'job_listings', |
| 35 | + 'job_applications', |
| 36 | + 'applications', |
| 37 | + 'interviews', |
| 38 | + 'interview_sessions', |
| 39 | + 'candidate_assessments', |
| 40 | + 'assessments', |
| 41 | + -- Performance & Training |
| 42 | + 'performance_reviews', |
| 43 | + 'review_cycles', |
| 44 | + 'performance_goals', |
| 45 | + 'goals', |
| 46 | + 'training_courses', |
| 47 | + 'training_enrollments', |
| 48 | + -- Onboarding / Offboarding |
| 49 | + 'onboarding_records', |
| 50 | + 'onboarding_tasks', |
| 51 | + 'offboarding_records', |
| 52 | + 'offboarding_tasks', |
| 53 | + -- HR Ops |
| 54 | + 'hr_tickets', |
| 55 | + 'hr_policies', |
| 56 | + 'employee_documents', |
| 57 | + 'expenses', |
| 58 | + -- Pulse Surveys |
| 59 | + 'pulse_surveys', |
| 60 | + 'pulse_survey_responses', |
| 61 | + -- Automation |
| 62 | + 'automation_rules', |
| 63 | + 'automation_logs', |
| 64 | + -- Multi-tenant / Org |
| 65 | + 'companies', |
| 66 | + 'users', |
| 67 | + 'org_profiles', |
| 68 | + -- Billing |
| 69 | + 'subscriptions', |
| 70 | + 'payment_transactions' |
| 71 | + ]; |
| 72 | +BEGIN |
| 73 | + FOREACH tbl IN ARRAY all_tables |
| 74 | + LOOP |
| 75 | + -- Only grant if the table actually exists in public schema |
| 76 | + IF EXISTS ( |
| 77 | + SELECT 1 FROM information_schema.tables |
| 78 | + WHERE table_schema = 'public' AND table_name = tbl |
| 79 | + ) THEN |
| 80 | + EXECUTE format('GRANT SELECT ON public.%I TO anon', tbl); |
| 81 | + EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON public.%I TO authenticated', tbl); |
| 82 | + EXECUTE format('GRANT ALL ON public.%I TO service_role', tbl); |
| 83 | + RAISE NOTICE 'Granted access on: %', tbl; |
| 84 | + ELSE |
| 85 | + RAISE NOTICE 'Skipped (does not exist): %', tbl; |
| 86 | + END IF; |
| 87 | + END LOOP; |
| 88 | +END |
| 89 | +$$; |
| 90 | + |
| 91 | + |
| 92 | +-- ───────────────────────────────────────────────────────────────────────────── |
| 93 | +-- SEQUENCES — Grant usage on all sequences in public schema |
| 94 | +-- (Required for gen_random_uuid() / auto-increment inserts via Data API) |
| 95 | +-- ───────────────────────────────────────────────────────────────────────────── |
| 96 | + |
| 97 | +GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO anon; |
| 98 | +GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO authenticated; |
| 99 | +GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO service_role; |
| 100 | + |
| 101 | + |
| 102 | +-- ───────────────────────────────────────────────────────────────────────────── |
| 103 | +-- DEFAULT PRIVILEGES — Auto-grant on FUTURE tables and sequences |
| 104 | +-- (This is the key safeguard: any new CREATE TABLE will automatically |
| 105 | +-- get these grants, preventing 42501 errors after the cutoff date) |
| 106 | +-- ───────────────────────────────────────────────────────────────────────────── |
| 107 | + |
| 108 | +ALTER DEFAULT PRIVILEGES IN SCHEMA public |
| 109 | + GRANT SELECT ON TABLES TO anon; |
| 110 | + |
| 111 | +ALTER DEFAULT PRIVILEGES IN SCHEMA public |
| 112 | + GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO authenticated; |
| 113 | + |
| 114 | +ALTER DEFAULT PRIVILEGES IN SCHEMA public |
| 115 | + GRANT ALL ON TABLES TO service_role; |
| 116 | + |
| 117 | +ALTER DEFAULT PRIVILEGES IN SCHEMA public |
| 118 | + GRANT USAGE, SELECT ON SEQUENCES TO anon, authenticated, service_role; |
| 119 | + |
| 120 | + |
| 121 | +-- ───────────────────────────────────────────────────────────────────────────── |
| 122 | +-- SCHEMA USAGE — Ensure roles can access the public schema itself |
| 123 | +-- ───────────────────────────────────────────────────────────────────────────── |
| 124 | + |
| 125 | +GRANT USAGE ON SCHEMA public TO anon; |
| 126 | +GRANT USAGE ON SCHEMA public TO authenticated; |
| 127 | +GRANT USAGE ON SCHEMA public TO service_role; |
| 128 | + |
| 129 | + |
| 130 | +-- ═══════════════════════════════════════════════════════════════════════════════ |
| 131 | +-- REFRESH POSTGREST SCHEMA CACHE |
| 132 | +-- ═══════════════════════════════════════════════════════════════════════════════ |
| 133 | +NOTIFY pgrst, 'reload schema'; |
| 134 | + |
| 135 | + |
| 136 | +-- ═══════════════════════════════════════════════════════════════════════════════ |
| 137 | +-- DONE. After running this migration: |
| 138 | +-- |
| 139 | +-- 1. All existing tables have explicit GRANTs for anon, authenticated, service_role |
| 140 | +-- 2. Tables that don't exist are silently skipped (check NOTICE logs) |
| 141 | +-- 3. RLS policies (already in place) still control row-level access |
| 142 | +-- 4. DEFAULT PRIVILEGES ensure future tables automatically get the same grants |
| 143 | +-- 5. No 42501 errors will occur after the Supabase May 30 / October 30 cutoff |
| 144 | +-- ═══════════════════════════════════════════════════════════════════════════════ |
0 commit comments