#!/bin/bash # Fase 13.1.2 — server admin bootstrap. # # Runs once on first volume init (docker-entrypoint-initdb.d). Reads # SERVER_ADMIN_EMAIL from the environment. If the env var is set AND the # `public.server_admins` table is empty AND there's a matching `public.users` # row, promotes that user to server admin. # # Idempotent + safe to re-run: # * If SERVER_ADMIN_EMAIL is unset → no-op (logged). # * If the table already has at least one admin → no-op (logged). This is the # guard the plan calls "second invocation with a different email shouldn't # touch previous rows". # * If the email is set but no matching user exists yet (first prod boot: # volume is fresh, nobody has signed in via Keycloak yet) → log a warning # and exit cleanly. The operator must re-run this script (or insert # manually) after the first login. Documented in docs/deployment.md. # # Order: the leading digit (10-) puts this AFTER 00-role-passwords.sh so all # the supporting role + schema bootstrap has happened. # # Caveat: `docker-entrypoint-initdb.d` only fires on a FRESH volume. On a # long-lived dev volume it never runs again after the first init. We rely on # supabase/seed.sql to also insert the seed dev admin (Ana) so the integration # + e2e suites have a deterministic admin without depending on initdb timing. set -e if [ -z "${SERVER_ADMIN_EMAIL:-}" ]; then echo "==> server-admin-seed: SERVER_ADMIN_EMAIL not set, skipping" exit 0 fi echo "==> server-admin-seed: looking up ${SERVER_ADMIN_EMAIL}…" # Bash expands ${SERVER_ADMIN_EMAIL} inside the unquoted heredoc tag below. # The PL/pgSQL `$$ ... $$` dollar-quoting needs to be escaped (\$\$) so bash # doesn't try to interpolate it. Same idea as 00-role-passwords.sh. psql -v ON_ERROR_STOP=1 --username postgres --dbname postgres < 0 THEN RAISE NOTICE 'server-admin-seed: server_admins already populated (% row(s)), skipping', v_existing; RETURN; END IF; SELECT id INTO v_user_id FROM public.users WHERE lower(email) = lower(v_email); IF v_user_id IS NULL THEN RAISE WARNING 'server-admin-seed: no public.users row matches email %, skipping (re-run after first login)', v_email; RETURN; END IF; INSERT INTO public.server_admins (user_id) VALUES (v_user_id) ON CONFLICT (user_id) DO NOTHING; RAISE NOTICE 'server-admin-seed: promoted user % (email %)', v_user_id, v_email; END \$\$; EOSQL echo "==> server-admin-seed: done"