-
Notifications
You must be signed in to change notification settings - Fork 750
feat(scim): add scim_users, scim_tokens tables #2745
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
dc402ed
feat(scim): add scim_users and scim_tokens tables
xlgmokha 9a4b646
feat(scim): noramlize scim_users.user_name to lowercase
xlgmokha 6037ef2
fix(scim): remove RLS
xlgmokha 6359000
feat(scim): remove default uuid generator on scim_users, scim_tokens
xlgmokha File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /* auth_migration: 20260821000000 */ | ||
| -- SCIM Users provisioned into one SSO provider. The resource is stored as a | ||
| -- document; queryable columns are generated from it so the two cannot drift. | ||
| create table if not exists {{ index .Options "Namespace" }}.scim_users ( | ||
| id uuid not null, | ||
| sso_provider_id uuid not null references {{ index .Options "Namespace" }}.sso_providers (id) on delete cascade, | ||
| user_id uuid references {{ index .Options "Namespace" }}.users (id) on delete set null, | ||
| resource jsonb not null, | ||
| user_name text not null generated always as (lower(resource->>'userName')) stored, | ||
| external_id text generated always as (resource->>'externalId') stored, | ||
| active boolean not null generated always as (coalesce((resource->>'active')::boolean, true)) stored, | ||
| created_at timestamptz not null default now(), | ||
| updated_at timestamptz not null default now(), | ||
| deleted_at timestamptz, | ||
|
xlgmokha marked this conversation as resolved.
|
||
| constraint scim_users_pkey primary key (id) | ||
| ); | ||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| -- userName is unique within a provider, case-folded, excluding soft-deleted rows. | ||
| create unique index if not exists scim_users_user_name_key | ||
| on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, user_name) | ||
| where deleted_at is null; | ||
|
xlgmokha marked this conversation as resolved.
|
||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| -- externalId is unique within a provider when set; nulls are unconstrained. | ||
| create unique index if not exists scim_users_external_id_key | ||
| on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, external_id) | ||
| where external_id is not null and deleted_at is null; | ||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| -- Links a SCIM user to its auth.users row; not partial, so an ON DELETE SET | ||
| -- NULL from auth.users can find soft-deleted rows too. | ||
| create index if not exists scim_users_user_id_idx | ||
| on {{ index .Options "Namespace" }}.scim_users (user_id); | ||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| create index if not exists scim_users_id_idx | ||
| on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, id) | ||
| where deleted_at is null; | ||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| create index if not exists scim_users_user_name_idx | ||
|
xlgmokha marked this conversation as resolved.
|
||
| on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, user_name collate "C", id) | ||
| where deleted_at is null; | ||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| create index if not exists scim_users_created_at_idx | ||
| on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, created_at, id) | ||
| where deleted_at is null; | ||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| create index if not exists scim_users_updated_at_idx | ||
| on {{ index .Options "Namespace" }}.scim_users (sso_provider_id, updated_at, id) | ||
| where deleted_at is null; | ||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| create index if not exists scim_users_sso_provider_id_idx | ||
| on {{ index .Options "Namespace" }}.scim_users (sso_provider_id); | ||
|
xlgmokha marked this conversation as resolved.
|
||
|
|
||
| /* auth_migration: 20260821000000 */ | ||
| -- Supports purging soft-deleted rows. | ||
| create index if not exists scim_users_deleted_at_idx | ||
| on {{ index .Options "Namespace" }}.scim_users (deleted_at); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| /* auth_migration: 20260821010000 */ | ||
| -- Bearer tokens authorising SCIM requests for one SSO provider. Only the | ||
| -- SHA-256 digest is stored; a token carries 160 bits, so the digest needs no salt. | ||
| create table if not exists {{ index .Options "Namespace" }}.scim_tokens ( | ||
| id uuid not null, | ||
| sso_provider_id uuid not null references {{ index .Options "Namespace" }}.sso_providers (id) on delete cascade, | ||
| token_hash text not null, | ||
| prefix text not null, | ||
| created_at timestamptz not null default now(), | ||
| expires_at timestamptz, | ||
| revoked_at timestamptz, | ||
| last_used_at timestamptz, | ||
| constraint scim_tokens_pkey primary key (id), | ||
| constraint scim_tokens_token_hash_check check (token_hash ~ '^[0-9a-f]{64}$'), | ||
| constraint scim_tokens_expires_at_future check (expires_at is null or expires_at > created_at), | ||
| constraint scim_tokens_revoked_after_created check (revoked_at is null or revoked_at >= created_at) | ||
| ); | ||
|
|
||
| /* auth_migration: 20260821010000 */ | ||
| -- The digest resolves a request to a provider, so it is unique across all providers. | ||
| create unique index if not exists scim_tokens_token_hash_key | ||
| on {{ index .Options "Namespace" }}.scim_tokens (token_hash); | ||
|
|
||
| /* auth_migration: 20260821010000 */ | ||
| -- Not partial, so an ON DELETE CASCADE from sso_providers can find revoked | ||
| -- tokens too. | ||
| create index if not exists scim_tokens_sso_provider_id_idx | ||
| on {{ index .Options "Namespace" }}.scim_tokens (sso_provider_id); | ||
|
|
||
| /* auth_migration: 20260821010000 */ | ||
| -- Supports purging expired tokens. | ||
| create index if not exists scim_tokens_expires_at_idx | ||
| on {{ index .Options "Namespace" }}.scim_tokens (expires_at); | ||
|
|
||
| /* auth_migration: 20260821010000 */ | ||
| -- Supports purging revoked tokens. | ||
| create index if not exists scim_tokens_revoked_at_idx | ||
| on {{ index .Options "Namespace" }}.scim_tokens (revoked_at); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.