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!