Skip to content
Draft
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
67 changes: 39 additions & 28 deletions packages/core/src/init/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,42 +69,53 @@ DECLARE
v_username TEXT := '${username.replace(/'/g, "''")}';
v_password TEXT := '${password.replace(/'/g, "''")}';
BEGIN
BEGIN
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', v_username, v_password);
EXCEPTION
WHEN duplicate_object THEN
-- Role already exists; optionally sync attributes here with ALTER ROLE
NULL;
END;
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = v_username) THEN
BEGIN
PERFORM pg_advisory_xact_lock(42, hashtext(v_username));
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', v_username, v_password);
EXCEPTION
WHEN duplicate_object OR unique_violation THEN
NULL;
END;
END IF;
END
$do$;

-- Robust GRANTs under concurrency: GRANT can race on pg_auth_members unique index.
-- Catch unique_violation (23505) and continue so CI/CD concurrent jobs don't fail.
DO $do$
DECLARE
v_username TEXT := '${username.replace(/'/g, "''")}';
BEGIN
BEGIN
EXECUTE format('GRANT %I TO %I', 'anonymous', v_username);
EXCEPTION
WHEN unique_violation THEN
-- Membership was granted concurrently; ignore.
NULL;
WHEN undefined_object THEN
-- One of the roles doesn't exist yet; order operations as needed.
RAISE NOTICE 'Missing role when granting % to %', 'anonymous', v_username;
END;
IF NOT EXISTS (
SELECT 1 FROM pg_auth_members am
JOIN pg_roles r1 ON am.roleid = r1.oid
JOIN pg_roles r2 ON am.member = r2.oid
WHERE r1.rolname = 'anonymous' AND r2.rolname = v_username
) THEN
BEGIN
EXECUTE format('GRANT %I TO %I', 'anonymous', v_username);
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'anonymous', v_username;
END;
END IF;

BEGIN
EXECUTE format('GRANT %I TO %I', 'authenticated', v_username);
EXCEPTION
WHEN unique_violation THEN
-- Membership was granted concurrently; ignore.
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'authenticated', v_username;
END;
IF NOT EXISTS (
SELECT 1 FROM pg_auth_members am
JOIN pg_roles r1 ON am.roleid = r1.oid
JOIN pg_roles r2 ON am.member = r2.oid
WHERE r1.rolname = 'authenticated' AND r2.rolname = v_username
) THEN
BEGIN
EXECUTE format('GRANT %I TO %I', 'authenticated', v_username);
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'authenticated', v_username;
END;
END IF;
END
$do$;
COMMIT;
Expand Down
53 changes: 28 additions & 25 deletions packages/core/src/init/sql/bootstrap-roles.sql
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
BEGIN;
DO $do$
BEGIN
-- anonymous
BEGIN
EXECUTE format('CREATE ROLE %I', 'anonymous');
EXCEPTION
WHEN duplicate_object THEN
-- Role already exists; optionally sync attributes here with ALTER ROLE
NULL;
END;
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'anonymous') THEN
BEGIN
PERFORM pg_advisory_xact_lock(42, hashtext('anonymous'));
EXECUTE format('CREATE ROLE %I', 'anonymous');
EXCEPTION
WHEN duplicate_object OR unique_violation THEN
NULL;
END;
END IF;

-- authenticated
BEGIN
EXECUTE format('CREATE ROLE %I', 'authenticated');
EXCEPTION
WHEN duplicate_object THEN
-- Role already exists; optionally sync attributes here with ALTER ROLE
NULL;
END;
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'authenticated') THEN
BEGIN
PERFORM pg_advisory_xact_lock(42, hashtext('authenticated'));
EXECUTE format('CREATE ROLE %I', 'authenticated');
EXCEPTION
WHEN duplicate_object OR unique_violation THEN
NULL;
END;
END IF;

-- administrator
BEGIN
EXECUTE format('CREATE ROLE %I', 'administrator');
EXCEPTION
WHEN duplicate_object THEN
-- Role already exists; optionally sync attributes here with ALTER ROLE
NULL;
END;
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'administrator') THEN
BEGIN
PERFORM pg_advisory_xact_lock(42, hashtext('administrator'));
EXECUTE format('CREATE ROLE %I', 'administrator');
EXCEPTION
WHEN duplicate_object OR unique_violation THEN
NULL;
END;
END IF;
END
$do$;

Expand All @@ -52,4 +55,4 @@ ALTER USER administrator WITH NOLOGIN;
ALTER USER administrator WITH NOREPLICATION;
-- they CAN bypass RLS
ALTER USER administrator WITH BYPASSRLS;
COMMIT;
COMMIT;
149 changes: 93 additions & 56 deletions packages/core/src/init/sql/bootstrap-test-roles.sql
Original file line number Diff line number Diff line change
@@ -1,72 +1,109 @@
BEGIN;
DO $do$
BEGIN
BEGIN
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', 'app_user', 'app_password');
EXCEPTION
WHEN duplicate_object THEN
-- Role already exists; optionally sync attributes here with ALTER ROLE
NULL;
END;
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'app_user') THEN
BEGIN
PERFORM pg_advisory_xact_lock(42, hashtext('app_user'));
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', 'app_user', 'app_password');
EXCEPTION
WHEN duplicate_object OR unique_violation THEN
NULL;
END;
END IF;

