@logto/schemas 1.28.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/alterations/1.29.0-1748832174-add-webauthn-related-origins.ts +20 -0
  2. package/alterations/1.29.0-1749005587-user-sso-identities-table-add-updated-at-column.ts +31 -0
  3. package/alterations/1.29.0-1749026308-add-oidc-session-extension-table.ts +41 -0
  4. package/alterations/1.29.0-1749523818-add-custom-profile-fields.ts +58 -0
  5. package/alterations/1.29.0-1749724664-drop-sie-order-constraint-from-custom-profile-fields.ts +20 -0
  6. package/alterations/1.29.0-1750663091-change-user-password-encrypted-length.ts +18 -0
  7. package/alterations/1.29.0-1750744518-add-secrets-table.ts +50 -0
  8. package/alterations/1.29.0-1750744539-add-secret-connector-relations-table.ts +109 -0
  9. package/alterations-js/1.29.0-1748832174-add-webauthn-related-origins.js +16 -0
  10. package/alterations-js/1.29.0-1749005587-user-sso-identities-table-add-updated-at-column.js +25 -0
  11. package/alterations-js/1.29.0-1749026308-add-oidc-session-extension-table.js +33 -0
  12. package/alterations-js/1.29.0-1749523818-add-custom-profile-fields.js +52 -0
  13. package/alterations-js/1.29.0-1749724664-drop-sie-order-constraint-from-custom-profile-fields.js +16 -0
  14. package/alterations-js/1.29.0-1750663091-change-user-password-encrypted-length.js +14 -0
  15. package/alterations-js/1.29.0-1750744518-add-secrets-table.js +42 -0
  16. package/alterations-js/1.29.0-1750744539-add-secret-connector-relations-table.js +99 -0
  17. package/lib/db-entries/account-center.d.ts +4 -2
  18. package/lib/db-entries/account-center.js +5 -1
  19. package/lib/db-entries/custom-profile-field.d.ts +32 -0
  20. package/lib/db-entries/custom-profile-field.js +58 -0
  21. package/lib/db-entries/index.d.ts +4 -0
  22. package/lib/db-entries/index.js +4 -0
  23. package/lib/db-entries/oidc-session-extension.d.ts +24 -0
  24. package/lib/db-entries/oidc-session-extension.js +42 -0
  25. package/lib/db-entries/secret-connector-relation.d.ts +40 -0
  26. package/lib/db-entries/secret-connector-relation.js +49 -0
  27. package/lib/db-entries/secret.d.ts +44 -0
  28. package/lib/db-entries/secret.js +62 -0
  29. package/lib/db-entries/user-sso-identity.d.ts +5 -1
  30. package/lib/db-entries/user-sso-identity.js +4 -0
  31. package/lib/db-entries/user.js +2 -2
  32. package/lib/foundations/jsonb-types/account-centers.d.ts +5 -0
  33. package/lib/foundations/jsonb-types/account-centers.js +2 -0
  34. package/lib/foundations/jsonb-types/custom-profile-fields.d.ts +116 -0
  35. package/lib/foundations/jsonb-types/custom-profile-fields.js +36 -0
  36. package/lib/foundations/jsonb-types/index.d.ts +2 -1
  37. package/lib/foundations/jsonb-types/index.js +2 -1
  38. package/lib/foundations/jsonb-types/secrets.d.ts +9 -0
  39. package/lib/foundations/jsonb-types/secrets.js +10 -0
  40. package/lib/foundations/jsonb-types/users.d.ts +32 -0
  41. package/lib/foundations/jsonb-types/users.js +11 -10
  42. package/lib/types/consent.d.ts +4 -0
  43. package/lib/types/custom-profile-fields.d.ts +1310 -0
  44. package/lib/types/custom-profile-fields.js +123 -0
  45. package/lib/types/index.d.ts +2 -0
  46. package/lib/types/index.js +2 -0
  47. package/lib/types/interactions.d.ts +6 -0
  48. package/lib/types/interactions.js +1 -0
  49. package/lib/types/log/interaction.d.ts +2 -1
  50. package/lib/types/logto-config/index.d.ts +1104 -18
  51. package/lib/types/logto-config/jwt-customizer.d.ts +2396 -24
  52. package/lib/types/logto-config/jwt-customizer.js +50 -1
  53. package/lib/types/logto-config/oidc-provider.d.ts +6 -6
  54. package/lib/types/mfa.d.ts +10 -10
  55. package/lib/types/sign-in-experience.d.ts +2 -2
  56. package/lib/types/sso-connector.d.ts +23 -0
  57. package/lib/types/sso-connector.js +3 -0
  58. package/lib/types/tenant.d.ts +1 -0
  59. package/lib/types/tenant.js +1 -0
  60. package/lib/types/user.d.ts +11 -0
  61. package/lib/types/user.js +3 -0
  62. package/lib/types/verification-records/backup-code-verification.d.ts +29 -0
  63. package/lib/types/verification-records/backup-code-verification.js +9 -0
  64. package/lib/types/verification-records/code-verification.d.ts +89 -0
  65. package/lib/types/verification-records/code-verification.js +22 -0
  66. package/lib/types/verification-records/enterprise-sso-verification.d.ts +68 -0
  67. package/lib/types/verification-records/enterprise-sso-verification.js +10 -0
  68. package/lib/types/verification-records/index.d.ts +16 -0
  69. package/lib/types/verification-records/index.js +16 -0
  70. package/lib/types/verification-records/new-password-identity-verification.d.ts +54 -0
  71. package/lib/types/verification-records/new-password-identity-verification.js +16 -0
  72. package/lib/types/verification-records/one-time-token-verification.d.ts +55 -0
  73. package/lib/types/verification-records/one-time-token-verification.js +13 -0
  74. package/lib/types/verification-records/password-verification.d.ts +40 -0
  75. package/lib/types/verification-records/password-verification.js +9 -0
  76. package/lib/types/verification-records/social-verification.d.ts +106 -0
  77. package/lib/types/verification-records/social-verification.js +10 -0
  78. package/lib/types/verification-records/totp-verification.d.ts +29 -0
  79. package/lib/types/verification-records/totp-verification.js +9 -0
  80. package/lib/types/verification-records/web-authn-verification.d.ts +80 -0
  81. package/lib/types/verification-records/web-authn-verification.js +12 -0
  82. package/package.json +1 -1
  83. package/tables/account_centers.sql +1 -0
  84. package/tables/connectors.sql +2 -0
  85. package/tables/custom_profile_fields.sql +31 -0
  86. package/tables/oidc_model_instances.sql +2 -0
  87. package/tables/oidc_session_extensions.sql +18 -0
  88. package/tables/secret_connector_relations.sql +78 -0
  89. package/tables/secrets.sql +26 -0
  90. package/tables/user_sso_identities.sql +8 -0
  91. package/tables/users.sql +1 -1
  92. /package/lib/{foundations/jsonb-types/verification-records.d.ts → types/verification-records/verification-type.d.ts} +0 -0
  93. /package/lib/{foundations/jsonb-types/verification-records.js → types/verification-records/verification-type.js} +0 -0
