diff --git a/.github/workflows/publish-migrations-prod.yml b/.github/workflows/publish-migrations-prod.yml new file mode 100644 index 000000000..d7e813667 --- /dev/null +++ b/.github/workflows/publish-migrations-prod.yml @@ -0,0 +1,41 @@ +name: Release Migrations - Prod + +on: + workflow_dispatch: + +jobs: + build: + runs-on: [self-hosted, linux] + timeout-minutes: 15 + permissions: + id-token: write + contents: read + + steps: + - name: Guard + run: | + if [ $GITHUB_REF != 'refs/heads/develop' ]; then + echo "This action can only be run on the develop branch" + exit 1 + fi + env: + GITHUB_REF: ${{ github.ref }} + + - name: Checkout Repo + uses: actions/checkout@v2 + + - name: Merging migration files + run: cat $(ls -1) > ../migration-output.sql + working-directory: ${{ github.workspace }}/migrations/db/migrations + + - name: configure aws credentials - prod + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: ${{ secrets.PROD_AWS_ROLE }} + aws-region: "ap-southeast-1" + + - name: Deploy to S3 prod + shell: bash + run: aws s3 sync migrations/db s3://$AWS_S3_BUCKET/migrations/db --delete + env: + AWS_S3_BUCKET: ${{ secrets.PG_INIT_SCRIPT_S3_BUCKET_PROD }} diff --git a/.github/workflows/publish-migrations.yml b/.github/workflows/publish-migrations-staging.yml similarity index 65% rename from .github/workflows/publish-migrations.yml rename to .github/workflows/publish-migrations-staging.yml index 1abc9f2b6..440838ac7 100644 --- a/.github/workflows/publish-migrations.yml +++ b/.github/workflows/publish-migrations-staging.yml @@ -1,4 +1,4 @@ -name: Release Migrations +name: Release Migrations - Staging on: push: @@ -32,15 +32,3 @@ jobs: run: aws s3 sync migrations/db s3://$AWS_S3_BUCKET/migrations/db --delete env: AWS_S3_BUCKET: ${{ secrets.PG_INIT_SCRIPT_S3_BUCKET_STAGING }} - - - name: configure aws credentials - prod - uses: aws-actions/configure-aws-credentials@v1 - with: - role-to-assume: ${{ secrets.PROD_AWS_ROLE }} - aws-region: "ap-southeast-1" - - - name: Deploy to S3 prod - shell: bash - run: aws s3 sync migrations/db s3://$AWS_S3_BUCKET/migrations/db --delete - env: - AWS_S3_BUCKET: ${{ secrets.PG_INIT_SCRIPT_S3_BUCKET_PROD }} diff --git a/flake.nix b/flake.nix index 4038a152d..19a20146f 100644 --- a/flake.nix +++ b/flake.nix @@ -807,6 +807,9 @@ exit 1 fi + echo "Running migrations tests" + pg_prove -p 5435 -U supabase_admin -h localhost -d postgres -v ${./migrations/tests}/test.sql + mkdir -p $out/regression_output if ! pg_regress \ --use-existing \ @@ -822,15 +825,12 @@ exit 1 fi - echo "Running migrations tests" - pg_prove -p 5435 -U supabase_admin -h localhost -d postgres -v ${./migrations/tests}/test.sql - # Copy logs to output for logfile in $(find /tmp -name postgresql.log -type f); do cp "$logfile" $out/postgresql.log done exit 0 - ''; + ''; in rec { # The list of all packages that can be built with 'nix build'. The list diff --git a/migrations/README.md b/migrations/README.md index e74fe4a53..ef3c7215b 100644 --- a/migrations/README.md +++ b/migrations/README.md @@ -42,6 +42,8 @@ nix run github:supabase/postgres/mybranch#dbmate-tool -- --version 15 aiming to provide a single source of truth for migrations on the platform that can be depended upon by those components. For more information on goals see [the RFC](https://www.notion.so/supabase/Centralize-SQL-Migrations-cd3847ae027d4f2bba9defb2cc82f69a) + + ## How it was Created Migrations were pulled (in order) from: @@ -51,8 +53,9 @@ Migrations were pulled (in order) from: For compatibility with hosted projects, we include [migrate.sh](migrate.sh) that executes migrations in the same order as ami build: -1. Run all `db/migrations` with `supabase_admin` superuser role. -2. Finalize role passwords with `/etc/postgresql.schema.sql` if present. +1. Run all `db/init-scripts` with `postgres` superuser role. +2. Run all `db/migrations` with `supabase_admin` superuser role. +3. Finalize role passwords with `/etc/postgresql.schema.sql` if present. Additionally, [supabase/postgres](https://github.com/supabase/postgres/blob/develop/ansible/playbook-docker.yml#L9) image contains several migration scripts to configure default extensions. These are run first by docker entrypoint and included in ami by ansible. diff --git a/migrations/db/init-scripts/00000000000000-initial-schema.sql b/migrations/db/init-scripts/00000000000000-initial-schema.sql new file mode 100644 index 000000000..ecce79a3d --- /dev/null +++ b/migrations/db/init-scripts/00000000000000-initial-schema.sql @@ -0,0 +1,57 @@ +-- migrate:up + +-- Set up realtime +-- defaults to empty publication +create publication supabase_realtime; + +-- Supabase super admin +alter user supabase_admin with superuser createdb createrole replication bypassrls; + +-- Supabase replication user +create user supabase_replication_admin with login replication; + +-- Supabase read-only user +create role supabase_read_only_user with login bypassrls; +grant pg_read_all_data to supabase_read_only_user; + +-- Extension namespacing +create schema if not exists extensions; +create extension if not exists "uuid-ossp" with schema extensions; +create extension if not exists pgcrypto with schema extensions; +create extension if not exists pgjwt with schema extensions; + +-- Set up auth roles for the developer +create role anon nologin noinherit; +create role authenticated nologin noinherit; -- "logged in" user: web_user, app_user, etc +create role service_role nologin noinherit bypassrls; -- allow developers to create JWT's that bypass their policies + +create user authenticator noinherit; +grant anon to authenticator; +grant authenticated to authenticator; +grant service_role to authenticator; +grant supabase_admin to authenticator; + +grant usage on schema public to postgres, anon, authenticated, service_role; +alter default privileges in schema public grant all on tables to postgres, anon, authenticated, service_role; +alter default privileges in schema public grant all on functions to postgres, anon, authenticated, service_role; +alter default privileges in schema public grant all on sequences to postgres, anon, authenticated, service_role; + +-- Allow Extensions to be used in the API +grant usage on schema extensions to postgres, anon, authenticated, service_role; + +-- Set up namespacing +alter user supabase_admin SET search_path TO public, extensions; -- don't include the "auth" schema + +-- These are required so that the users receive grants whenever "supabase_admin" creates tables/function +alter default privileges for user supabase_admin in schema public grant all + on sequences to postgres, anon, authenticated, service_role; +alter default privileges for user supabase_admin in schema public grant all + on tables to postgres, anon, authenticated, service_role; +alter default privileges for user supabase_admin in schema public grant all + on functions to postgres, anon, authenticated, service_role; + +-- Set short statement/query timeouts for API roles +alter role anon set statement_timeout = '3s'; +alter role authenticated set statement_timeout = '8s'; + +-- migrate:down diff --git a/migrations/db/migrations/00000000000001-auth-schema.sql b/migrations/db/init-scripts/00000000000001-auth-schema.sql similarity index 75% rename from migrations/db/migrations/00000000000001-auth-schema.sql rename to migrations/db/init-scripts/00000000000001-auth-schema.sql index d76eb10cf..ad47aadd9 100644 --- a/migrations/db/migrations/00000000000001-auth-schema.sql +++ b/migrations/db/init-scripts/00000000000001-auth-schema.sql @@ -4,7 +4,7 @@ CREATE SCHEMA IF NOT EXISTS auth AUTHORIZATION supabase_admin; -- auth.users definition -CREATE TABLE IF NOT EXISTS auth.users ( +CREATE TABLE auth.users ( instance_id uuid NULL, id uuid NOT NULL UNIQUE, aud varchar(255) NULL, @@ -28,13 +28,13 @@ CREATE TABLE IF NOT EXISTS auth.users ( updated_at timestamptz NULL, CONSTRAINT users_pkey PRIMARY KEY (id) ); -CREATE INDEX IF NOT EXISTS users_instance_id_email_idx ON auth.users USING btree (instance_id, email); -CREATE INDEX IF NOT EXISTS users_instance_id_idx ON auth.users USING btree (instance_id); +CREATE INDEX users_instance_id_email_idx ON auth.users USING btree (instance_id, email); +CREATE INDEX users_instance_id_idx ON auth.users USING btree (instance_id); comment on table auth.users is 'Auth: Stores user login data within a secure schema.'; -- auth.refresh_tokens definition -CREATE TABLE IF NOT EXISTS auth.refresh_tokens ( +CREATE TABLE auth.refresh_tokens ( instance_id uuid NULL, id bigserial NOT NULL, "token" varchar(255) NULL, @@ -44,14 +44,14 @@ CREATE TABLE IF NOT EXISTS auth.refresh_tokens ( updated_at timestamptz NULL, CONSTRAINT refresh_tokens_pkey PRIMARY KEY (id) ); -CREATE INDEX IF NOT EXISTS refresh_tokens_instance_id_idx ON auth.refresh_tokens USING btree (instance_id); -CREATE INDEX IF NOT EXISTS refresh_tokens_instance_id_user_id_idx ON auth.refresh_tokens USING btree (instance_id, user_id); -CREATE INDEX IF NOT EXISTS refresh_tokens_token_idx ON auth.refresh_tokens USING btree (token); +CREATE INDEX refresh_tokens_instance_id_idx ON auth.refresh_tokens USING btree (instance_id); +CREATE INDEX refresh_tokens_instance_id_user_id_idx ON auth.refresh_tokens USING btree (instance_id, user_id); +CREATE INDEX refresh_tokens_token_idx ON auth.refresh_tokens USING btree (token); comment on table auth.refresh_tokens is 'Auth: Store of tokens used to refresh JWT tokens once they expire.'; -- auth.instances definition -CREATE TABLE IF NOT EXISTS auth.instances ( +CREATE TABLE auth.instances ( id uuid NOT NULL, uuid uuid NULL, raw_base_config text NULL, @@ -63,25 +63,24 @@ comment on table auth.instances is 'Auth: Manages users across multiple sites.'; -- auth.audit_log_entries definition -CREATE TABLE IF NOT EXISTS auth.audit_log_entries ( +CREATE TABLE auth.audit_log_entries ( instance_id uuid NULL, id uuid NOT NULL, payload json NULL, created_at timestamptz NULL, CONSTRAINT audit_log_entries_pkey PRIMARY KEY (id) ); -CREATE INDEX IF NOT EXISTS audit_logs_instance_id_idx ON auth.audit_log_entries USING btree (instance_id); +CREATE INDEX audit_logs_instance_id_idx ON auth.audit_log_entries USING btree (instance_id); comment on table auth.audit_log_entries is 'Auth: Audit trail for user actions.'; -- auth.schema_migrations definition -CREATE TABLE IF NOT EXISTS auth.schema_migrations ( +CREATE TABLE auth.schema_migrations ( "version" varchar(255) NOT NULL, CONSTRAINT schema_migrations_pkey PRIMARY KEY ("version") ); comment on table auth.schema_migrations is 'Auth: Manages updates to the auth system.'; --- insert migrations if they do not yet exist INSERT INTO auth.schema_migrations (version) VALUES ('20171026211738'), ('20171026211808'), @@ -89,8 +88,7 @@ VALUES ('20171026211738'), ('20180103212743'), ('20180108183307'), ('20180119214651'), - ('20180125194653') -ON CONFLICT DO NOTHING; + ('20180125194653'); -- Gets the User ID from the request cookie create or replace function auth.uid() returns uuid as $$ @@ -111,18 +109,8 @@ $$ language sql stable; GRANT USAGE ON SCHEMA auth TO anon, authenticated, service_role; -- Supabase super admin -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'supabase_auth_admin' - ) - then - CREATE USER supabase_auth_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; - end if; -end -$$; - +CREATE USER supabase_auth_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; +GRANT ALL PRIVILEGES ON SCHEMA auth TO supabase_auth_admin; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA auth TO supabase_auth_admin; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA auth TO supabase_auth_admin; ALTER USER supabase_auth_admin SET search_path = "auth"; diff --git a/migrations/db/migrations/00000000000002-storage-schema.sql b/migrations/db/init-scripts/00000000000002-storage-schema.sql similarity index 80% rename from migrations/db/migrations/00000000000002-storage-schema.sql rename to migrations/db/init-scripts/00000000000002-storage-schema.sql index 3446c3420..40503e4dd 100644 --- a/migrations/db/migrations/00000000000002-storage-schema.sql +++ b/migrations/db/init-scripts/00000000000002-storage-schema.sql @@ -7,7 +7,7 @@ alter default privileges in schema storage grant all on tables to postgres, anon alter default privileges in schema storage grant all on functions to postgres, anon, authenticated, service_role; alter default privileges in schema storage grant all on sequences to postgres, anon, authenticated, service_role; -CREATE TABLE IF NOT EXISTS "storage"."buckets" ( +CREATE TABLE "storage"."buckets" ( "id" text not NULL, "name" text NOT NULL, "owner" uuid, @@ -16,9 +16,9 @@ CREATE TABLE IF NOT EXISTS "storage"."buckets" ( CONSTRAINT "buckets_owner_fkey" FOREIGN KEY ("owner") REFERENCES "auth"."users"("id"), PRIMARY KEY ("id") ); -CREATE UNIQUE INDEX IF NOT EXISTS "bname" ON "storage"."buckets" USING BTREE ("name"); +CREATE UNIQUE INDEX "bname" ON "storage"."buckets" USING BTREE ("name"); -CREATE TABLE IF NOT EXISTS "storage"."objects" ( +CREATE TABLE "storage"."objects" ( "id" uuid NOT NULL DEFAULT extensions.uuid_generate_v4(), "bucket_id" text, "name" text, @@ -31,12 +31,12 @@ CREATE TABLE IF NOT EXISTS "storage"."objects" ( CONSTRAINT "objects_owner_fkey" FOREIGN KEY ("owner") REFERENCES "auth"."users"("id"), PRIMARY KEY ("id") ); -CREATE UNIQUE INDEX IF NOT EXISTS "bucketid_objname" ON "storage"."objects" USING BTREE ("bucket_id","name"); -CREATE INDEX IF NOT EXISTS name_prefix_search ON storage.objects(name text_pattern_ops); +CREATE UNIQUE INDEX "bucketid_objname" ON "storage"."objects" USING BTREE ("bucket_id","name"); +CREATE INDEX name_prefix_search ON storage.objects(name text_pattern_ops); ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY; -CREATE OR REPLACE FUNCTION storage.foldername(name text) +CREATE FUNCTION storage.foldername(name text) RETURNS text[] LANGUAGE plpgsql AS $function$ @@ -48,7 +48,7 @@ BEGIN END $function$; -CREATE OR REPLACE FUNCTION storage.filename(name text) +CREATE FUNCTION storage.filename(name text) RETURNS text LANGUAGE plpgsql AS $function$ @@ -60,7 +60,7 @@ BEGIN END $function$; -CREATE OR REPLACE FUNCTION storage.extension(name text) +CREATE FUNCTION storage.extension(name text) RETURNS text LANGUAGE plpgsql AS $function$ @@ -75,7 +75,7 @@ BEGIN END $function$; -CREATE OR REPLACE FUNCTION storage.search(prefix text, bucketname text, limits int DEFAULT 100, levels int DEFAULT 1, offsets int DEFAULT 0) +CREATE FUNCTION storage.search(prefix text, bucketname text, limits int DEFAULT 100, levels int DEFAULT 1, offsets int DEFAULT 0) RETURNS TABLE ( name text, id uuid, @@ -104,17 +104,7 @@ CREATE TABLE IF NOT EXISTS storage.migrations ( executed_at timestamp DEFAULT current_timestamp ); -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'supabase_storage_admin' - ) - then - CREATE USER supabase_storage_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; - end if; -end -$$; +CREATE USER supabase_storage_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; GRANT ALL PRIVILEGES ON SCHEMA storage TO supabase_storage_admin; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA storage TO supabase_storage_admin; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA storage TO supabase_storage_admin; diff --git a/migrations/db/migrations/00000000000003-post-setup.sql b/migrations/db/init-scripts/00000000000003-post-setup.sql similarity index 89% rename from migrations/db/migrations/00000000000003-post-setup.sql rename to migrations/db/init-scripts/00000000000003-post-setup.sql index 8b7730cdd..47cdd13a0 100644 --- a/migrations/db/migrations/00000000000003-post-setup.sql +++ b/migrations/db/init-scripts/00000000000003-post-setup.sql @@ -39,20 +39,8 @@ BEGIN END; $$; -DO $$ - -BEGIN - IF NOT EXISTS ( - SELECT 1 - FROM pg_catalog.pg_event_trigger - WHERE evtname = 'issue_pg_cron_access' - ) - THEN - CREATE EVENT TRIGGER issue_pg_cron_access ON ddl_command_end WHEN TAG in ('CREATE SCHEMA') - EXECUTE PROCEDURE extensions.grant_pg_cron_access(); - END IF; -END -$$; +CREATE EVENT TRIGGER issue_pg_cron_access ON ddl_command_end WHEN TAG in ('CREATE SCHEMA') +EXECUTE PROCEDURE extensions.grant_pg_cron_access(); COMMENT ON FUNCTION extensions.grant_pg_cron_access IS 'Grants access to pg_cron'; -- Event trigger for pg_net @@ -94,6 +82,7 @@ BEGIN END IF; END; $$; +COMMENT ON FUNCTION extensions.grant_pg_net_access IS 'Grants access to pg_net'; DO $$ @@ -110,21 +99,9 @@ BEGIN END IF; END $$; -COMMENT ON FUNCTION extensions.grant_pg_net_access IS 'Grants access to pg_net'; -- Supabase dashboard user -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'dashboard_user' - ) - then - CREATE ROLE dashboard_user NOSUPERUSER CREATEDB CREATEROLE REPLICATION; - end if; -end -$$; - +CREATE ROLE dashboard_user NOSUPERUSER CREATEDB CREATEROLE REPLICATION; GRANT ALL ON DATABASE postgres TO dashboard_user; GRANT ALL ON SCHEMA auth TO dashboard_user; GRANT ALL ON SCHEMA extensions TO dashboard_user; diff --git a/migrations/db/migrate.sh b/migrations/db/migrate.sh index 40b5cac6b..0a84d1e6c 100755 --- a/migrations/db/migrate.sh +++ b/migrations/db/migrate.sh @@ -38,6 +38,11 @@ begin end if; end \$\$ EOSQL + # run init scripts as postgres user + for sql in "$db"/init-scripts/*.sql; do + echo "$0: running $sql" + psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -f "$sql" + done psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -c "ALTER USER supabase_admin WITH PASSWORD '$PGPASSWORD'" # run migrations as super user - postgres user demoted in post-setup for sql in "$db"/migrations/*.sql; do @@ -49,6 +54,8 @@ else create role postgres superuser login password '$PGPASSWORD'; alter database postgres owner to postgres; EOSQL + # run init scripts as postgres user + DBMATE_MIGRATIONS_DIR="$db/init-scripts" DATABASE_URL="postgres://postgres:$connect" dbmate --no-dump-schema migrate psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -c "ALTER USER supabase_admin WITH PASSWORD '$PGPASSWORD'" # run migrations as super user - postgres user demoted in post-setup DBMATE_MIGRATIONS_DIR="$db/migrations" DATABASE_URL="postgres://supabase_admin:$connect" dbmate --no-dump-schema migrate diff --git a/migrations/db/migrations/00000000000000-initial-schema.sql b/migrations/db/migrations/00000000000000-initial-schema.sql deleted file mode 100644 index c89057633..000000000 --- a/migrations/db/migrations/00000000000000-initial-schema.sql +++ /dev/null @@ -1,138 +0,0 @@ --- migrate:up - --- Set up realtime --- 1. Create publication supabase_realtime if it doesn't already exist -do $$ -begin - if not exists ( - select 1 from pg_catalog.pg_publication - where pubname = 'supabase_realtime' - ) - then - create publication supabase_realtime; - end if; -end -$$; - --- Supabase super admin -alter user supabase_admin with superuser createdb createrole replication bypassrls; - --- Supabase replication user -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'supabase_replication_admin' - ) - then - create user supabase_replication_admin with - login - replication; - end if; -end -$$; - --- Supabase read-only user -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'supabase_read_only_user' - ) - then - create role supabase_read_only_user with - login - bypassrls; - end if; -end -$$; -grant pg_read_all_data to supabase_read_only_user; - --- Extension namespacing -create schema if not exists extensions; -create extension if not exists "uuid-ossp" with schema extensions; -create extension if not exists pgcrypto with schema extensions; -create extension if not exists pgjwt with schema extensions; - --- Set up auth roles for the developer -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'anon' - ) - then - create role anon nologin noinherit; - end if; -end -$$; - --- "logged in" user: web_user, app_user, etc -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'authenticated' - ) - then - create role authenticated nologin noinherit; - end if; -end -$$; - - -- allow developers to create JWT's that bypass their policies -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'service_role' - ) - then - create role service_role nologin noinherit bypassrls; - end if; -end -$$; - -do $$ -begin - if not exists ( - select 1 from pg_roles - where rolname = 'authenticator' - ) - then - create role authenticator login noinherit; - end if; -end -$$; - - -grant anon to authenticator; -grant authenticated to authenticator; -grant service_role to authenticator; -grant supabase_admin to authenticator; - --- These are required so that the users receive grants whenever "postgres" creates tables/function -grant usage on schema public to postgres, anon, authenticated, service_role; -alter default privileges for role postgres in schema public grant all on tables to postgres, anon, authenticated, service_role; -alter default privileges for role postgres in schema public grant all on functions to postgres, anon, authenticated, service_role; -alter default privileges for role postgres in schema public grant all on sequences to postgres, anon, authenticated, service_role; - --- Allow Extensions to be used in the API -grant usage on schema extensions to postgres, anon, authenticated, service_role; - --- Set up namespacing -alter user supabase_admin SET search_path TO public, extensions; -- don't include the "auth" schema - --- These are required so that the users receive grants whenever "supabase_admin" creates tables/function -alter default privileges for user supabase_admin in schema public grant all - on sequences to postgres, anon, authenticated, service_role; -alter default privileges for user supabase_admin in schema public grant all - on tables to postgres, anon, authenticated, service_role; -alter default privileges for user supabase_admin in schema public grant all - on functions to postgres, anon, authenticated, service_role; - --- Set short statement/query timeouts for API roles -alter role anon set statement_timeout = '3s'; -alter role authenticated set statement_timeout = '8s'; - --- migrate:down diff --git a/migrations/tests/extensions/04-pg_cron.sql b/migrations/tests/extensions/04-pg_cron.sql index 111f28004..7f6686f13 100644 --- a/migrations/tests/extensions/04-pg_cron.sql +++ b/migrations/tests/extensions/04-pg_cron.sql @@ -2,6 +2,7 @@ BEGIN; -- create cron extension as supabase_admin create extension if not exists pg_cron; +-- \ir migrations/db/init-scripts/00000000000003-post-setup.sql grant usage on schema cron to postgres with grant option; alter default privileges in schema cron grant all on tables to postgres with grant option; alter default privileges in schema cron grant all on routines to postgres with grant option; diff --git a/migrations/tests/extensions/15-pg_net.sql b/migrations/tests/extensions/15-pg_net.sql index db1d6b15b..121e11e14 100644 --- a/migrations/tests/extensions/15-pg_net.sql +++ b/migrations/tests/extensions/15-pg_net.sql @@ -2,6 +2,7 @@ BEGIN; -- create net extension as supabase_admin create extension if not exists pg_net with schema "extensions"; +-- \ir migrations/db/init-scripts/00000000000003-post-setup.sql grant usage on schema net TO postgres, anon, authenticated, service_role; alter function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) security definer; alter function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) security definer; diff --git a/nix/tests/expected/evtrigs.out b/nix/tests/expected/evtrigs.out deleted file mode 100644 index 332f04c35..000000000 --- a/nix/tests/expected/evtrigs.out +++ /dev/null @@ -1,19 +0,0 @@ -select proname, proowner::regrole -from pg_proc where prorettype = 'event_trigger'::regtype -order by proname; - proname | proowner -------------------------------+---------------- - event_trigger_in | supabase_admin - grant_pg_cron_access | supabase_admin - grant_pg_graphql_access | supabase_admin - grant_pg_net_access | supabase_admin - increment_schema_version | supabase_admin - pg_tle_feature_info_sql_drop | supabase_admin - pgaudit_ddl_command_end | supabase_admin - pgaudit_sql_drop | supabase_admin - pgrst_ddl_watch | supabase_admin - pgrst_drop_watch | supabase_admin - set_graphql_placeholder | supabase_admin - trg_mask_update | supabase_admin -(12 rows) - diff --git a/nix/tests/sql/evtrigs.sql b/nix/tests/sql/evtrigs.sql deleted file mode 100644 index 1cd376b62..000000000 --- a/nix/tests/sql/evtrigs.sql +++ /dev/null @@ -1,3 +0,0 @@ -select proname, proowner::regrole -from pg_proc where prorettype = 'event_trigger'::regtype -order by proname; diff --git a/nix/tools/dbmate-tool.sh.in b/nix/tools/dbmate-tool.sh.in index ccac958ad..1197228af 100644 --- a/nix/tools/dbmate-tool.sh.in +++ b/nix/tools/dbmate-tool.sh.in @@ -243,6 +243,11 @@ EOSQL export DATABASE_URL="postgres://$PGSQL_USER:$PGPASSWORD@localhost:$PORTNO/postgres?sslmode=disable" # Export path so dbmate can find correct psql and pg_dump export PATH="$PSQLBIN:$PATH" + # Run init scripts + if ! dbmate --migrations-dir "$MIGRATIONS_DIR/init-scripts" up; then + echo "Error: Initial migration failed" + exit 1 + fi # Password update command if ! "${PSQLBIN}/psql" -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U postgres -p "$PORTNO" -h localhost -c "ALTER USER supabase_admin WITH PASSWORD '$PGPASSWORD'"; then diff --git a/nix/tools/run-server.sh.in b/nix/tools/run-server.sh.in index a799da15c..0586e010b 100644 --- a/nix/tools/run-server.sh.in +++ b/nix/tools/run-server.sh.in @@ -309,6 +309,14 @@ EOSQL 'stop_postgres' 1 fi else + # Run default init scripts + for sql in "$MIGRATIONS_DIR"/init-scripts/*.sql; do + echo "Running $sql" + if ! psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U "$PSQL_USER" -p "$PORTNO" -h localhost -f "$sql" postgres; then + 'stop_postgres' 1 + fi + done + # Set superuser password if ! psql -v ON_ERROR_STOP=1 --no-password --no-psqlrc -U "$PSQL_USER" -p "$PORTNO" -h localhost -c "ALTER USER supabase_admin WITH PASSWORD '$PGPASSWORD'"; then 'stop_postgres' 1