From c1b10aef4e3271aecdc1b5d671968a619fff39ba Mon Sep 17 00:00:00 2001 From: Darcy Ye Date: Mon, 18 Nov 2024 12:31:11 +0800 Subject: [PATCH] feat(schemas): add saml_application_proxies table --- ...4029-add-saml-application-proxies-table.ts | 37 +++++++++++++++++++ .../src/foundations/jsonb-types/index.ts | 1 + .../jsonb-types/saml-application-proxies.ts | 29 +++++++++++++++ .../tables/saml_application_proxies.sql | 23 ++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 packages/schemas/alterations/next-1731904029-add-saml-application-proxies-table.ts create mode 100644 packages/schemas/src/foundations/jsonb-types/saml-application-proxies.ts create mode 100644 packages/schemas/tables/saml_application_proxies.sql diff --git a/packages/schemas/alterations/next-1731904029-add-saml-application-proxies-table.ts b/packages/schemas/alterations/next-1731904029-add-saml-application-proxies-table.ts new file mode 100644 index 000000000000..92e673b557f8 --- /dev/null +++ b/packages/schemas/alterations/next-1731904029-add-saml-application-proxies-table.ts @@ -0,0 +1,37 @@ +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_proxies ( + application_id varchar(21) not null + references applications (id) on update cascade on delete cascade, + tenant_id varchar(21) not null + references tenants (id) on update cascade on delete cascade, + name varchar(256) not null, + description text, + attribute_mapping jsonb /* @use SamlAttributeMapping */ not null default '{}'::jsonb, + sp_metadata jsonb /* @use SamlSpMetadata */ not null, + primary key (application_id), + constraint application_type + check (check_application_type(application_id, 'SAML')) + ); + + create unique index saml_application_proxies__unique_application_id + on saml_application_proxies (application_id); + `); + await applyTableRls(pool, 'saml_application_proxies'); + }, + down: async (pool) => { + await dropTableRls(pool, 'saml_application_proxies'); + await pool.query(sql` + drop table saml_application_proxies; + `); + }, +}; + +export default alteration; diff --git a/packages/schemas/src/foundations/jsonb-types/index.ts b/packages/schemas/src/foundations/jsonb-types/index.ts index 4cbc95dc99e1..e4d8f25dc66a 100644 --- a/packages/schemas/src/foundations/jsonb-types/index.ts +++ b/packages/schemas/src/foundations/jsonb-types/index.ts @@ -10,6 +10,7 @@ export * from './sso-connector.js'; export * from './applications.js'; export * from './verification-records.js'; export * from './account-centers.js'; +export * from './saml-application-proxies.js'; export { configurableConnectorMetadataGuard, diff --git a/packages/schemas/src/foundations/jsonb-types/saml-application-proxies.ts b/packages/schemas/src/foundations/jsonb-types/saml-application-proxies.ts new file mode 100644 index 000000000000..6df8b801d403 --- /dev/null +++ b/packages/schemas/src/foundations/jsonb-types/saml-application-proxies.ts @@ -0,0 +1,29 @@ +import { type ToZodObject } from '@logto/connector-kit'; +import { z } from 'zod'; + +export type SamlAttributeMapping = Record; + +export const samlAttributeMappingGuard = z.record( + z.string() +) satisfies z.ZodType; + +export enum BindingType { + POST = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + REDIRECT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', +} + +export type SamlSpMetadata = { + entityID: string; + acsURL: { + binding: BindingType; + url: string; + }; +}; + +export const samlSpMetadataGuard = z.object({ + entityID: z.string(), + acsURL: z.object({ + binding: z.nativeEnum(BindingType), + url: z.string(), + }), +}) satisfies ToZodObject; diff --git a/packages/schemas/tables/saml_application_proxies.sql b/packages/schemas/tables/saml_application_proxies.sql new file mode 100644 index 000000000000..894848eaec47 --- /dev/null +++ b/packages/schemas/tables/saml_application_proxies.sql @@ -0,0 +1,23 @@ +/* init_order = 2 */ + +/** + * The SAML application proxy and SAML-type application have a one-to-one correspondence: + * - a SAML-type application can only have one SAML application proxy + * - a SAML application proxy can only proxy one SAML-type application + */ +create table saml_application_proxies ( + application_id varchar(21) not null + references applications (id) on update cascade on delete cascade, + tenant_id varchar(21) not null + references tenants (id) on update cascade on delete cascade, + name varchar(256) not null, + description text, + attribute_mapping jsonb /* @use SamlAttributeMapping */ not null default '{}'::jsonb, + sp_metadata jsonb /* @use SamlSpMetadata */ not null, + primary key (application_id), + constraint application_type + check (check_application_type(application_id, 'SAML')) +); + +create unique index saml_application_proxies__unique_application_id + on saml_application_proxies (application_id);