201 lines
12 KiB
SQL
201 lines
12 KiB
SQL
-- ============================================================================
|
|
-- Africa Alert — Supabase tenant_id reconciliation script
|
|
-- Paste into Supabase SQL Editor, then RUN.
|
|
-- Safe to re-run (idempotent).
|
|
-- Tenant UUID hard-coded below (matches local system_settings.tenant_id).
|
|
-- ============================================================================
|
|
|
|
DO $script$
|
|
DECLARE
|
|
v_tenant_id uuid := '5b39bcb5-506a-456d-b7cb-91730b397cc1';
|
|
BEGIN
|
|
|
|
-- Sanity check: tenant must exist in the tenants table.
|
|
IF NOT EXISTS (SELECT 1 FROM public.tenants WHERE id = v_tenant_id) THEN
|
|
RAISE EXCEPTION 'Tenant % not found in public.tenants. Insert it first or re-run the registration cycle on the server.', v_tenant_id;
|
|
END IF;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- 1. Backfill null tenant_id on every business table that carries one
|
|
-- (skip 'tenants' itself, plus 'notices' / 'sync_logs' / 'sync_metadata'
|
|
-- / 'sync_config' which don't have a tenant_id column).
|
|
---------------------------------------------------------------------------
|
|
UPDATE public.admission_enquiries SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.applicants SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.assignments SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.attendance SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.attendance_new SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.calendar_events SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.classes SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.club_announcements SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.club_attendance SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.club_chats SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.club_memberships SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.clubs SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.complaints SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.course_enrolments SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.course_grades SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.courses SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.crossword_clues SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.crossword_games SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.crossword_sessions SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.departments SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.enrollments SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.events SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.exam_answers SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.exam_attempts SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.exam_groups SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.exam_schedules SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.expenses SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.fee_groups SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.grades SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.hostel_attendance SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.hostel_fees SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.hostels SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.item_categories SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.item_issues SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.item_stock SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.items SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.leave_requests SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.leave_types SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.library_books SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.library_fines SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.library_issues SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.library_reservations SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.messages SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.messages_new SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.parent_students SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.payments SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.payroll_runs SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.payslips SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.phone_call_logs SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.pickup_points SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.postal_dispatch SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.question_banks SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.room_assignments SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.room_types SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.rooms SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.routes SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.salary_grades SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.settings SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.staff_attendance SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.staff_records SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.staff_roles SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.stock_transactions SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.store_locations SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.student_fees SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.subjects SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.subjects_new SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.submissions SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.suppliers SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.system_settings SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.transport_allocations SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.transport_attendance SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.users SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.vacancies SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.vehicle_routes SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.vehicles SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.visitor_logs SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
UPDATE public.audit_logs SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- 2. Enforce NOT NULL now that all rows have a tenant.
|
|
-- Wrapped in dynamic SQL + DO blocks so missing columns don't blow up.
|
|
---------------------------------------------------------------------------
|
|
PERFORM (
|
|
SELECT string_agg(
|
|
format('ALTER TABLE public.%I ALTER COLUMN tenant_id SET NOT NULL', t.table_name),
|
|
'; '
|
|
)
|
|
FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND column_name = 'tenant_id'
|
|
AND is_nullable = 'YES'
|
|
AND table_name <> 'tenants'
|
|
)::text;
|
|
|
|
IF (SELECT string_agg(
|
|
format('ALTER TABLE public.%I ALTER COLUMN tenant_id SET NOT NULL', t.table_name), '; ')
|
|
FROM information_schema.columns
|
|
WHERE table_schema='public' AND column_name='tenant_id'
|
|
AND is_nullable='YES' AND table_name <> 'tenants') IS NOT NULL THEN
|
|
EXECUTE (
|
|
SELECT string_agg(
|
|
format('ALTER TABLE public.%I ALTER COLUMN tenant_id SET NOT NULL', t.table_name),
|
|
'; '
|
|
)
|
|
FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND column_name = 'tenant_id'
|
|
AND is_nullable = 'YES'
|
|
AND table_name <> 'tenants'
|
|
);
|
|
END IF;
|
|
|
|
---------------------------------------------------------------------------
|
|
-- 3. Indexes on tenant_id (RLS checks every row; you want these).
|
|
---------------------------------------------------------------------------
|
|
PERFORM (
|
|
SELECT string_agg(
|
|
format('CREATE INDEX IF NOT EXISTS %I ON public.%I (tenant_id)', t.table_name || '_tenant_id_idx', t.table_name),
|
|
'; '
|
|
)
|
|
FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND column_name = 'tenant_id'
|
|
AND table_name <> 'tenants'
|
|
);
|
|
|
|
IF (SELECT string_agg(
|
|
format('CREATE INDEX IF NOT EXISTS %I ON public.%I (tenant_id)', t.table_name || '_tenant_id_idx', t.table_name), '; ')
|
|
FROM information_schema.columns
|
|
WHERE table_schema='public' AND column_name='tenant_id'
|
|
AND table_name <> 'tenants') IS NOT NULL THEN
|
|
EXECUTE (
|
|
SELECT string_agg(
|
|
format('CREATE INDEX IF NOT EXISTS %I ON public.%I (tenant_id)', t.table_name || '_tenant_id_idx', t.table_name),
|
|
'; '
|
|
)
|
|
FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND column_name = 'tenant_id'
|
|
AND table_name <> 'tenants'
|
|
);
|
|
END IF;
|
|
|
|
RAISE NOTICE 'Tenant % reconciled: rows backfilled, NOT NULL enforced, indexes created.', v_tenant_id;
|
|
END
|
|
$script$;
|
|
|
|
|
|
-- ============================================================================
|
|
-- 4. Enable RLS + tenant-isolation policies on every tenant_id-bearing table.
|
|
-- service_role key bypasses RLS, so the sync engine still has full access.
|
|
-- Run as a separate batch (RLS changes can't be inside the DO block).
|
|
-- ============================================================================
|
|
|
|
DO $rls$
|
|
DECLARE
|
|
r record;
|
|
BEGIN
|
|
FOR r IN
|
|
SELECT c.table_name
|
|
FROM information_schema.columns c
|
|
WHERE c.table_schema = 'public'
|
|
AND c.column_name = 'tenant_id'
|
|
AND c.table_name <> 'tenants'
|
|
LOOP
|
|
EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', r.table_name);
|
|
|
|
-- Drop any prior version of our policy to keep this idempotent.
|
|
EXECUTE format('DROP POLICY IF EXISTS tenant_isolation ON public.%I', r.table_name);
|
|
|
|
EXECUTE format(
|
|
'CREATE POLICY tenant_isolation ON public.%I
|
|
USING (tenant_id::text = current_setting(''app.current_tenant'', true))
|
|
WITH CHECK (tenant_id::text = current_setting(''app.current_tenant'', true))',
|
|
r.table_name
|
|
);
|
|
END LOOP;
|
|
END
|
|
$rls$; |