@@ -0,0 +1,20 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ const alteration: AlterationScript = {
6
+ up: async (pool) => {
7
+ await pool.query(sql`
8
+ alter table account_centers
9
+ add column webauthn_related_origins jsonb not null default '[]'::jsonb;
10
+ `);
11
+ },
12
+ down: async (pool) => {
13
+ await pool.query(sql`
14
+ alter table account_centers
15
+ drop column webauthn_related_origins;
16
+ `);
17
+ },
18
+ };
19
+
20
+ export default alteration;
@@ -0,0 +1,31 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ const alteration: AlterationScript = {
6
+ up: async (pool) => {
7
+ await pool.query(sql`
8
+ alter table user_sso_identities
9
+ add column updated_at timestamptz not null default(now());
10
+ `);
11
+
12
+ await pool.query(sql`
13
+ create trigger set_updated_at
14
+ before update on user_sso_identities
15
+ for each row
16
+ execute procedure set_updated_at();
17
+ `);
18
+ },
19
+ down: async (pool) => {
20
+ await pool.query(sql`
21
+ drop trigger set_updated_at on user_sso_identities;
22
+ `);
23
+
24
+ await pool.query(sql`
25
+ alter table user_sso_identities
26
+ drop column updated_at;
27
+ `);
28
+ },
29
+ };
30
+
31
+ export default alteration;
@@ -0,0 +1,41 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
6
+
7
+ const alteration: AlterationScript = {
8
+ up: async (pool) => {
9
+ await pool.query(sql`
10
+ create table oidc_session_extensions (
11
+ tenant_id varchar(21) not null
12
+ references tenants (id) on update cascade on delete cascade,
13
+ session_uid varchar(128) not null,
14
+ account_id varchar(12) not null
15
+ references users (id) on update cascade on delete cascade,
16
+ last_submission jsonb /* @use JsonObject */ not null default '{}'::jsonb,
17
+ created_at timestamptz not null default(now()),
18
+ updated_at timestamptz not null default(now()),
19
+ primary key (tenant_id, session_uid)
20
+ );
21
+ `);
22
+
23
+ await pool.query(sql`
24
+ create trigger set_updated_at
25
+ before update on oidc_session_extensions
26
+ for each row
27
+ execute procedure set_updated_at();
28
+ `);
29
+
30
+ await applyTableRls(pool, 'oidc_session_extensions');
31
+ },
32
+ down: async (pool) => {
33
+ await dropTableRls(pool, 'oidc_session_extensions');
34
+
35
+ await pool.query(sql`
36
+ drop table oidc_session_extensions;
37
+ `);
38
+ },
39
+ };
40
+
41
+ export default alteration;
@@ -0,0 +1,58 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
6
+
7
+ const alteration: AlterationScript = {
8
+ up: async (pool) => {
9
+ await pool.query(sql`
10
+ create table custom_profile_fields (
11
+ tenant_id varchar(21) not null
12
+ references tenants (id) on update cascade on delete cascade,
13
+ id varchar(21) not null,
14
+ name varchar(128) not null,
15
+ type varchar(128) not null /* @use CustomProfileFieldType */,
16
+ label varchar(128) not null default '',
17
+ description varchar(256),
18
+ required boolean not null default false,
19
+ config jsonb /* @use CustomProfileFieldConfig */ not null default '{}'::jsonb,
20
+ created_at timestamptz not null default(now()),
21
+ sie_order int2 not null default 0,
22
+ primary key (id),
23
+ constraint custom_profile_fields__name
24
+ unique (tenant_id, name),
25
+ constraint custom_profile_fields__sie_order
26
+ unique (tenant_id, sie_order)
27
+ );
28
+
29
+ create or replace function custom_profile_fields__increment_sie_order() returns trigger as
30
+ $$ begin
31
+ new.sie_order = (
32
+ select coalesce(max(sie_order), 0)
33
+ from custom_profile_fields
34
+ where tenant_id = (
35
+ select id from tenants where db_user = current_user
36
+ )
37
+ ) + 1;
38
+ return new;
39
+ end; $$ language plpgsql;
40
+
41
+ create trigger custom_profile_fields__increment_sie_order before insert on custom_profile_fields
42
+ for each row execute procedure custom_profile_fields__increment_sie_order();
43
+ `);
44
+
45
+ await applyTableRls(pool, 'custom_profile_fields');
46
+ },
47
+ down: async (pool) => {
48
+ await dropTableRls(pool, 'custom_profile_fields');
49
+ await pool.query(sql`
50
+ drop trigger custom_profile_fields__increment_sie_order on custom_profile_fields;
51
+ drop function custom_profile_fields__increment_sie_order;
52
+ drop table if exists custom_profile_fields;
53
+ drop type if exists custom_profile_field_type;
54
+ `);
55
+ },
56
+ };
57
+
58
+ export default alteration;
@@ -0,0 +1,20 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ const alteration: AlterationScript = {
6
+ up: async (pool) => {
7
+ await pool.query(sql`
8
+ alter table custom_profile_fields
9
+ drop constraint custom_profile_fields__sie_order
10
+ `);
11
+ },
12
+ down: async (pool) => {
13
+ await pool.query(sql`
14
+ alter table custom_profile_fields
15
+ add constraint custom_profile_fields__sie_order unique (tenant_id, sie_order)
16
+ `);
17
+ },
18
+ };
19
+
20
+ export default alteration;
@@ -0,0 +1,18 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ const alteration: AlterationScript = {
6
+ up: async (pool) => {
7
+ await pool.query(sql`
8
+ alter table users alter column password_encrypted set data type varchar(256);
9
+ `);
10
+ },
11
+ down: async (pool) => {
12
+ await pool.query(sql`
13
+ alter table users alter column password_encrypted set data type varchar(128);
14
+ `);
15
+ },
16
+ };
17
+
18
+ export default alteration;
@@ -0,0 +1,50 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
6
+
7
+ const alteration: AlterationScript = {
8
+ up: async (pool) => {
9
+ await pool.query(sql`
10
+ create table secrets (
11
+ tenant_id varchar(21) not null
12
+ references tenants (id) on update cascade on delete cascade,
13
+ id varchar(21) not null primary key,
14
+ user_id varchar(21) not null
15
+ references users (id) on update cascade on delete cascade,
16
+ type varchar(256) /* @user SecretType */ not null,
17
+ /** Encrypted data encryption key (DEK) for the secret. */
18
+ encrypted_dek bytea not null,
19
+ /** Initialization vector for the secret encryption. */
20
+ iv bytea not null,
21
+ /** Authentication tag for the secret encryption. */
22
+ auth_tag bytea not null,
23
+ /** The encrypted secret data. e.g. { access_token, refresh_token }*/
24
+ ciphertext bytea not null,
25
+ /** The metadata associated with the secret. */
26
+ metadata jsonb not null default '{}'::jsonb,
27
+ created_at timestamptz not null default(now()),
28
+ updated_at timestamptz not null default(now())
29
+ );
30
+ `);
31
+
32
+ await pool.query(sql`
33
+ create trigger set_updated_at
34
+ before update on secrets
35
+ for each row
36
+ execute procedure set_updated_at();
37
+ `);
38
+
39
+ await applyTableRls(pool, 'secrets');
40
+ },
41
+ down: async (pool) => {
42
+ await dropTableRls(pool, 'secrets');
43
+
44
+ await pool.query(sql`
45
+ drop table secrets;
46
+ `);
47
+ },
48
+ };
49
+
50
+ export default alteration;
@@ -0,0 +1,109 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
6
+
7
+ const alteration: AlterationScript = {
8
+ up: async (pool) => {
9
+ await pool.query(sql`
10
+ create table secret_connector_relations (
11
+ tenant_id varchar(21) not null
12
+ references tenants (id) on update cascade on delete cascade,
13
+ secret_id varchar(21) not null
14
+ references secrets (id) on update cascade on delete cascade,
15
+ /** Social connector ID foreign reference. Only present for secrets that store social connector tokens. Note: avoid directly cascading deletes here, need to delete the secrets first.*/
16
+ connector_id varchar(128)
17
+ references connectors (id) on update cascade,
18
+ /** SSO connector ID foreign reference. Only present for secrets that store SSO connector tokens. Note: avoid directly cascading deletes here, need to delete the secrets first.*/
19
+ sso_connector_id varchar(128)
20
+ references sso_connectors (id) on update cascade,
21
+ /** The target of the social connector. e.g. 'github', 'google', etc. */
22
+ social_connector_target varchar(256),
23
+ /** User social identity ID foreign reference. Only present for secrets that store social identity tokens. */
24
+ social_identity_id varchar(128),
25
+ /** User sso connector issuer. Only present for secrets that store SSO connector tokens. */
26
+ sso_connector_issuer varchar(256),
27
+ /** User SSO identity ID. Only present for secrets that store SSO identity tokens. */
28
+ sso_identity_id varchar(128),
29
+ primary key (tenant_id, secret_id),
30
+ /** Ensures that each social identity is associated with only one secret. */
31
+ constraint secret_connector_relations__target__social_identity_id
32
+ unique (tenant_id, social_connector_target, social_identity_id),
33
+ /** Ensures that each SSO identity is associated with only one secret. */
34
+ foreign key (tenant_id, sso_connector_issuer, sso_identity_id)
35
+ references user_sso_identities (tenant_id, issuer, identity_id) on update cascade,
36
+ /** Ensure that each secret is associated with a social connector or SSO connector, but not both at the same time. */
37
+ constraint secret_connector_relations__connector_id__sso_connector_id
38
+ check (
39
+ (
40
+ connector_id is not null and social_connector_target is not null and social_identity_id is not null and
41
+ sso_connector_id is null and sso_identity_id is null
42
+ ) or (
43
+ connector_id is null and social_connector_target is null and social_identity_id is null and
44
+ sso_connector_id is not null and sso_identity_id is not null
45
+ )
46
+ )
47
+ );
48
+ `);
49
+
50
+ /** Trigger function to delete secrets when the social connector is deleted. */
51
+ await pool.query(sql`
52
+ create function delete_secrets_on_social_connector_delete()
53
+ returns trigger as $$
54
+ begin
55
+ delete from secrets
56
+ where id in (
57
+ select secret_id from secret_connector_relations
58
+ where tenant_id = old.tenant_id and connector_id = old.id
59
+ );
60
+ return old;
61
+ end;
62
+ $$ language plpgsql;
63
+
64
+ create trigger delete_secrets_before_social_connector_delete
65
+ before delete on connectors
66
+ for each row
67
+ execute procedure delete_secrets_on_social_connector_delete();
68
+ `);
69
+
70
+ /** Trigger function to delete secrets when the SSO connector is deleted. */
71
+ await pool.query(sql`
72
+ create function delete_secrets_on_sso_connector_delete()
73
+ returns trigger as $$
74
+ begin
75
+ delete from secrets
76
+ where id in (
77
+ select secret_id from secret_connector_relations
78
+ where tenant_id = old.tenant_id and sso_connector_id = old.id
79
+ );
80
+ return old;
81
+ end;
82
+ $$ language plpgsql;
83
+
84
+ create trigger delete_secrets_before_sso_connector_delete
85
+ before delete on sso_connectors
86
+ for each row
87
+ execute procedure delete_secrets_on_sso_connector_delete();
88
+ `);
89
+
90
+ await applyTableRls(pool, 'secret_connector_relations');
91
+ },
92
+ down: async (pool) => {
93
+ await pool.query(sql`
94
+ drop trigger if exists delete_secrets_before_social_connector_delete on connectors;
95
+ drop function if exists delete_secrets_on_social_connector_delete;
96
+
97
+ drop trigger if exists delete_secrets_before_sso_connector_delete on sso_connectors;
98
+ drop function if exists delete_secrets_on_sso_connector_delete;
99
+ `);
100
+
101
+ await dropTableRls(pool, 'secret_connector_relations');
102
+
103
+ await pool.query(sql`
104
+ drop table secret_connector_relations;
105
+ `);
106
+ },
107
+ };
108
+
109
+ export default alteration;
@@ -0,0 +1,16 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ const alteration = {
3
+ up: async (pool) => {
4
+ await pool.query(sql `
5
+ alter table account_centers
6
+ add column webauthn_related_origins jsonb not null default '[]'::jsonb;
7
+ `);
8
+ },
9
+ down: async (pool) => {
10
+ await pool.query(sql `
11
+ alter table account_centers
12
+ drop column webauthn_related_origins;
13
+ `);
14
+ },
15
+ };
16
+ export default alteration;
@@ -0,0 +1,25 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ const alteration = {
3
+ up: async (pool) => {
4
+ await pool.query(sql `
5
+ alter table user_sso_identities
6
+ add column updated_at timestamptz not null default(now());
7
+ `);
8
+ await pool.query(sql `
9
+ create trigger set_updated_at
10
+ before update on user_sso_identities
11
+ for each row
12
+ execute procedure set_updated_at();
13
+ `);
14
+ },
15
+ down: async (pool) => {
16
+ await pool.query(sql `
17
+ drop trigger set_updated_at on user_sso_identities;
18
+ `);
19
+ await pool.query(sql `
20
+ alter table user_sso_identities
21
+ drop column updated_at;
22
+ `);
23
+ },
24
+ };
25
+ export default alteration;
@@ -0,0 +1,33 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
3
+ const alteration = {
4
+ up: async (pool) => {
5
+ await pool.query(sql `
6
+ create table oidc_session_extensions (
7
+ tenant_id varchar(21) not null
8
+ references tenants (id) on update cascade on delete cascade,
9
+ session_uid varchar(128) not null,
10
+ account_id varchar(12) not null
11
+ references users (id) on update cascade on delete cascade,
12
+ last_submission jsonb /* @use JsonObject */ not null default '{}'::jsonb,
13
+ created_at timestamptz not null default(now()),
14
+ updated_at timestamptz not null default(now()),
15
+ primary key (tenant_id, session_uid)
16
+ );
17
+ `);
18
+ await pool.query(sql `
19
+ create trigger set_updated_at
20
+ before update on oidc_session_extensions
21
+ for each row
22
+ execute procedure set_updated_at();
23
+ `);
24
+ await applyTableRls(pool, 'oidc_session_extensions');
25
+ },
26
+ down: async (pool) => {
27
+ await dropTableRls(pool, 'oidc_session_extensions');
28
+ await pool.query(sql `
29
+ drop table oidc_session_extensions;
30
+ `);
31
+ },
32
+ };
33
+ export default alteration;
@@ -0,0 +1,52 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
3
+ const alteration = {
4
+ up: async (pool) => {
5
+ await pool.query(sql `
6
+ create table custom_profile_fields (
7
+ tenant_id varchar(21) not null
8
+ references tenants (id) on update cascade on delete cascade,
9
+ id varchar(21) not null,
10
+ name varchar(128) not null,
11
+ type varchar(128) not null /* @use CustomProfileFieldType */,
12
+ label varchar(128) not null default '',
13
+ description varchar(256),
14
+ required boolean not null default false,
15
+ config jsonb /* @use CustomProfileFieldConfig */ not null default '{}'::jsonb,
16
+ created_at timestamptz not null default(now()),
17
+ sie_order int2 not null default 0,
18
+ primary key (id),
19
+ constraint custom_profile_fields__name
20
+ unique (tenant_id, name),
21
+ constraint custom_profile_fields__sie_order
22
+ unique (tenant_id, sie_order)
23
+ );
24
+
25
+ create or replace function custom_profile_fields__increment_sie_order() returns trigger as
26
+ $$ begin
27
+ new.sie_order = (
28
+ select coalesce(max(sie_order), 0)
29
+ from custom_profile_fields
30
+ where tenant_id = (
31
+ select id from tenants where db_user = current_user
32
+ )
33
+ ) + 1;
34
+ return new;
35
+ end; $$ language plpgsql;
36
+
37
+ create trigger custom_profile_fields__increment_sie_order before insert on custom_profile_fields
38
+ for each row execute procedure custom_profile_fields__increment_sie_order();
39
+ `);
40
+ await applyTableRls(pool, 'custom_profile_fields');
41
+ },
42
+ down: async (pool) => {
43
+ await dropTableRls(pool, 'custom_profile_fields');
44
+ await pool.query(sql `
45
+ drop trigger custom_profile_fields__increment_sie_order on custom_profile_fields;
46
+ drop function custom_profile_fields__increment_sie_order;
47
+ drop table if exists custom_profile_fields;
48
+ drop type if exists custom_profile_field_type;
49
+ `);
50
+ },
51
+ };
52
+ export default alteration;
@@ -0,0 +1,16 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ const alteration = {
3
+ up: async (pool) => {
4
+ await pool.query(sql `
5
+ alter table custom_profile_fields
6
+ drop constraint custom_profile_fields__sie_order
7
+ `);
8
+ },
9
+ down: async (pool) => {
10
+ await pool.query(sql `
11
+ alter table custom_profile_fields
12
+ add constraint custom_profile_fields__sie_order unique (tenant_id, sie_order)
13
+ `);
14
+ },
15
+ };
16
+ export default alteration;
@@ -0,0 +1,14 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ const alteration = {
3
+ up: async (pool) => {
4
+ await pool.query(sql `
5
+ alter table users alter column password_encrypted set data type varchar(256);
6
+ `);
7
+ },
8
+ down: async (pool) => {
9
+ await pool.query(sql `
10
+ alter table users alter column password_encrypted set data type varchar(128);
11
+ `);
12
+ },
13
+ };
14
+ export default alteration;
@@ -0,0 +1,42 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
3
+ const alteration = {
4
+ up: async (pool) => {
5
+ await pool.query(sql `
6
+ create table secrets (
7
+ tenant_id varchar(21) not null
8
+ references tenants (id) on update cascade on delete cascade,
9
+ id varchar(21) not null primary key,
10
+ user_id varchar(21) not null
11
+ references users (id) on update cascade on delete cascade,
12
+ type varchar(256) /* @user SecretType */ not null,
13
+ /** Encrypted data encryption key (DEK) for the secret. */
14
+ encrypted_dek bytea not null,
15
+ /** Initialization vector for the secret encryption. */
16
+ iv bytea not null,
17
+ /** Authentication tag for the secret encryption. */
18
+ auth_tag bytea not null,
19
+ /** The encrypted secret data. e.g. { access_token, refresh_token }*/
20
+ ciphertext bytea not null,
21
+ /** The metadata associated with the secret. */
22
+ metadata jsonb not null default '{}'::jsonb,
23
+ created_at timestamptz not null default(now()),
24
+ updated_at timestamptz not null default(now())
25
+ );
26
+ `);
27
+ await pool.query(sql `
28
+ create trigger set_updated_at
29
+ before update on secrets
30
+ for each row
31
+ execute procedure set_updated_at();
32
+ `);
33
+ await applyTableRls(pool, 'secrets');
34
+ },
35
+ down: async (pool) => {
36
+ await dropTableRls(pool, 'secrets');
37
+ await pool.query(sql `
38
+ drop table secrets;
39
+ `);
40
+ },
41
+ };
42
+ export default alteration;
@@ -0,0 +1,99 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
3
+ const alteration = {
4
+ up: async (pool) => {
5
+ await pool.query(sql `
6
+ create table secret_connector_relations (
7
+ tenant_id varchar(21) not null
8
+ references tenants (id) on update cascade on delete cascade,
9
+ secret_id varchar(21) not null
10
+ references secrets (id) on update cascade on delete cascade,
11
+ /** Social connector ID foreign reference. Only present for secrets that store social connector tokens. Note: avoid directly cascading deletes here, need to delete the secrets first.*/
12
+ connector_id varchar(128)
13
+ references connectors (id) on update cascade,
14
+ /** SSO connector ID foreign reference. Only present for secrets that store SSO connector tokens. Note: avoid directly cascading deletes here, need to delete the secrets first.*/
15
+ sso_connector_id varchar(128)
16
+ references sso_connectors (id) on update cascade,
17
+ /** The target of the social connector. e.g. 'github', 'google', etc. */
18
+ social_connector_target varchar(256),
19
+ /** User social identity ID foreign reference. Only present for secrets that store social identity tokens. */
20
+ social_identity_id varchar(128),
21
+ /** User sso connector issuer. Only present for secrets that store SSO connector tokens. */
22
+ sso_connector_issuer varchar(256),
23
+ /** User SSO identity ID. Only present for secrets that store SSO identity tokens. */
24
+ sso_identity_id varchar(128),
25
+ primary key (tenant_id, secret_id),
26
+ /** Ensures that each social identity is associated with only one secret. */
27
+ constraint secret_connector_relations__target__social_identity_id
28
+ unique (tenant_id, social_connector_target, social_identity_id),
29
+ /** Ensures that each SSO identity is associated with only one secret. */
30
+ foreign key (tenant_id, sso_connector_issuer, sso_identity_id)
31
+ references user_sso_identities (tenant_id, issuer, identity_id) on update cascade,
32
+ /** Ensure that each secret is associated with a social connector or SSO connector, but not both at the same time. */
33
+ constraint secret_connector_relations__connector_id__sso_connector_id
34
+ check (
35
+ (
36
+ connector_id is not null and social_connector_target is not null and social_identity_id is not null and
37
+ sso_connector_id is null and sso_identity_id is null
38
+ ) or (
39
+ connector_id is null and social_connector_target is null and social_identity_id is null and
40
+ sso_connector_id is not null and sso_identity_id is not null
41
+ )
42
+ )
43
+ );
44
+ `);
45
+ /** Trigger function to delete secrets when the social connector is deleted. */
46
+ await pool.query(sql `
47
+ create function delete_secrets_on_social_connector_delete()
48
+ returns trigger as $$
49
+ begin
50
+ delete from secrets
51
+ where id in (
52
+ select secret_id from secret_connector_relations
53
+ where tenant_id = old.tenant_id and connector_id = old.id
54
+ );
55
+ return old;
56
+ end;
57
+ $$ language plpgsql;
58
+
59
+ create trigger delete_secrets_before_social_connector_delete
60
+ before delete on connectors
61
+ for each row
62
+ execute procedure delete_secrets_on_social_connector_delete();
63
+ `);
64
+ /** Trigger function to delete secrets when the SSO connector is deleted. */
65
+ await pool.query(sql `
66
+ create function delete_secrets_on_sso_connector_delete()
67
+ returns trigger as $$
68
+ begin
69
+ delete from secrets
70
+ where id in (
71
+ select secret_id from secret_connector_relations
72
+ where tenant_id = old.tenant_id and sso_connector_id = old.id
73
+ );
74
+ return old;
75
+ end;
76
+ $$ language plpgsql;
77
+
78
+ create trigger delete_secrets_before_sso_connector_delete
79
+ before delete on sso_connectors
80
+ for each row
81
+ execute procedure delete_secrets_on_sso_connector_delete();
82
+ `);
83
+ await applyTableRls(pool, 'secret_connector_relations');
84
+ },
85
+ down: async (pool) => {
86
+ await pool.query(sql `
87
+ drop trigger if exists delete_secrets_before_social_connector_delete on connectors;
88
+ drop function if exists delete_secrets_on_social_connector_delete;
89
+
90
+ drop trigger if exists delete_secrets_before_sso_connector_delete on sso_connectors;
91
+ drop function if exists delete_secrets_on_sso_connector_delete;
92
+ `);
93
+ await dropTableRls(pool, 'secret_connector_relations');
94
+ await pool.query(sql `
95
+ drop table secret_connector_relations;
96
+ `);
97
+ },
98
+ };
99
+ export default alteration;