Skip to content

Commit b66b6b0

Browse files
committed
chore(db): regenerate SSO migration after staging
1 parent 515526a commit b66b6b0

3 files changed

Lines changed: 25944 additions & 0 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
-- An organization may run several identity providers, but sign-in routes by email domain, so
2+
-- each of its domains must name exactly one provider. The registration route checks this before
3+
-- writing, but that check is a plain read: two concurrent registrations with different provider
4+
-- ids can both see no sibling and both land. This index makes the invariant hold at the database.
5+
--
6+
-- Keyed on the same expression the verify and resolve paths compare domains with, so a legacy
7+
-- leading `*.` or stray case cannot slip a second provider onto a domain already routed.
8+
--
9+
-- Duplicates must be resolved first. Failing here, inside the transaction, avoids letting the
10+
-- CONCURRENT build fail afterwards and strand an INVALID index that IF NOT EXISTS would skip
11+
-- forever. Which row survives is a judgement call, so this reports the ids and stops.
12+
DO $$
13+
DECLARE duplicate_provider_ids text;
14+
BEGIN
15+
SELECT string_agg(provider_id, ', ')
16+
INTO duplicate_provider_ids
17+
FROM "sso_provider"
18+
WHERE "organization_id" IS NOT NULL
19+
AND ("organization_id", lower(regexp_replace(btrim("domain"), '^\*\.', ''))) IN (
20+
SELECT "organization_id", lower(regexp_replace(btrim("domain"), '^\*\.', ''))
21+
FROM "sso_provider"
22+
WHERE "organization_id" IS NOT NULL
23+
GROUP BY 1, 2
24+
HAVING count(*) > 1
25+
);
26+
IF duplicate_provider_ids IS NOT NULL THEN
27+
RAISE EXCEPTION
28+
'sso_provider has several providers on one organization domain: %. Keep one provider per (organization, domain) and re-run.',
29+
duplicate_provider_ids;
30+
END IF;
31+
END $$;--> statement-breakpoint
32+
33+
COMMIT;--> statement-breakpoint
34+
35+
-- `lock_timeout = 0` for the concurrent build, per packages/db/scripts/migrate.ts.
36+
-- CREATE INDEX CONCURRENTLY waits on every concurrent write in the database, not just
37+
-- this table, so the session's 5s DDL timeout would cancel it (55P03) and strand an
38+
-- INVALID index that the IF NOT EXISTS below would skip forever.
39+
SET lock_timeout = 0;--> statement-breakpoint
40+
41+
-- Clear any INVALID index left by a previously cancelled build, so a replay
42+
-- rebuilds it instead of skipping it.
43+
DROP INDEX CONCURRENTLY IF EXISTS "sso_provider_org_domain_unique";--> statement-breakpoint
44+
45+
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS "sso_provider_org_domain_unique" ON "sso_provider" USING btree ("organization_id", lower(regexp_replace(btrim("domain"), '^\*\.', ''))) WHERE "sso_provider"."organization_id" is not null;--> statement-breakpoint
46+
47+
SET lock_timeout = '5s';

0 commit comments

Comments
 (0)