BEGIN
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', 'app_admin', 'admin_password');
EXCEPTION
WHEN duplicate_object THEN
-- Role already exists; optionally sync attributes here with ALTER ROLE
NULL;
END;
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = 'app_admin') THEN
BEGIN
PERFORM pg_advisory_xact_lock(42, hashtext('app_admin'));
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', 'app_admin', 'admin_password');
EXCEPTION
WHEN duplicate_object OR unique_violation THEN
NULL;
END;
END IF;
END
$do$;

DO $do$
BEGIN
BEGIN
EXECUTE format('GRANT %I TO %I', 'anonymous', 'app_user');
EXCEPTION
WHEN unique_violation THEN
-- Membership was granted concurrently; ignore.
NULL;
WHEN undefined_object THEN
-- One of the roles doesn't exist yet; order operations as needed.
RAISE NOTICE 'Missing role when granting % to %', 'anonymous', 'app_user';
END;
IF NOT EXISTS (
SELECT 1 FROM pg_auth_members am
JOIN pg_roles r1 ON am.roleid = r1.oid
JOIN pg_roles r2 ON am.member = r2.oid
WHERE r1.rolname = 'anonymous' AND r2.rolname = 'app_user'
) THEN
BEGIN
EXECUTE format('GRANT %I TO %I', 'anonymous', 'app_user');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'anonymous', 'app_user';
END;
END IF;

BEGIN
EXECUTE format('GRANT %I TO %I', 'authenticated', 'app_user');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'authenticated', 'app_user';
END;
IF NOT EXISTS (
SELECT 1 FROM pg_auth_members am
JOIN pg_roles r1 ON am.roleid = r1.oid
JOIN pg_roles r2 ON am.member = r2.oid
WHERE r1.rolname = 'authenticated' AND r2.rolname = 'app_user'
) THEN
BEGIN
EXECUTE format('GRANT %I TO %I', 'authenticated', 'app_user');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'authenticated', 'app_user';
END;
END IF;

BEGIN
EXECUTE format('GRANT %I TO %I', 'anonymous', 'administrator');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'anonymous', 'administrator';
END;
IF NOT EXISTS (
SELECT 1 FROM pg_auth_members am
JOIN pg_roles r1 ON am.roleid = r1.oid
JOIN pg_roles r2 ON am.member = r2.oid
WHERE r1.rolname = 'anonymous' AND r2.rolname = 'administrator'
) THEN
BEGIN
EXECUTE format('GRANT %I TO %I', 'anonymous', 'administrator');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'anonymous', 'administrator';
END;
END IF;

BEGIN
EXECUTE format('GRANT %I TO %I', 'authenticated', 'administrator');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'authenticated', 'administrator';
END;
IF NOT EXISTS (
SELECT 1 FROM pg_auth_members am
JOIN pg_roles r1 ON am.roleid = r1.oid
JOIN pg_roles r2 ON am.member = r2.oid
WHERE r1.rolname = 'authenticated' AND r2.rolname = 'administrator'
) THEN
BEGIN
EXECUTE format('GRANT %I TO %I', 'authenticated', 'administrator');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'authenticated', 'administrator';
END;
END IF;

BEGIN
EXECUTE format('GRANT %I TO %I', 'administrator', 'app_admin');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'administrator', 'app_admin';
END;
IF NOT EXISTS (
SELECT 1 FROM pg_auth_members am
JOIN pg_roles r1 ON am.roleid = r1.oid
JOIN pg_roles r2 ON am.member = r2.oid
WHERE r1.rolname = 'administrator' AND r2.rolname = 'app_admin'
) THEN
BEGIN
EXECUTE format('GRANT %I TO %I', 'administrator', 'app_admin');
EXCEPTION
WHEN unique_violation THEN
NULL;
WHEN undefined_object THEN
RAISE NOTICE 'Missing role when granting % to %', 'administrator', 'app_admin';
END;
END IF;
END
$do$;
COMMIT;
17 changes: 9 additions & 8 deletions packages/pgsql-test/src/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,15 @@ $$;
v_user TEXT := '${user.replace(/'/g, "''")}';
v_password TEXT := '${password.replace(/'/g, "''")}';
BEGIN
-- Create role if it doesn't exist
BEGIN
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', v_user, v_password);
EXCEPTION
WHEN duplicate_object THEN
-- Role already exists; optionally sync attributes here with ALTER ROLE
NULL;
END;
IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = v_user) THEN
BEGIN
PERFORM pg_advisory_xact_lock(42, hashtext(v_user));
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', v_user, v_password);
EXCEPTION
WHEN duplicate_object OR unique_violation THEN
NULL;
END;
END IF;

-- CI/CD concurrency note: GRANT role membership can race on pg_auth_members unique index
-- We pre-check membership and still catch unique_violation to handle TOCTOU safely.
Expand Down