Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/db/reset/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func resetDatabase15(ctx context.Context, version string, fsys afero.Fs, options
}

func initDatabase(ctx context.Context, options ...func(*pgx.ConnConfig)) error {
conn, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{User: "supabase_admin"}, options...)
conn, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{User: utils.SUPERUSER_ROLE}, options...)
if err != nil {
return err
}
Expand All @@ -152,7 +152,7 @@ func initDatabase(ctx context.Context, options ...func(*pgx.ConnConfig)) error {

// Recreate postgres database by connecting to template1
func recreateDatabase(ctx context.Context, options ...func(*pgx.ConnConfig)) error {
conn, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{User: "supabase_admin", Database: "template1"}, options...)
conn, err := utils.ConnectLocalPostgres(ctx, pgconn.Config{User: utils.SUPERUSER_ROLE, Database: "template1"}, options...)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/db/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func initRealtimeJob(host string) utils.DockerJob {
"PORT=4000",
"DB_HOST=" + host,
"DB_PORT=5432",
"DB_USER=supabase_admin",
"DB_USER=" + utils.SUPERUSER_ROLE,
"DB_PASSWORD=" + utils.Config.Db.Password,
"DB_NAME=postgres",
"DB_AFTER_CONNECT_QUERY=SET search_path TO _realtime",
Expand Down
5 changes: 2 additions & 3 deletions internal/link/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/supabase/cli/pkg/api"
"github.com/supabase/cli/pkg/migration"
"github.com/supabase/cli/pkg/pgtest"
"github.com/supabase/cli/pkg/pgxv5"
"github.com/zalando/go-keyring"
)

Expand All @@ -48,7 +47,7 @@ func TestLinkCommand(t *testing.T) {
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(pgxv5.SET_SESSION_ROLE).
conn.Query(utils.SET_SESSION_ROLE).
Reply("SET ROLE").
Query(GET_LATEST_STORAGE_MIGRATION).
Reply("SELECT 1", []interface{}{"custom-metadata"})
Expand Down Expand Up @@ -198,7 +197,7 @@ func TestLinkCommand(t *testing.T) {
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(pgxv5.SET_SESSION_ROLE).
conn.Query(utils.SET_SESSION_ROLE).
Reply("SET ROLE").
Query(GET_LATEST_STORAGE_MIGRATION).
Reply("SELECT 1", []interface{}{"custom-metadata"})
Expand Down
4 changes: 2 additions & 2 deletions internal/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func run(ctx context.Context, fsys afero.Fs, excludedContainers []string, dbConf
"DB_HOSTNAME=" + dbConfig.Host,
fmt.Sprintf("DB_PORT=%d", dbConfig.Port),
"DB_SCHEMA=_analytics",
"DB_USERNAME=supabase_admin",
"DB_USERNAME=" + utils.SUPERUSER_ROLE,
"DB_PASSWORD=" + dbConfig.Password,
"LOGFLARE_MIN_CLUSTER_SIZE=1",
"LOGFLARE_SINGLE_TENANT=true",
Expand Down Expand Up @@ -791,7 +791,7 @@ EOF
"PORT=4000",
"DB_HOST=" + dbConfig.Host,
fmt.Sprintf("DB_PORT=%d", dbConfig.Port),
"DB_USER=supabase_admin",
"DB_USER=" + utils.SUPERUSER_ROLE,
"DB_PASSWORD=" + dbConfig.Password,
"DB_NAME=" + dbConfig.Database,
"DB_AFTER_CONNECT_QUERY=SET search_path TO _realtime",
Expand Down
13 changes: 13 additions & 0 deletions internal/utils/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ func ConnectByUrl(ctx context.Context, url string, options ...func(*pgx.ConnConf
return pgxv5.Connect(ctx, url, options...)
}

const (
SUPERUSER_ROLE = "supabase_admin"
CLI_LOGIN_PREFIX = "cli_login_"
SET_SESSION_ROLE = "SET SESSION ROLE postgres"
)

func ConnectByConfigStream(ctx context.Context, config pgconn.Config, w io.Writer, options ...func(*pgx.ConnConfig)) (*pgx.Conn, error) {
if IsLocalDatabase(config) {
fmt.Fprintln(w, "Connecting to local database...")
Expand All @@ -160,6 +166,13 @@ func ConnectByConfigStream(ctx context.Context, config pgconn.Config, w io.Write
if DNSResolver.Value == DNS_OVER_HTTPS {
cc.LookupFunc = FallbackLookupIP
}
// Step down from platform provisioned login roles or privileged roles
if user := strings.Split(cc.User, ".")[0]; strings.EqualFold(user, SUPERUSER_ROLE) ||
strings.HasPrefix(user, CLI_LOGIN_PREFIX) {
cc.AfterConnect = func(ctx context.Context, pgconn *pgconn.PgConn) error {
return pgconn.Exec(ctx, SET_SESSION_ROLE).Close()
}
}
})
return ConnectByUrl(ctx, ToPostgresURL(config), opts...)
}
Expand Down
11 changes: 11 additions & 0 deletions pkg/migration/queries/drop.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ begin
-- If an extension uses a schema it doesn't create, dropping the schema will cascade to also
-- drop the extension. But if an extension creates its own schema, dropping the schema will
-- throw an error. Hence, we drop schemas first while excluding those created by extensions.
raise notice 'dropping schema: %', rec.nspname;
execute format('drop schema if exists %I cascade', rec.nspname);
end loop;

Expand All @@ -22,6 +23,7 @@ begin
from pg_extension p
where p.extname not in ('pg_graphql', 'pg_net', 'pg_stat_statements', 'pgcrypto', 'pgjwt', 'pgsodium', 'plpgsql', 'supabase_vault', 'uuid-ossp')
loop
raise notice 'dropping extension: %', rec.extname;
execute format('drop extension if exists %I cascade', rec.extname);
end loop;

Expand All @@ -32,6 +34,7 @@ begin
where p.pronamespace::regnamespace::name = 'public'
loop
-- supports aggregate, function, and procedure
raise notice 'dropping function: %.%', rec.pronamespace::regnamespace::name, rec.proname;
execute format('drop routine if exists %I.%I(%s) cascade', rec.pronamespace::regnamespace::name, rec.proname, pg_catalog.pg_get_function_identity_arguments(rec.oid));
end loop;

Expand All @@ -43,6 +46,7 @@ begin
c.relnamespace::regnamespace::name = 'public'
and c.relkind = 'v'
loop
raise notice 'dropping view: %.%', rec.relnamespace::regnamespace::name, rec.relname;
execute format('drop view if exists %I.%I cascade', rec.relnamespace::regnamespace::name, rec.relname);
end loop;

Expand All @@ -54,6 +58,7 @@ begin
c.relnamespace::regnamespace::name = 'public'
and c.relkind = 'm'
loop
raise notice 'dropping materialized view: %.%', rec.relnamespace::regnamespace::name, rec.relname;
execute format('drop materialized view if exists %I.%I cascade', rec.relnamespace::regnamespace::name, rec.relname);
end loop;

Expand All @@ -67,6 +72,7 @@ begin
order by c.relkind desc
loop
-- supports all table like relations, except views, complex types, and sequences
raise notice 'dropping table: %.%', rec.relnamespace::regnamespace::name, rec.relname;
execute format('drop table if exists %I.%I cascade', rec.relnamespace::regnamespace::name, rec.relname);
end loop;

Expand All @@ -80,6 +86,7 @@ begin
or c.relnamespace::regnamespace::name = 'supabase_migrations')
and c.relkind = 'r'
loop
raise notice 'truncating table: %.%', rec.relnamespace::regnamespace::name, rec.relname;
execute format('truncate %I.%I cascade', rec.relnamespace::regnamespace::name, rec.relname);
end loop;

Expand All @@ -91,6 +98,7 @@ begin
c.relnamespace::regnamespace::name = 'public'
and c.relkind = 's'
loop
raise notice 'dropping sequence: %.%', rec.relnamespace::regnamespace::name, rec.relname;
execute format('drop sequence if exists %I.%I cascade', rec.relnamespace::regnamespace::name, rec.relname);
end loop;

Expand All @@ -102,6 +110,7 @@ begin
t.typnamespace::regnamespace::name = 'public'
and typtype != 'b'
loop
raise notice 'dropping type: %.%', rec.typnamespace::regnamespace::name, rec.typname;
execute format('drop type if exists %I.%I cascade', rec.typnamespace::regnamespace::name, rec.typname);
end loop;

Expand All @@ -110,6 +119,7 @@ begin
select *
from pg_policies p
loop
raise notice 'dropping policy: %', rec.policyname;
execute format('drop policy if exists %I on %I.%I cascade', rec.policyname, rec.schemaname, rec.tablename);
end loop;

Expand All @@ -120,6 +130,7 @@ begin
where
not p.pubname like any(array['supabase\_realtime%', 'realtime\_messages%'])
loop
raise notice 'dropping publication: %', rec.pubname;
execute format('drop publication if exists %I', rec.pubname);
end loop;
end $$;
10 changes: 0 additions & 10 deletions pkg/pgxv5/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import (
"github.com/jackc/pgx/v4"
)

const (
CLI_LOGIN_PREFIX = "cli_login_"
SET_SESSION_ROLE = "SET SESSION ROLE postgres"
)

// Extends pgx.Connect with support for programmatically overriding parsed config
func Connect(ctx context.Context, connString string, options ...func(*pgx.ConnConfig)) (*pgx.Conn, error) {
// Parse connection url
Expand All @@ -28,11 +23,6 @@ func Connect(ctx context.Context, connString string, options ...func(*pgx.ConnCo
fmt.Fprintf(os.Stderr, "%s (%s): %s\n", n.Severity, n.Code, n.Message)
}
}
if strings.HasPrefix(config.User, CLI_LOGIN_PREFIX) {
config.AfterConnect = func(ctx context.Context, pgconn *pgconn.PgConn) error {
return pgconn.Exec(ctx, SET_SESSION_ROLE).Close()
}
}
// Apply config overrides
for _, op := range options {
op(config)
Expand Down