diff --git a/packages/schemas/alterations/next-1731901231-add-saml-application-secrets-table.ts b/packages/schemas/alterations/next-1731901231-add-saml-application-secrets-table.ts new file mode 100644 index 00000000000..165b73a284a --- /dev/null +++ b/packages/schemas/alterations/next-1731901231-add-saml-application-secrets-table.ts @@ -0,0 +1,40 @@ +import { sql } from '@silverhand/slonik'; + +import type { AlterationScript } from '../lib/types/alteration.js'; + +import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js'; + +const alteration: AlterationScript = { + up: async (pool) => { + await pool.query(sql` + create table saml_application_secrets ( + id varchar(21) not null, + tenant_id varchar(21) not null + references tenants (id) on update cascade on delete cascade, + application_id varchar(21) not null + references applications (id) on update cascade on delete cascade, + private_key text not null, + certificate text not null, + created_at timestamptz not null default now(), + expires_at timestamptz not null, + active boolean not null, + primary key (tenant_id, application_id, id), + constraint application_type + check (check_application_type(application_id, 'SAML')) + ); + + create unique index saml_application_secrets__unique_active_secret + on saml_application_secrets (tenant_id, application_id, active) + where active; + `); + await applyTableRls(pool, 'saml_application_secrets'); + }, + down: async (pool) => { + await dropTableRls(pool, 'saml_application_secrets'); + await pool.query(sql` + drop table saml_application_secrets; + `); + }, +}; + +export default alteration; diff --git a/packages/schemas/tables/saml_application_secrets.sql b/packages/schemas/tables/saml_application_secrets.sql new file mode 100644 index 00000000000..4a9c7825722 --- /dev/null +++ b/packages/schemas/tables/saml_application_secrets.sql @@ -0,0 +1,22 @@ +/* init_order = 2 */ + +create table saml_application_secrets ( + id varchar(21) not null, + tenant_id varchar(21) not null + references tenants (id) on update cascade on delete cascade, + application_id varchar(21) not null + references applications (id) on update cascade on delete cascade, + private_key text not null, + certificate text not null, + created_at timestamptz not null default now(), + expires_at timestamptz not null, + active boolean not null, + primary key (tenant_id, application_id, id), + constraint application_type + check (check_application_type(application_id, 'SAML')) +); + +-- Only one active secret per application +create unique index saml_application_secrets__unique_active_secret + on saml_application_secrets (tenant_id, application_id, active) + where active;