|
| 1 | +/* auth_migration: 20260821000000 */ |
| 2 | +-- SCIM Users provisioned into one SSO provider. The resource is stored as a |
| 3 | +-- document; queryable columns are generated from it so the two cannot drift. |
| 4 | +create table if not exists {{ index .Options "Namespace" }}.scim_users ( |
| 5 | + id uuid not null default gen_random_uuid(), |
| 6 | + sso_provider_id uuid not null references {{ index .Options "Namespace" }}.sso_providers (id) on delete cascade, |
| 7 | + user_id uuid references {{ index .Options "Namespace" }}.users (id) on delete set null, |
| 8 | + resource jsonb not null, |
| 9 | + user_name text not null generated always as (resource->>'userName') stored, |
| 10 | + external_id text generated always as (resource->>'externalId') stored, |
| 11 | + active boolean not null generated always as (coalesce((resource->>'active')::boolean, true)) stored, |
| 12 | + created_at timestamptz not null default now(), |
| 13 | + updated_at timestamptz not null default now(), |
| 14 | + deleted_at timestamptz, |
| 15 | + constraint scim_users_pkey primary key (id) |
| 16 | +); |
| 17 | + |
| 18 | +/* auth_migration: 20260821000000 */ |
| 19 | +-- userName is unique within a provider, case-folded, excluding soft-deleted rows. |
| 20 | +create unique index if not exists scim_users_user_name_key |
| 21 | + on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, lower(user_name collate "C")) |
| 22 | + where deleted_at is null; |
| 23 | + |
| 24 | +/* auth_migration: 20260821000000 */ |
| 25 | +-- externalId is unique within a provider when set; nulls are unconstrained. |
| 26 | +create unique index if not exists scim_users_external_id_key |
| 27 | + on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, external_id) |
| 28 | + where external_id is not null and deleted_at is null; |
| 29 | + |
| 30 | +/* auth_migration: 20260821000000 */ |
| 31 | +-- Links a SCIM user to its auth.users row; not partial, so an ON DELETE SET |
| 32 | +-- NULL from auth.users can find soft-deleted rows too. |
| 33 | +create index if not exists scim_users_user_id_idx |
| 34 | + on {{ index .Options "Namespace" }}.scim_users (user_id); |
| 35 | + |
| 36 | +/* auth_migration: 20260821000000 */ |
| 37 | +-- Sort indexes break ties on id for a total order; user_name uses collate "C" |
| 38 | +-- so ordering does not depend on the database's collation. |
| 39 | +create index if not exists scim_users_id_idx |
| 40 | + on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, id) |
| 41 | + where deleted_at is null; |
| 42 | + |
| 43 | +/* auth_migration: 20260821000000 */ |
| 44 | +create index if not exists scim_users_user_name_idx |
| 45 | + on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, lower(user_name collate "C"), id) |
| 46 | + where deleted_at is null; |
| 47 | + |
| 48 | +/* auth_migration: 20260821000000 */ |
| 49 | +create index if not exists scim_users_created_at_idx |
| 50 | + on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, created_at, id) |
| 51 | + where deleted_at is null; |
| 52 | + |
| 53 | +/* auth_migration: 20260821000000 */ |
| 54 | +create index if not exists scim_users_updated_at_idx |
| 55 | + on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, updated_at, id) |
| 56 | + where deleted_at is null; |
| 57 | + |
| 58 | +/* auth_migration: 20260821000000 */ |
| 59 | +create index if not exists scim_users_sso_provider_id_idx |
| 60 | + on {{ index .Options "Namespace" }}.scim_users (sso_provider_id); |
| 61 | + |
| 62 | +/* auth_migration: 20260821000000 */ |
| 63 | +-- Supports purging soft-deleted rows. |
| 64 | +create index if not exists scim_users_deleted_at_idx |
| 65 | + on {{ index .Options "Namespace" }}.scim_users (deleted_at); |
| 66 | + |
| 67 | +/* auth_migration: 20260821000000 */ |
| 68 | +alter table {{ index .Options "Namespace" }}.scim_users enable row level security; |
| 69 | +/* auth_migration: 20260821000000 */ |
| 70 | +grant select on {{ index .Options "Namespace" }}.scim_users to postgres with grant option; |
0 commit comments