github.com/Redstoneguy129/cli@v0.0.0-20230211220159-15dca4e91917/internal/utils/templates/initial_schemas/README.md (about) 1 # About Initial Schemas 2 3 These SQL files represent initial schemas needed to set up the database with Supabase stuff. These need to be manually generated for each Postgres major version. Which initial schema used depends on the Docker image tag used to run the local db, which in turn depends on the CLI's `db.major_version` config. 4 5 The initial schema for PG12 is not available because the latest image (`supabase/postgres:12.5.0`) doesn't contain `wal2json`, which is required for Realtime to work. 6 7 # Why use the pg_dump output instead of running the `init.sql` directly? 8 9 Because Realtime, GoTrue, and Storage have their own migrations, and these need to be included in the initial schema for e.g. `supabase db reset` to work. 10 11 # How to Generate Initial Schemas 12 13 This is roughly what's needed to create new initial schema files for new Postgres major versions: 14 15 - Create a temporary directory 16 - Create `docker-compose.yml` (this one's for `supabase/postgres:14.1.0` - modify as needed): 17 18 ```yaml 19 services: 20 db: 21 container_name: supabase-db 22 image: supabase/postgres:14.1.0.34 23 restart: unless-stopped 24 ports: 25 - 5432:5432 26 environment: 27 POSTGRES_PASSWORD: postgres 28 volumes: 29 - ./globals.sql:/docker-entrypoint-initdb.d/globals.sql 30 - ./init.sql:/docker-entrypoint-initdb.d/init.sql 31 32 # We don't care about the correct env, we just want each services' migrations to run 33 34 auth: 35 container_name: supabase-auth 36 image: supabase/gotrue:v2.10.3 37 depends_on: 38 - db 39 restart: unless-stopped 40 environment: 41 GOTRUE_DB_DRIVER: postgres 42 GOTRUE_DB_DATABASE_URL: postgres://supabase_auth_admin:postgres@db:5432/postgres 43 GOTRUE_SITE_URL: a 44 GOTRUE_JWT_SECRET: a 45 46 realtime: 47 container_name: supabase-realtime 48 image: supabase/realtime:v1.0.0-rc.11 49 depends_on: 50 - db 51 restart: on-failure 52 environment: 53 PORT: 4000 54 DB_HOST: db 55 DB_PORT: 5432 56 DB_NAME: postgres 57 DB_USER: supabase_admin 58 DB_PASSWORD: postgres 59 DB_AFTER_CONNECT_QUERY: 'SET search_path TO _realtime' 60 DB_ENC_KEY: aaaaaaaaaaaaaaaa 61 FLY_ALLOC_ID: a 62 FLY_APP_NAME: a 63 SECRET_KEY_BASE: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 64 ERL_AFLAGS: '-proto_dist inet_tcp' 65 ENABLE_TAILSCALE: 'false' 66 DNS_NODES: a 67 command: /app/bin/realtime eval Realtime.Release.migrate 68 69 storage: 70 container_name: supabase-storage 71 image: supabase/storage-api:v0.16.6 72 depends_on: 73 - db 74 restart: unless-stopped 75 environment: 76 DATABASE_URL: postgresql://supabase_storage_admin:postgres@db:5432/postgres 77 78 ANON_KEY: a 79 SERVICE_KEY: a 80 TENANT_ID: a 81 REGION: a 82 POSTGREST_URL: a 83 GLOBAL_S3_BUCKET: a 84 PGRST_JWT_SECRET: a 85 FILE_SIZE_LIMIT: a 86 STORAGE_BACKEND: a 87 ``` 88 89 - Copy `/internal/utils/templates/globals.sql` to `./globals.sql` 90 - Create `./init.sql`: 91 92 ```plpgsql 93 -- 94 -- 00-initial-schema.sql 95 -- 96 97 -- Set up realtime 98 -- create publication supabase_realtime; -- defaults to empty publication 99 create publication supabase_realtime; 100 101 -- Supabase super admin 102 -- create user supabase_admin; 103 -- alter user supabase_admin with superuser createdb createrole replication bypassrls; 104 105 -- Extension namespacing 106 create SCHEMA IF NOT exists extensions; 107 create extension if not exists "uuid-ossp" with schema extensions; 108 create extension if not exists pgcrypto with schema extensions; 109 create extension if not exists pgjwt with schema extensions; 110 111 -- Set up auth roles for the developer 112 -- create role anon nologin noinherit; 113 -- create role authenticated nologin noinherit; -- "logged in" user: web_user, app_user, etc 114 -- create role service_role nologin noinherit bypassrls; -- allow developers to create JWT's that bypass their policies 115 116 -- create user authenticator noinherit; 117 -- grant anon to authenticator; 118 -- grant authenticated to authenticator; 119 -- grant service_role to authenticator; 120 -- grant supabase_admin to authenticator; 121 122 grant usage on schema public to postgres, anon, authenticated, service_role; 123 alter default privileges in schema public grant all on tables to postgres, anon, authenticated, service_role; 124 alter default privileges in schema public grant all on functions to postgres, anon, authenticated, service_role; 125 alter default privileges in schema public grant all on sequences to postgres, anon, authenticated, service_role; 126 127 -- Allow Extensions to be used in the API 128 grant usage on schema extensions to postgres, anon, authenticated, service_role; 129 130 -- Set up namespacing 131 -- alter user supabase_admin SET search_path TO public, extensions; -- don't include the "auth" schema 132 133 -- These are required so that the users receive grants whenever "supabase_admin" creates tables/function 134 alter default privileges for user supabase_admin in schema public grant all 135 on sequences to postgres, anon, authenticated, service_role; 136 alter default privileges for user supabase_admin in schema public grant all 137 on tables to postgres, anon, authenticated, service_role; 138 alter default privileges for user supabase_admin in schema public grant all 139 on functions to postgres, anon, authenticated, service_role; 140 141 -- Set short statement/query timeouts for API roles 142 -- alter role anon set statement_timeout = '3s'; 143 -- alter role authenticated set statement_timeout = '8s'; 144 145 -- 146 -- auth-schema.sql 147 -- 148 149 CREATE SCHEMA IF NOT EXISTS auth AUTHORIZATION supabase_admin; 150 151 -- auth.users definition 152 153 CREATE TABLE auth.users ( 154 instance_id uuid NULL, 155 id uuid NOT NULL UNIQUE, 156 aud varchar(255) NULL, 157 "role" varchar(255) NULL, 158 email varchar(255) NULL UNIQUE, 159 encrypted_password varchar(255) NULL, 160 confirmed_at timestamptz NULL, 161 invited_at timestamptz NULL, 162 confirmation_token varchar(255) NULL, 163 confirmation_sent_at timestamptz NULL, 164 recovery_token varchar(255) NULL, 165 recovery_sent_at timestamptz NULL, 166 email_change_token varchar(255) NULL, 167 email_change varchar(255) NULL, 168 email_change_sent_at timestamptz NULL, 169 last_sign_in_at timestamptz NULL, 170 raw_app_meta_data jsonb NULL, 171 raw_user_meta_data jsonb NULL, 172 is_super_admin bool NULL, 173 created_at timestamptz NULL, 174 updated_at timestamptz NULL, 175 CONSTRAINT users_pkey PRIMARY KEY (id) 176 ); 177 CREATE INDEX users_instance_id_email_idx ON auth.users USING btree (instance_id, email); 178 CREATE INDEX users_instance_id_idx ON auth.users USING btree (instance_id); 179 comment on table auth.users is 'Auth: Stores user login data within a secure schema.'; 180 181 -- auth.refresh_tokens definition 182 183 CREATE TABLE auth.refresh_tokens ( 184 instance_id uuid NULL, 185 id bigserial NOT NULL, 186 "token" varchar(255) NULL, 187 user_id varchar(255) NULL, 188 revoked bool NULL, 189 created_at timestamptz NULL, 190 updated_at timestamptz NULL, 191 CONSTRAINT refresh_tokens_pkey PRIMARY KEY (id) 192 ); 193 CREATE INDEX refresh_tokens_instance_id_idx ON auth.refresh_tokens USING btree (instance_id); 194 CREATE INDEX refresh_tokens_instance_id_user_id_idx ON auth.refresh_tokens USING btree (instance_id, user_id); 195 CREATE INDEX refresh_tokens_token_idx ON auth.refresh_tokens USING btree (token); 196 comment on table auth.refresh_tokens is 'Auth: Store of tokens used to refresh JWT tokens once they expire.'; 197 198 -- auth.instances definition 199 200 CREATE TABLE auth.instances ( 201 id uuid NOT NULL, 202 uuid uuid NULL, 203 raw_base_config text NULL, 204 created_at timestamptz NULL, 205 updated_at timestamptz NULL, 206 CONSTRAINT instances_pkey PRIMARY KEY (id) 207 ); 208 comment on table auth.instances is 'Auth: Manages users across multiple sites.'; 209 210 -- auth.audit_log_entries definition 211 212 CREATE TABLE auth.audit_log_entries ( 213 instance_id uuid NULL, 214 id uuid NOT NULL, 215 payload json NULL, 216 created_at timestamptz NULL, 217 CONSTRAINT audit_log_entries_pkey PRIMARY KEY (id) 218 ); 219 CREATE INDEX audit_logs_instance_id_idx ON auth.audit_log_entries USING btree (instance_id); 220 comment on table auth.audit_log_entries is 'Auth: Audit trail for user actions.'; 221 222 -- auth.schema_migrations definition 223 224 CREATE TABLE auth.schema_migrations ( 225 "version" varchar(255) NOT NULL, 226 CONSTRAINT schema_migrations_pkey PRIMARY KEY ("version") 227 ); 228 comment on table auth.schema_migrations is 'Auth: Manages updates to the auth system.'; 229 230 INSERT INTO auth.schema_migrations (version) 231 VALUES ('20171026211738'), 232 ('20171026211808'), 233 ('20171026211834'), 234 ('20180103212743'), 235 ('20180108183307'), 236 ('20180119214651'), 237 ('20180125194653'); 238 239 -- Gets the User ID from the request cookie 240 create or replace function auth.uid() returns uuid as $$ 241 select nullif(current_setting('request.jwt.claim.sub', true), '')::uuid; 242 $$ language sql stable; 243 244 -- Gets the User ID from the request cookie 245 create or replace function auth.role() returns text as $$ 246 select nullif(current_setting('request.jwt.claim.role', true), '')::text; 247 $$ language sql stable; 248 249 -- Gets the User email 250 create or replace function auth.email() returns text as $$ 251 select nullif(current_setting('request.jwt.claim.email', true), '')::text; 252 $$ language sql stable; 253 254 -- usage on auth functions to API roles 255 GRANT USAGE ON SCHEMA auth TO anon, authenticated, service_role; 256 257 -- Supabase super admin 258 -- CREATE USER supabase_auth_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; 259 GRANT ALL PRIVILEGES ON SCHEMA auth TO supabase_auth_admin; 260 GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA auth TO supabase_auth_admin; 261 GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA auth TO supabase_auth_admin; 262 -- ALTER USER supabase_auth_admin SET search_path = "auth"; 263 ALTER table "auth".users OWNER TO supabase_auth_admin; 264 ALTER table "auth".refresh_tokens OWNER TO supabase_auth_admin; 265 ALTER table "auth".audit_log_entries OWNER TO supabase_auth_admin; 266 ALTER table "auth".instances OWNER TO supabase_auth_admin; 267 ALTER table "auth".schema_migrations OWNER TO supabase_auth_admin; 268 269 -- 270 -- storage-schema.sql 271 -- 272 273 CREATE SCHEMA IF NOT EXISTS storage AUTHORIZATION supabase_admin; 274 275 grant usage on schema storage to postgres, anon, authenticated, service_role; 276 alter default privileges in schema storage grant all on tables to postgres, anon, authenticated, service_role; 277 alter default privileges in schema storage grant all on functions to postgres, anon, authenticated, service_role; 278 alter default privileges in schema storage grant all on sequences to postgres, anon, authenticated, service_role; 279 280 CREATE TABLE "storage"."buckets" ( 281 "id" text not NULL, 282 "name" text NOT NULL, 283 "owner" uuid, 284 "created_at" timestamptz DEFAULT now(), 285 "updated_at" timestamptz DEFAULT now(), 286 CONSTRAINT "buckets_owner_fkey" FOREIGN KEY ("owner") REFERENCES "auth"."users"("id"), 287 PRIMARY KEY ("id") 288 ); 289 CREATE UNIQUE INDEX "bname" ON "storage"."buckets" USING BTREE ("name"); 290 291 CREATE TABLE "storage"."objects" ( 292 "id" uuid NOT NULL DEFAULT extensions.uuid_generate_v4(), 293 "bucket_id" text, 294 "name" text, 295 "owner" uuid, 296 "created_at" timestamptz DEFAULT now(), 297 "updated_at" timestamptz DEFAULT now(), 298 "last_accessed_at" timestamptz DEFAULT now(), 299 "metadata" jsonb, 300 CONSTRAINT "objects_bucketId_fkey" FOREIGN KEY ("bucket_id") REFERENCES "storage"."buckets"("id"), 301 CONSTRAINT "objects_owner_fkey" FOREIGN KEY ("owner") REFERENCES "auth"."users"("id"), 302 PRIMARY KEY ("id") 303 ); 304 CREATE UNIQUE INDEX "bucketid_objname" ON "storage"."objects" USING BTREE ("bucket_id","name"); 305 CREATE INDEX name_prefix_search ON storage.objects(name text_pattern_ops); 306 307 ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY; 308 309 CREATE FUNCTION storage.foldername(name text) 310 RETURNS text[] 311 LANGUAGE plpgsql 312 AS $function$ 313 DECLARE 314 _parts text[]; 315 BEGIN 316 select string_to_array(name, '/') into _parts; 317 return _parts[1:array_length(_parts,1)-1]; 318 END 319 $function$; 320 321 CREATE FUNCTION storage.filename(name text) 322 RETURNS text 323 LANGUAGE plpgsql 324 AS $function$ 325 DECLARE 326 _parts text[]; 327 BEGIN 328 select string_to_array(name, '/') into _parts; 329 return _parts[array_length(_parts,1)]; 330 END 331 $function$; 332 333 CREATE FUNCTION storage.extension(name text) 334 RETURNS text 335 LANGUAGE plpgsql 336 AS $function$ 337 DECLARE 338 _parts text[]; 339 _filename text; 340 BEGIN 341 select string_to_array(name, '/') into _parts; 342 select _parts[array_length(_parts,1)] into _filename; 343 -- @todo return the last part instead of 2 344 return split_part(_filename, '.', 2); 345 END 346 $function$; 347 348 CREATE FUNCTION storage.search(prefix text, bucketname text, limits int DEFAULT 100, levels int DEFAULT 1, offsets int DEFAULT 0) 349 RETURNS TABLE ( 350 name text, 351 id uuid, 352 updated_at TIMESTAMPTZ, 353 created_at TIMESTAMPTZ, 354 last_accessed_at TIMESTAMPTZ, 355 metadata jsonb 356 ) 357 LANGUAGE plpgsql 358 AS $function$ 359 DECLARE 360 _bucketId text; 361 BEGIN 362 -- will be replaced by migrations when server starts 363 RAISE 'Storage Tenant not ready. Please contact Supabase Support.'; 364 END 365 $function$; 366 367 -- create migrations table 368 -- https://github.com/ThomWright/postgres-migrations/blob/master/src/migrations/0_create-migrations-table.sql 369 -- we add this table here and not let it be auto-created so that the permissions are properly applied to it 370 CREATE TABLE IF NOT EXISTS storage.migrations ( 371 id integer PRIMARY KEY, 372 name varchar(100) UNIQUE NOT NULL, 373 hash varchar(40) NOT NULL, -- sha1 hex encoded hash of the file name and contents, to ensure it hasn't been altered since applying the migration 374 executed_at timestamp DEFAULT current_timestamp 375 ); 376 377 -- CREATE USER supabase_storage_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; 378 GRANT ALL PRIVILEGES ON SCHEMA storage TO supabase_storage_admin; 379 GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA storage TO supabase_storage_admin; 380 GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA storage TO supabase_storage_admin; 381 -- ALTER USER supabase_storage_admin SET search_path = "storage"; 382 ALTER table "storage".objects owner to supabase_storage_admin; 383 ALTER table "storage".buckets owner to supabase_storage_admin; 384 ALTER table "storage".migrations OWNER TO supabase_storage_admin; 385 ALTER function "storage".foldername(text) owner to supabase_storage_admin; 386 ALTER function "storage".filename(text) owner to supabase_storage_admin; 387 ALTER function "storage".extension(text) owner to supabase_storage_admin; 388 ALTER function "storage".search(text,text,int,int,int) owner to supabase_storage_admin; 389 390 -- 391 -- post-setup.sql 392 -- 393 394 -- ALTER ROLE postgres SET search_path TO "\$user",public,extensions; 395 396 -- Trigger for pg_cron 397 CREATE OR REPLACE FUNCTION extensions.grant_pg_cron_access() 398 RETURNS event_trigger 399 LANGUAGE plpgsql 400 AS $$ 401 DECLARE 402 schema_is_cron bool; 403 BEGIN 404 schema_is_cron = ( 405 SELECT n.nspname = 'cron' 406 FROM pg_event_trigger_ddl_commands() AS ev 407 LEFT JOIN pg_catalog.pg_namespace AS n 408 ON ev.objid = n.oid 409 ); 410 411 IF schema_is_cron 412 THEN 413 grant usage on schema cron to postgres with grant option; 414 415 alter default privileges in schema cron grant all on tables to postgres with grant option; 416 alter default privileges in schema cron grant all on functions to postgres with grant option; 417 alter default privileges in schema cron grant all on sequences to postgres with grant option; 418 419 alter default privileges for user supabase_admin in schema cron grant all 420 on sequences to postgres with grant option; 421 alter default privileges for user supabase_admin in schema cron grant all 422 on tables to postgres with grant option; 423 alter default privileges for user supabase_admin in schema cron grant all 424 on functions to postgres with grant option; 425 426 grant all privileges on all tables in schema cron to postgres with grant option; 427 428 END IF; 429 430 END; 431 $$; 432 CREATE EVENT TRIGGER issue_pg_cron_access ON ddl_command_end WHEN TAG in ('CREATE SCHEMA') 433 EXECUTE PROCEDURE extensions.grant_pg_cron_access(); 434 COMMENT ON FUNCTION extensions.grant_pg_cron_access IS 'Grants access to pg_cron'; 435 436 -- Event trigger for pg_net 437 CREATE OR REPLACE FUNCTION extensions.grant_pg_net_access() 438 RETURNS event_trigger 439 LANGUAGE plpgsql 440 AS $$ 441 BEGIN 442 IF EXISTS ( 443 SELECT 1 444 FROM pg_event_trigger_ddl_commands() AS ev 445 JOIN pg_extension AS ext 446 ON ev.objid = ext.oid 447 WHERE ext.extname = 'pg_net' 448 ) 449 THEN 450 IF NOT EXISTS ( 451 SELECT 1 452 FROM pg_roles 453 WHERE rolname = 'supabase_functions_admin' 454 ) 455 THEN 456 CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; 457 END IF; 458 459 GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; 460 461 ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; 462 ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; 463 ALTER function net.http_collect_response(request_id bigint, async boolean) SECURITY DEFINER; 464 465 ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; 466 ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; 467 ALTER function net.http_collect_response(request_id bigint, async boolean) SET search_path = net; 468 469 REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; 470 REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; 471 REVOKE ALL ON FUNCTION net.http_collect_response(request_id bigint, async boolean) FROM PUBLIC; 472 473 GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; 474 GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; 475 GRANT EXECUTE ON FUNCTION net.http_collect_response(request_id bigint, async boolean) TO supabase_functions_admin, postgres, anon, authenticated, service_role; 476 END IF; 477 END; 478 $$; 479 COMMENT ON FUNCTION extensions.grant_pg_net_access IS 'Grants access to pg_net'; 480 481 DO 482 $$ 483 BEGIN 484 IF NOT EXISTS ( 485 SELECT 1 486 FROM pg_event_trigger 487 WHERE evtname = 'issue_pg_net_access' 488 ) THEN 489 CREATE EVENT TRIGGER issue_pg_net_access 490 ON ddl_command_end 491 WHEN TAG IN ('CREATE EXTENSION') 492 EXECUTE PROCEDURE extensions.grant_pg_net_access(); 493 END IF; 494 END 495 $$; 496 497 -- Supabase dashboard user 498 -- CREATE ROLE dashboard_user NOSUPERUSER CREATEDB CREATEROLE REPLICATION; 499 GRANT ALL ON DATABASE postgres TO dashboard_user; 500 GRANT ALL ON SCHEMA auth TO dashboard_user; 501 GRANT ALL ON SCHEMA extensions TO dashboard_user; 502 GRANT ALL ON SCHEMA storage TO dashboard_user; 503 GRANT ALL ON ALL TABLES IN SCHEMA auth TO dashboard_user; 504 GRANT ALL ON ALL TABLES IN SCHEMA extensions TO dashboard_user; 505 -- GRANT ALL ON ALL TABLES IN SCHEMA storage TO dashboard_user; 506 GRANT ALL ON ALL SEQUENCES IN SCHEMA auth TO dashboard_user; 507 GRANT ALL ON ALL SEQUENCES IN SCHEMA storage TO dashboard_user; 508 GRANT ALL ON ALL SEQUENCES IN SCHEMA extensions TO dashboard_user; 509 GRANT ALL ON ALL ROUTINES IN SCHEMA auth TO dashboard_user; 510 GRANT ALL ON ALL ROUTINES IN SCHEMA storage TO dashboard_user; 511 GRANT ALL ON ALL ROUTINES IN SCHEMA extensions TO dashboard_user; 512 513 -- demote postgres user 514 GRANT ALL ON DATABASE postgres TO postgres; 515 GRANT ALL ON SCHEMA auth TO postgres; 516 GRANT ALL ON SCHEMA extensions TO postgres; 517 GRANT ALL ON SCHEMA storage TO postgres; 518 GRANT ALL ON ALL TABLES IN SCHEMA auth TO postgres; 519 GRANT ALL ON ALL TABLES IN SCHEMA storage TO postgres; 520 GRANT ALL ON ALL TABLES IN SCHEMA extensions TO postgres; 521 GRANT ALL ON ALL SEQUENCES IN SCHEMA auth TO postgres; 522 GRANT ALL ON ALL SEQUENCES IN SCHEMA storage TO postgres; 523 GRANT ALL ON ALL SEQUENCES IN SCHEMA extensions TO postgres; 524 GRANT ALL ON ALL ROUTINES IN SCHEMA auth TO postgres; 525 GRANT ALL ON ALL ROUTINES IN SCHEMA storage TO postgres; 526 GRANT ALL ON ALL ROUTINES IN SCHEMA extensions TO postgres; 527 -- ALTER ROLE postgres NOSUPERUSER CREATEDB CREATEROLE LOGIN REPLICATION BYPASSRLS; 528 529 -- 530 -- Ad-hoc 531 -- 532 533 SET ROLE supabase_admin; 534 535 -- 536 -- 20211115181400-update-auth-permissions.sql 537 -- 538 539 -- update auth schema permissions 540 GRANT ALL PRIVILEGES ON SCHEMA auth TO supabase_auth_admin; 541 GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA auth TO supabase_auth_admin; 542 GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA auth TO supabase_auth_admin; 543 544 ALTER table IF EXISTS "auth".users OWNER TO supabase_auth_admin; 545 ALTER table IF EXISTS "auth".refresh_tokens OWNER TO supabase_auth_admin; 546 ALTER table IF EXISTS "auth".audit_log_entries OWNER TO supabase_auth_admin; 547 ALTER table IF EXISTS "auth".instances OWNER TO supabase_auth_admin; 548 ALTER table IF EXISTS "auth".schema_migrations OWNER TO supabase_auth_admin; 549 550 GRANT USAGE ON SCHEMA auth TO postgres; 551 GRANT ALL ON ALL TABLES IN SCHEMA auth TO postgres, dashboard_user; 552 GRANT ALL ON ALL SEQUENCES IN SCHEMA auth TO postgres, dashboard_user; 553 GRANT ALL ON ALL ROUTINES IN SCHEMA auth TO postgres, dashboard_user; 554 ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON TABLES TO postgres, dashboard_user; 555 ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON SEQUENCES TO postgres, dashboard_user; 556 ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON ROUTINES TO postgres, dashboard_user; 557 558 -- 559 -- 20211118015519-create-realtime-schema.sql 560 -- 561 562 -- create realtime schema for Realtime RLS (WALRUS) 563 CREATE SCHEMA IF NOT EXISTS realtime; 564 565 -- 566 -- 20211122051245-update-realtime-permissions.sql 567 -- 568 569 -- update realtime schema permissions 570 GRANT USAGE ON SCHEMA realtime TO postgres; 571 GRANT ALL ON ALL TABLES IN SCHEMA realtime TO postgres, dashboard_user; 572 GRANT ALL ON ALL SEQUENCES IN SCHEMA realtime TO postgres, dashboard_user; 573 GRANT ALL ON ALL ROUTINES IN SCHEMA realtime TO postgres, dashboard_user; 574 575 -- 576 -- 20211124212715-update-auth-owner.sql 577 -- 578 579 -- update owner for auth.uid, auth.role and auth.email functions 580 ALTER FUNCTION auth.uid owner to supabase_auth_admin; 581 ALTER FUNCTION auth.role owner to supabase_auth_admin; 582 ALTER FUNCTION auth.email owner to supabase_auth_admin; 583 584 -- 585 -- 20211130151719-update-realtime-permissions.sql 586 -- 587 588 -- Update future objects' permissions 589 ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON TABLES TO postgres, dashboard_user; 590 ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON SEQUENCES TO postgres, dashboard_user; 591 ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON ROUTINES TO postgres, dashboard_user; 592 593 -- 594 -- 20220118070449-enable-safeupdate-postgrest.sql 595 -- 596 597 -- ALTER ROLE authenticator SET session_preload_libraries = 'safeupdate'; 598 599 -- 600 -- 20220126121436-finer-postgrest-triggers.sql 601 -- 602 603 drop event trigger if exists api_restart; 604 drop function if exists extensions.notify_api_restart(); 605 606 -- https://postgrest.org/en/latest/schema_cache.html#finer-grained-event-trigger 607 -- watch create and alter 608 CREATE OR REPLACE FUNCTION extensions.pgrst_ddl_watch() RETURNS event_trigger AS $$ 609 DECLARE 610 cmd record; 611 BEGIN 612 FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands() 613 LOOP 614 IF cmd.command_tag IN ( 615 'CREATE SCHEMA', 'ALTER SCHEMA' 616 , 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE' 617 , 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE' 618 , 'CREATE VIEW', 'ALTER VIEW' 619 , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW' 620 , 'CREATE FUNCTION', 'ALTER FUNCTION' 621 , 'CREATE TRIGGER' 622 , 'CREATE TYPE' 623 , 'CREATE RULE' 624 , 'COMMENT' 625 ) 626 -- don't notify in case of CREATE TEMP table or other objects created on pg_temp 627 AND cmd.schema_name is distinct from 'pg_temp' 628 THEN 629 NOTIFY pgrst, 'reload schema'; 630 END IF; 631 END LOOP; 632 END; $$ LANGUAGE plpgsql; 633 634 -- watch drop 635 CREATE OR REPLACE FUNCTION extensions.pgrst_drop_watch() RETURNS event_trigger AS $$ 636 DECLARE 637 obj record; 638 BEGIN 639 FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() 640 LOOP 641 IF obj.object_type IN ( 642 'schema' 643 , 'table' 644 , 'foreign table' 645 , 'view' 646 , 'materialized view' 647 , 'function' 648 , 'trigger' 649 , 'type' 650 , 'rule' 651 ) 652 AND obj.is_temporary IS false -- no pg_temp objects 653 THEN 654 NOTIFY pgrst, 'reload schema'; 655 END IF; 656 END LOOP; 657 END; $$ LANGUAGE plpgsql; 658 659 CREATE EVENT TRIGGER pgrst_ddl_watch 660 ON ddl_command_end 661 EXECUTE PROCEDURE extensions.pgrst_ddl_watch(); 662 663 CREATE EVENT TRIGGER pgrst_drop_watch 664 ON sql_drop 665 EXECUTE PROCEDURE extensions.pgrst_drop_watch(); 666 667 -- 668 -- 20220224211803-fix-postgrest-supautils.sql 669 -- 670 671 -- ALTER ROLE authenticator SET session_preload_libraries = supautils, safeupdate; 672 673 -- 674 -- 20220317095840_pg_graphql.sql 675 -- 676 677 create schema if not exists graphql_public; 678 679 -- GraphQL Placeholder Entrypoint 680 create or replace function graphql_public.graphql( 681 "operationName" text default null, 682 query text default null, 683 variables jsonb default null, 684 extensions jsonb default null 685 ) 686 returns jsonb 687 language plpgsql 688 as $$ 689 DECLARE 690 server_version float; 691 BEGIN 692 server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float); 693 694 IF server_version >= 14 THEN 695 RETURN jsonb_build_object( 696 'data', null::jsonb, 697 'errors', array['pg_graphql extension is not enabled.'] 698 ); 699 ELSE 700 RETURN jsonb_build_object( 701 'data', null::jsonb, 702 'errors', array['pg_graphql is only available on projects running Postgres 14 onwards.'] 703 ); 704 END IF; 705 END; 706 $$; 707 708 grant usage on schema graphql_public to postgres, anon, authenticated, service_role; 709 alter default privileges in schema graphql_public grant all on tables to postgres, anon, authenticated, service_role; 710 alter default privileges in schema graphql_public grant all on functions to postgres, anon, authenticated, service_role; 711 alter default privileges in schema graphql_public grant all on sequences to postgres, anon, authenticated, service_role; 712 713 alter default privileges for user supabase_admin in schema graphql_public grant all 714 on sequences to postgres, anon, authenticated, service_role; 715 alter default privileges for user supabase_admin in schema graphql_public grant all 716 on tables to postgres, anon, authenticated, service_role; 717 alter default privileges for user supabase_admin in schema graphql_public grant all 718 on functions to postgres, anon, authenticated, service_role; 719 720 -- Trigger upon enabling pg_graphql 721 CREATE OR REPLACE FUNCTION extensions.grant_pg_graphql_access() 722 RETURNS event_trigger 723 LANGUAGE plpgsql 724 AS $func$ 725 DECLARE 726 func_is_graphql_resolve bool; 727 BEGIN 728 func_is_graphql_resolve = ( 729 SELECT n.proname = 'resolve' 730 FROM pg_event_trigger_ddl_commands() AS ev 731 LEFT JOIN pg_catalog.pg_proc AS n 732 ON ev.objid = n.oid 733 ); 734 735 IF func_is_graphql_resolve 736 THEN 737 grant usage on schema graphql to postgres, anon, authenticated, service_role; 738 grant all on function graphql.resolve to postgres, anon, authenticated, service_role; 739 740 alter default privileges in schema graphql grant all on tables to postgres, anon, authenticated, service_role; 741 alter default privileges in schema graphql grant all on functions to postgres, anon, authenticated, service_role; 742 alter default privileges in schema graphql grant all on sequences to postgres, anon, authenticated, service_role; 743 744 create or replace function graphql_public.graphql( 745 "operationName" text default null, 746 query text default null, 747 variables jsonb default null, 748 extensions jsonb default null 749 ) 750 returns jsonb 751 language sql 752 as $$ 753 SELECT graphql.resolve(query, coalesce(variables, '{}')); 754 $$; 755 756 grant select on graphql.field, graphql.type, graphql.enum_value to postgres, anon, authenticated, service_role; 757 grant execute on function graphql.resolve to postgres, anon, authenticated, service_role; 758 END IF; 759 760 END; 761 $func$; 762 763 CREATE EVENT TRIGGER issue_pg_graphql_access ON ddl_command_end WHEN TAG in ('CREATE FUNCTION') 764 EXECUTE PROCEDURE extensions.grant_pg_graphql_access(); 765 COMMENT ON FUNCTION extensions.grant_pg_graphql_access IS 'Grants access to pg_graphql'; 766 767 -- Trigger upon dropping the pg_graphql extension 768 CREATE OR REPLACE FUNCTION extensions.set_graphql_placeholder() 769 RETURNS event_trigger 770 LANGUAGE plpgsql 771 AS $func$ 772 DECLARE 773 graphql_is_dropped bool; 774 BEGIN 775 graphql_is_dropped = ( 776 SELECT ev.schema_name = 'graphql_public' 777 FROM pg_event_trigger_dropped_objects() AS ev 778 WHERE ev.schema_name = 'graphql_public' 779 ); 780 781 IF graphql_is_dropped 782 THEN 783 create or replace function graphql_public.graphql( 784 "operationName" text default null, 785 query text default null, 786 variables jsonb default null, 787 extensions jsonb default null 788 ) 789 returns jsonb 790 language plpgsql 791 as $$ 792 DECLARE 793 server_version float; 794 BEGIN 795 server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float); 796 797 IF server_version >= 14 THEN 798 RETURN jsonb_build_object( 799 'data', null::jsonb, 800 'errors', array['pg_graphql extension is not enabled.'] 801 ); 802 ELSE 803 RETURN jsonb_build_object( 804 'data', null::jsonb, 805 'errors', array['pg_graphql is only available on projects running Postgres 14 onwards.'] 806 ); 807 END IF; 808 END; 809 $$; 810 END IF; 811 812 END; 813 $func$; 814 815 CREATE EVENT TRIGGER issue_graphql_placeholder ON sql_drop WHEN TAG in ('DROP EXTENSION') 816 EXECUTE PROCEDURE extensions.set_graphql_placeholder(); 817 COMMENT ON FUNCTION extensions.set_graphql_placeholder IS 'Reintroduces placeholder function for graphql_public.graphql'; 818 819 -- 820 -- 20220321174452-fix-postgrest-alter-type-event-trigger.sql 821 -- 822 823 drop event trigger if exists api_restart; 824 drop function if exists extensions.notify_api_restart(); 825 826 -- https://postgrest.org/en/latest/schema_cache.html#finer-grained-event-trigger 827 -- watch create and alter 828 CREATE OR REPLACE FUNCTION extensions.pgrst_ddl_watch() RETURNS event_trigger AS $$ 829 DECLARE 830 cmd record; 831 BEGIN 832 FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands() 833 LOOP 834 IF cmd.command_tag IN ( 835 'CREATE SCHEMA', 'ALTER SCHEMA' 836 , 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE' 837 , 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE' 838 , 'CREATE VIEW', 'ALTER VIEW' 839 , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW' 840 , 'CREATE FUNCTION', 'ALTER FUNCTION' 841 , 'CREATE TRIGGER' 842 , 'CREATE TYPE', 'ALTER TYPE' 843 , 'CREATE RULE' 844 , 'COMMENT' 845 ) 846 -- don't notify in case of CREATE TEMP table or other objects created on pg_temp 847 AND cmd.schema_name is distinct from 'pg_temp' 848 THEN 849 NOTIFY pgrst, 'reload schema'; 850 END IF; 851 END LOOP; 852 END; $$ LANGUAGE plpgsql; 853 854 -- watch drop 855 CREATE OR REPLACE FUNCTION extensions.pgrst_drop_watch() RETURNS event_trigger AS $$ 856 DECLARE 857 obj record; 858 BEGIN 859 FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() 860 LOOP 861 IF obj.object_type IN ( 862 'schema' 863 , 'table' 864 , 'foreign table' 865 , 'view' 866 , 'materialized view' 867 , 'function' 868 , 'trigger' 869 , 'type' 870 , 'rule' 871 ) 872 AND obj.is_temporary IS false -- no pg_temp objects 873 THEN 874 NOTIFY pgrst, 'reload schema'; 875 END IF; 876 END LOOP; 877 END; $$ LANGUAGE plpgsql; 878 879 -- CREATE EVENT TRIGGER pgrst_ddl_watch 880 -- ON ddl_command_end 881 -- EXECUTE PROCEDURE extensions.pgrst_ddl_watch(); 882 883 -- CREATE EVENT TRIGGER pgrst_drop_watch 884 -- ON sql_drop 885 -- EXECUTE PROCEDURE extensions.pgrst_drop_watch(); 886 887 -- 888 -- 20220322085208_gotrue_session_limit.sql 889 -- 890 891 -- ALTER ROLE supabase_auth_admin SET idle_in_transaction_session_timeout TO 60000; 892 893 -- 894 -- 20220404205710-pg_graphql-on-by-default.sql 895 -- 896 897 -- Update Trigger upon enabling pg_graphql 898 create or replace function extensions.grant_pg_graphql_access() 899 returns event_trigger 900 language plpgsql 901 AS $func$ 902 DECLARE 903 func_is_graphql_resolve bool; 904 BEGIN 905 func_is_graphql_resolve = ( 906 SELECT n.proname = 'resolve' 907 FROM pg_event_trigger_ddl_commands() AS ev 908 LEFT JOIN pg_catalog.pg_proc AS n 909 ON ev.objid = n.oid 910 ); 911 912 IF func_is_graphql_resolve 913 THEN 914 grant usage on schema graphql to postgres, anon, authenticated, service_role; 915 grant all on function graphql.resolve to postgres, anon, authenticated, service_role; 916 917 alter default privileges in schema graphql grant all on tables to postgres, anon, authenticated, service_role; 918 alter default privileges in schema graphql grant all on functions to postgres, anon, authenticated, service_role; 919 alter default privileges in schema graphql grant all on sequences to postgres, anon, authenticated, service_role; 920 921 -- Update public wrapper to pass all arguments through to the pg_graphql resolve func 922 create or replace function graphql_public.graphql( 923 "operationName" text default null, 924 query text default null, 925 variables jsonb default null, 926 extensions jsonb default null 927 ) 928 returns jsonb 929 language sql 930 as $$ 931 -- This changed 932 select graphql.resolve( 933 query := query, 934 variables := coalesce(variables, '{}'), 935 "operationName" := "operationName", 936 extensions := extensions 937 ); 938 $$; 939 940 grant select on graphql.field, graphql.type, graphql.enum_value to postgres, anon, authenticated, service_role; 941 grant execute on function graphql.resolve to postgres, anon, authenticated, service_role; 942 END IF; 943 944 END; 945 $func$; 946 947 CREATE OR REPLACE FUNCTION extensions.set_graphql_placeholder() 948 RETURNS event_trigger 949 LANGUAGE plpgsql 950 AS $func$ 951 DECLARE 952 graphql_is_dropped bool; 953 BEGIN 954 graphql_is_dropped = ( 955 SELECT ev.schema_name = 'graphql_public' 956 FROM pg_event_trigger_dropped_objects() AS ev 957 WHERE ev.schema_name = 'graphql_public' 958 ); 959 960 IF graphql_is_dropped 961 THEN 962 create or replace function graphql_public.graphql( 963 "operationName" text default null, 964 query text default null, 965 variables jsonb default null, 966 extensions jsonb default null 967 ) 968 returns jsonb 969 language plpgsql 970 as $$ 971 DECLARE 972 server_version float; 973 BEGIN 974 server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float); 975 976 IF server_version >= 14 THEN 977 RETURN jsonb_build_object( 978 'errors', jsonb_build_array( 979 jsonb_build_object( 980 'message', 'pg_graphql extension is not enabled.' 981 ) 982 ) 983 ); 984 ELSE 985 RETURN jsonb_build_object( 986 'errors', jsonb_build_array( 987 jsonb_build_object( 988 'message', 'pg_graphql is only available on projects running Postgres 14 onwards.' 989 ) 990 ) 991 ); 992 END IF; 993 END; 994 $$; 995 END IF; 996 997 END; 998 $func$; 999 1000 -- GraphQL Placeholder Entrypoint 1001 create or replace function graphql_public.graphql( 1002 "operationName" text default null, 1003 query text default null, 1004 variables jsonb default null, 1005 extensions jsonb default null 1006 ) 1007 returns jsonb 1008 language plpgsql 1009 as $$ 1010 DECLARE 1011 server_version float; 1012 BEGIN 1013 server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float); 1014 1015 IF server_version >= 14 THEN 1016 RETURN jsonb_build_object( 1017 'errors', jsonb_build_array( 1018 jsonb_build_object( 1019 'message', 'pg_graphql extension is not enabled.' 1020 ) 1021 ) 1022 ); 1023 ELSE 1024 RETURN jsonb_build_object( 1025 'errors', jsonb_build_array( 1026 jsonb_build_object( 1027 'message', 'pg_graphql is only available on projects running Postgres 14 onwards.' 1028 ) 1029 ) 1030 ); 1031 END IF; 1032 END; 1033 $$; 1034 1035 1036 drop extension if exists pg_graphql; 1037 -- Avoids limitation of only being able to load the extension via dashboard 1038 -- Only install as well if the extension is actually installed 1039 DO $$ 1040 DECLARE 1041 graphql_exists boolean; 1042 BEGIN 1043 graphql_exists = ( 1044 select count(*) = 1 1045 from pg_available_extensions 1046 where name = 'pg_graphql' 1047 ); 1048 1049 IF graphql_exists 1050 THEN 1051 create extension if not exists pg_graphql; 1052 END IF; 1053 END $$; 1054 1055 -- 1056 -- 20220609081115-grant-supabase-auth-admin-and-supabase-storage-admin-to-postgres.sql 1057 -- 1058 1059 -- grant supabase_auth_admin, supabase_storage_admin to postgres; 1060 1061 -- 1062 -- 20220613123923-pg_graphql-pg-dump-perms.sql 1063 -- 1064 1065 create or replace function extensions.grant_pg_graphql_access() 1066 returns event_trigger 1067 language plpgsql 1068 AS $func$ 1069 DECLARE 1070 func_is_graphql_resolve bool; 1071 BEGIN 1072 func_is_graphql_resolve = ( 1073 SELECT n.proname = 'resolve' 1074 FROM pg_event_trigger_ddl_commands() AS ev 1075 LEFT JOIN pg_catalog.pg_proc AS n 1076 ON ev.objid = n.oid 1077 ); 1078 1079 IF func_is_graphql_resolve 1080 THEN 1081 1082 -- Update public wrapper to pass all arguments through to the pg_graphql resolve func 1083 create or replace function graphql_public.graphql( 1084 "operationName" text default null, 1085 query text default null, 1086 variables jsonb default null, 1087 extensions jsonb default null 1088 ) 1089 returns jsonb 1090 language sql 1091 as $$ 1092 select graphql.resolve( 1093 query := query, 1094 variables := coalesce(variables, '{}'), 1095 "operationName" := "operationName", 1096 extensions := extensions 1097 ); 1098 $$; 1099 1100 -- This hook executes when `graphql.resolve` is created. That is not necessarily the last 1101 -- function in the extension so we need to grant permissions on existing entities AND 1102 -- update default permissions to any others that are created after `graphql.resolve` 1103 grant usage on schema graphql to postgres, anon, authenticated, service_role; 1104 grant select on all tables in schema graphql to postgres, anon, authenticated, service_role; 1105 grant execute on all functions in schema graphql to postgres, anon, authenticated, service_role; 1106 grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role; 1107 alter default privileges in schema graphql grant all on tables to postgres, anon, authenticated, service_role; 1108 alter default privileges in schema graphql grant all on functions to postgres, anon, authenticated, service_role; 1109 alter default privileges in schema graphql grant all on sequences to postgres, anon, authenticated, service_role; 1110 END IF; 1111 1112 END; 1113 $func$; 1114 1115 -- Cycle the extension off and back on to apply the permissions update. 1116 1117 drop extension if exists pg_graphql; 1118 -- Avoids limitation of only being able to load the extension via dashboard 1119 -- Only install as well if the extension is actually installed 1120 DO $$ 1121 DECLARE 1122 graphql_exists boolean; 1123 BEGIN 1124 graphql_exists = ( 1125 select count(*) = 1 1126 from pg_available_extensions 1127 where name = 'pg_graphql' 1128 ); 1129 1130 IF graphql_exists 1131 THEN 1132 create extension if not exists pg_graphql schema extensions; 1133 END IF; 1134 END $$; 1135 1136 -- 1137 -- 20220713082019_pg_cron_pg_net_temp_perms_fix.sql 1138 -- 1139 1140 DO $$ 1141 DECLARE 1142 pg_cron_installed boolean; 1143 BEGIN 1144 -- checks if pg_cron is enabled 1145 pg_cron_installed = ( 1146 select count(*) = 1 1147 from pg_available_extensions 1148 where name = 'pg_cron' 1149 and installed_version is not null 1150 ); 1151 1152 IF pg_cron_installed 1153 THEN 1154 grant usage on schema cron to postgres with grant option; 1155 1156 alter default privileges in schema cron grant all on tables to postgres with grant option; 1157 alter default privileges in schema cron grant all on functions to postgres with grant option; 1158 alter default privileges in schema cron grant all on sequences to postgres with grant option; 1159 1160 alter default privileges for user supabase_admin in schema cron grant all 1161 on sequences to postgres with grant option; 1162 alter default privileges for user supabase_admin in schema cron grant all 1163 on tables to postgres with grant option; 1164 alter default privileges for user supabase_admin in schema cron grant all 1165 on functions to postgres with grant option; 1166 1167 grant all privileges on all tables in schema cron to postgres with grant option; 1168 END IF; 1169 END $$; 1170 1171 DO $$ 1172 DECLARE 1173 pg_net_installed boolean; 1174 BEGIN 1175 -- checks if pg_net is enabled 1176 pg_net_installed = ( 1177 select count(*) = 1 1178 from pg_available_extensions 1179 where name = 'pg_net' 1180 and installed_version is not null 1181 1182 ); 1183 1184 IF pg_net_installed 1185 THEN 1186 IF NOT EXISTS ( 1187 SELECT 1 1188 FROM pg_roles 1189 WHERE rolname = 'supabase_functions_admin' 1190 ) 1191 THEN 1192 CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; 1193 END IF; 1194 1195 GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; 1196 1197 ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; 1198 ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; 1199 ALTER function net.http_collect_response(request_id bigint, async boolean) SECURITY DEFINER; 1200 1201 ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; 1202 ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; 1203 ALTER function net.http_collect_response(request_id bigint, async boolean) SET search_path = net; 1204 1205 REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; 1206 REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; 1207 REVOKE ALL ON FUNCTION net.http_collect_response(request_id bigint, async boolean) FROM PUBLIC; 1208 1209 GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; 1210 GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; 1211 GRANT EXECUTE ON FUNCTION net.http_collect_response(request_id bigint, async boolean) TO supabase_functions_admin, postgres, anon, authenticated, service_role; 1212 END IF; 1213 END $$; 1214 ``` 1215 1216 - Run `docker compose up -d` 1217 - Once all migrations are finished, run `pg_dump --inserts --dbname 'postgresql://postgres:postgres@localhost:5432/postgres' > initial_schema.sql` 1218 - Comment out lines that start with `GRANT ALL ON FUNCTION graphql_public` 1219 - Add `drop extension pg_graphql; create extension pg_graphql schema extensions;` at the end 1220 - You're done!