@logto/schemas 1.28.0 → 1.30.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 (129) 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/1.30.0-1750744685-add-triggers-to-delete-secrets-on-social-identities-deletion.ts +81 -0
  10. package/alterations/1.30.0-1750748516-add-enable-token-storage-column-to-connectors-table.ts +20 -0
  11. package/alterations/1.30.0-1751255436-split-secret-connector-relatioins-table.ts +359 -0
  12. package/alterations/1.30.0-1751337183-add-require-mfa-on-sign-in-to-users.ts +20 -0
  13. package/alterations/1.30.0-1751400000-move-require-mfa-on-sign-in-to-logto-config.ts +21 -0
  14. package/alterations/1.30.0-1751529530-add-enable-token-storage-column-to-sso-connectors-table.ts +20 -0
  15. package/alterations/1.30.0-1752630302-alterate-enable-column-default-value-in-account-centers-table.ts +20 -0
  16. package/alterations/1.30.0-1753669579-add-organization-user-relations-foreign-key.ts +46 -0
  17. package/alterations-js/1.29.0-1748832174-add-webauthn-related-origins.js +16 -0
  18. package/alterations-js/1.29.0-1749005587-user-sso-identities-table-add-updated-at-column.js +25 -0
  19. package/alterations-js/1.29.0-1749026308-add-oidc-session-extension-table.js +33 -0
  20. package/alterations-js/1.29.0-1749523818-add-custom-profile-fields.js +52 -0
  21. package/alterations-js/1.29.0-1749724664-drop-sie-order-constraint-from-custom-profile-fields.js +16 -0
  22. package/alterations-js/1.29.0-1750663091-change-user-password-encrypted-length.js +14 -0
  23. package/alterations-js/1.29.0-1750744518-add-secrets-table.js +42 -0
  24. package/alterations-js/1.29.0-1750744539-add-secret-connector-relations-table.js +99 -0
  25. package/alterations-js/1.30.0-1750744685-add-triggers-to-delete-secrets-on-social-identities-deletion.js +76 -0
  26. package/alterations-js/1.30.0-1750748516-add-enable-token-storage-column-to-connectors-table.js +16 -0
  27. package/alterations-js/1.30.0-1751255436-split-secret-connector-relatioins-table.js +338 -0
  28. package/alterations-js/1.30.0-1751337183-add-require-mfa-on-sign-in-to-users.js +16 -0
  29. package/alterations-js/1.30.0-1751400000-move-require-mfa-on-sign-in-to-logto-config.js +17 -0
  30. package/alterations-js/1.30.0-1751529530-add-enable-token-storage-column-to-sso-connectors-table.js +16 -0
  31. package/alterations-js/1.30.0-1752630302-alterate-enable-column-default-value-in-account-centers-table.js +16 -0
  32. package/alterations-js/1.30.0-1753669579-add-organization-user-relations-foreign-key.js +38 -0
  33. package/lib/consts/oidc.d.ts +9 -1
  34. package/lib/consts/oidc.js +5 -0
  35. package/lib/db-entries/account-center.d.ts +4 -2
  36. package/lib/db-entries/account-center.js +5 -1
  37. package/lib/db-entries/connector.d.ts +5 -1
  38. package/lib/db-entries/connector.js +4 -0
  39. package/lib/db-entries/custom-profile-field.d.ts +32 -0
  40. package/lib/db-entries/custom-profile-field.js +58 -0
  41. package/lib/db-entries/index.d.ts +5 -0
  42. package/lib/db-entries/index.js +5 -0
  43. package/lib/db-entries/oidc-session-extension.d.ts +24 -0
  44. package/lib/db-entries/oidc-session-extension.js +42 -0
  45. package/lib/db-entries/secret-enterprise-sso-connector-relation.d.ts +28 -0
  46. package/lib/db-entries/secret-enterprise-sso-connector-relation.js +37 -0
  47. package/lib/db-entries/secret-social-connector-relation.d.ts +28 -0
  48. package/lib/db-entries/secret-social-connector-relation.js +37 -0
  49. package/lib/db-entries/secret.d.ts +44 -0
  50. package/lib/db-entries/secret.js +62 -0
  51. package/lib/db-entries/sso-connector.d.ts +5 -1
  52. package/lib/db-entries/sso-connector.js +4 -0
  53. package/lib/db-entries/user-sso-identity.d.ts +5 -1
  54. package/lib/db-entries/user-sso-identity.js +4 -0
  55. package/lib/db-entries/user.js +2 -2
  56. package/lib/foundations/jsonb-types/account-centers.d.ts +5 -0
  57. package/lib/foundations/jsonb-types/account-centers.js +2 -0
  58. package/lib/foundations/jsonb-types/custom-profile-fields.d.ts +441 -0
  59. package/lib/foundations/jsonb-types/custom-profile-fields.js +44 -0
  60. package/lib/foundations/jsonb-types/index.d.ts +2 -1
  61. package/lib/foundations/jsonb-types/index.js +2 -1
  62. package/lib/foundations/jsonb-types/secrets.d.ts +11 -0
  63. package/lib/foundations/jsonb-types/secrets.js +15 -0
  64. package/lib/foundations/jsonb-types/sign-in-experience.d.ts +3 -1
  65. package/lib/foundations/jsonb-types/sign-in-experience.js +2 -0
  66. package/lib/foundations/jsonb-types/users.d.ts +126 -0
  67. package/lib/foundations/jsonb-types/users.js +22 -10
  68. package/lib/types/connector.d.ts +39 -0
  69. package/lib/types/connector.js +1 -0
  70. package/lib/types/consent.d.ts +44 -0
  71. package/lib/types/custom-profile-fields.d.ts +2587 -0
  72. package/lib/types/custom-profile-fields.js +159 -0
  73. package/lib/types/index.d.ts +4 -0
  74. package/lib/types/index.js +4 -0
  75. package/lib/types/interactions.d.ts +181 -1
  76. package/lib/types/interactions.js +49 -1
  77. package/lib/types/log/interaction.d.ts +2 -1
  78. package/lib/types/logto-config/index.d.ts +1139 -18
  79. package/lib/types/logto-config/jwt-customizer.d.ts +2529 -32
  80. package/lib/types/logto-config/jwt-customizer.js +55 -1
  81. package/lib/types/logto-config/oidc-provider.d.ts +6 -6
  82. package/lib/types/mfa.d.ts +10 -10
  83. package/lib/types/secrets.d.ts +436 -0
  84. package/lib/types/secrets.js +73 -0
  85. package/lib/types/sign-in-experience.d.ts +21 -3
  86. package/lib/types/sign-in-experience.js +3 -1
  87. package/lib/types/sso-connector.d.ts +28 -2
  88. package/lib/types/sso-connector.js +3 -0
  89. package/lib/types/tenant.d.ts +1 -0
  90. package/lib/types/tenant.js +1 -0
  91. package/lib/types/user-logto-config.d.ts +45 -0
  92. package/lib/types/user-logto-config.js +18 -0
  93. package/lib/types/user.d.ts +626 -0
  94. package/lib/types/user.js +17 -1
  95. package/lib/types/verification-records/backup-code-verification.d.ts +47 -0
  96. package/lib/types/verification-records/backup-code-verification.js +12 -0
  97. package/lib/types/verification-records/code-verification.d.ts +89 -0
  98. package/lib/types/verification-records/code-verification.js +22 -0
  99. package/lib/types/verification-records/enterprise-sso-verification.d.ts +213 -0
  100. package/lib/types/verification-records/enterprise-sso-verification.js +15 -0
  101. package/lib/types/verification-records/index.d.ts +16 -0
  102. package/lib/types/verification-records/index.js +16 -0
  103. package/lib/types/verification-records/new-password-identity-verification.d.ts +85 -0
  104. package/lib/types/verification-records/new-password-identity-verification.js +20 -0
  105. package/lib/types/verification-records/one-time-token-verification.d.ts +55 -0
  106. package/lib/types/verification-records/one-time-token-verification.js +13 -0
  107. package/lib/types/verification-records/password-verification.d.ts +40 -0
  108. package/lib/types/verification-records/password-verification.js +9 -0
  109. package/lib/types/verification-records/social-verification.d.ts +270 -0
  110. package/lib/types/verification-records/social-verification.js +16 -0
  111. package/lib/types/verification-records/totp-verification.d.ts +47 -0
  112. package/lib/types/verification-records/totp-verification.js +12 -0
  113. package/lib/types/verification-records/web-authn-verification.d.ts +124 -0
  114. package/lib/types/verification-records/web-authn-verification.js +17 -0
  115. package/package.json +6 -6
  116. package/tables/account_centers.sql +2 -1
  117. package/tables/connectors.sql +4 -0
  118. package/tables/custom_profile_fields.sql +31 -0
  119. package/tables/oidc_model_instances.sql +2 -0
  120. package/tables/oidc_session_extensions.sql +18 -0
  121. package/tables/organization_user_relations.sql +4 -1
  122. package/tables/secret_enterprise_sso_connector_relations.sql +60 -0
  123. package/tables/secret_social_connector_relations.sql +75 -0
  124. package/tables/secrets.sql +26 -0
  125. package/tables/sso_connectors.sql +2 -0
  126. package/tables/user_sso_identities.sql +8 -0
  127. package/tables/users.sql +3 -2
  128. /package/lib/{foundations/jsonb-types/verification-records.d.ts → types/verification-records/verification-type.d.ts} +0 -0
  129. /package/lib/{foundations/jsonb-types/verification-records.js → types/verification-records/verification-type.js} +0 -0
@@ -0,0 +1,359 @@
1
+ /**
2
+ * @fileoverview
3
+ * This migration script alters the database schema to split the `secret_connector_relations` table into two separate tables:
4
+ * `secret_social_connector_relations` and `secret_enterprise_sso_connector_relations`.
5
+ */
6
+
7
+ import { sql } from '@silverhand/slonik';
8
+
9
+ import type { AlterationScript } from '../lib/types/alteration.js';
10
+
11
+ import { applyTableRls, dropTableRls } from './utils/1704934999-tables.js';
12
+
13
+ const alteration: AlterationScript = {
14
+ up: async (pool) => {
15
+ // Drop all triggers
16
+ await pool.query(sql`
17
+ drop trigger if exists delete_secrets_before_social_connector_delete on connectors;
18
+ drop function if exists delete_secrets_on_social_connector_delete();
19
+
20
+ drop trigger if exists delete_secrets_before_sso_connector_delete on sso_connectors;
21
+ drop function if exists delete_secrets_on_sso_connector_delete;
22
+
23
+ drop trigger if exists delete_secret_before_sso_identity_delete on user_sso_identities;
24
+ drop function if exists delete_secret_on_sso_identity_delete();
25
+
26
+ drop trigger if exists delete_secrets_before_social_identity_delete on users;
27
+ drop function if exists delete_secrets_on_social_identity_delete();
28
+ `);
29
+
30
+ // Drop the existing `secret_connector_relations` table
31
+ await pool.query(sql`
32
+ drop table if exists secret_connector_relations;
33
+ `);
34
+
35
+ // Create the new `secret_social_connector_relations` table
36
+ await pool.query(sql`
37
+ create table secret_social_connector_relations (
38
+ tenant_id varchar(21) not null
39
+ references tenants (id) on update cascade on delete cascade,
40
+ secret_id varchar(21) not null
41
+ references secrets (id) on update cascade on delete cascade,
42
+ /** 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.*/
43
+ connector_id varchar(128) not null
44
+ references connectors (id) on update cascade,
45
+ /** The target of the social connector. e.g. 'github', 'google', etc. */
46
+ target varchar(256) not null,
47
+ /** User social identity ID foreign reference. Only present for secrets that store social identity tokens. */
48
+ identity_id varchar(128) not null,
49
+ primary key (tenant_id, secret_id),
50
+ /** Ensures that each social identity is associated with only one secret. */
51
+ constraint secret_social_connector_relations__target__identity_id
52
+ unique (tenant_id, target, identity_id)
53
+ );
54
+ `);
55
+
56
+ // Create triggers for the new `secret_social_connector_relations` table
57
+ await pool.query(sql`
58
+ /** Trigger function to delete secrets when the social connector is deleted. */
59
+ create function delete_secrets_on_social_connector_delete()
60
+ returns trigger as $$
61
+ begin
62
+ delete from secrets
63
+ where id in (
64
+ select secret_id from secret_social_connector_relations
65
+ where tenant_id = old.tenant_id and connector_id = old.id
66
+ );
67
+ return old;
68
+ end;
69
+ $$ language plpgsql;
70
+
71
+ create trigger delete_secrets_before_social_connector_delete
72
+ before delete on connectors
73
+ for each row
74
+ execute procedure delete_secrets_on_social_connector_delete();
75
+
76
+ /** Trigger function to delete associated secrets when social identities are deleted. */
77
+ create function delete_secrets_on_social_identity_delete()
78
+ returns trigger as $$
79
+ declare
80
+ identity_target text;
81
+ old_identity jsonb;
82
+ new_identity jsonb;
83
+ begin
84
+ -- Loop over old identities to detect deletions or modifications
85
+ for identity_target in select jsonb_object_keys(old.identities)
86
+ loop
87
+ old_identity := old.identities -> identity_target;
88
+ new_identity := new.identities -> identity_target;
89
+
90
+ -- If the identity was deleted or modified, delete the associated secret
91
+ if new_identity is null or (new_identity->>'userId') is distinct from (old_identity->>'userId') then
92
+ -- Identity was removed or changed, delete the corresponding secrets
93
+ delete from secrets
94
+ using secret_social_connector_relations
95
+ where secrets.id = secret_social_connector_relations.secret_id
96
+ -- Ensure we are deleting the correct social identity
97
+ and secret_social_connector_relations.target = identity_target
98
+ and secret_social_connector_relations.identity_id = old_identity->>'userId'
99
+ -- Ensure we delete the correct user's secret
100
+ and secrets.user_id = old.id;
101
+ end if;
102
+ end loop;
103
+
104
+ return new;
105
+ end;
106
+ $$ language plpgsql;
107
+
108
+ create trigger delete_secrets_before_social_identity_delete
109
+ before update of identities on users
110
+ for each row
111
+ execute procedure delete_secrets_on_social_identity_delete();
112
+ `);
113
+
114
+ await applyTableRls(pool, 'secret_social_connector_relations');
115
+
116
+ // Create the new `secret_enterprise_sso_connector_relations` table
117
+ await pool.query(sql`
118
+ create table secret_enterprise_sso_connector_relations (
119
+ tenant_id varchar(21) not null
120
+ references tenants (id) on update cascade on delete cascade,
121
+ secret_id varchar(21) not null
122
+ references secrets (id) on update cascade on delete cascade,
123
+ /** 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.*/
124
+ sso_connector_id varchar(128) not null
125
+ references sso_connectors (id) on update cascade,
126
+ /** User SSO connector issuer. Only present for secrets that store SSO connector tokens. */
127
+ issuer varchar(256) not null,
128
+ /** User SSO identity ID. Only present for secrets that store SSO identity tokens. */
129
+ identity_id varchar(128) not null,
130
+ primary key (tenant_id, secret_id),
131
+ /** Ensures that each SSO identity is associated with only one secret. */
132
+ foreign key (tenant_id, issuer, identity_id)
133
+ references user_sso_identities (tenant_id, issuer, identity_id) on update cascade
134
+ );
135
+ `);
136
+
137
+ // Create triggers for the new `secret_enterprise_sso_connector_relations` table
138
+ await pool.query(sql`
139
+ /** Trigger function to delete secrets when the SSO connector is deleted. */
140
+ create function delete_secrets_on_sso_connector_delete()
141
+ returns trigger as $$
142
+ begin
143
+ delete from secrets
144
+ where id in (
145
+ select secret_id from secret_enterprise_sso_connector_relations
146
+ where tenant_id = old.tenant_id and sso_connector_id = old.id
147
+ );
148
+ return old;
149
+ end;
150
+ $$ language plpgsql;
151
+
152
+ create trigger delete_secrets_before_sso_connector_delete
153
+ before delete on sso_connectors
154
+ for each row
155
+ execute procedure delete_secrets_on_sso_connector_delete();
156
+
157
+ /** Trigger function to delete secret when the SSO identity is deleted. */
158
+ create function delete_secret_on_sso_identity_delete()
159
+ returns trigger as $$
160
+ begin
161
+ delete from secrets
162
+ where id in (
163
+ select secret_id from secret_enterprise_sso_connector_relations
164
+ where tenant_id = old.tenant_id
165
+ and issuer = old.issuer
166
+ and identity_id = old.identity_id
167
+ )
168
+ -- we also need to ensure that the secret is associated with the correct user
169
+ and user_id = old.user_id;
170
+ return old;
171
+ end;
172
+ $$ language plpgsql;
173
+
174
+ create trigger delete_secret_before_sso_identity_delete
175
+ before delete on user_sso_identities
176
+ for each row
177
+ execute procedure delete_secret_on_sso_identity_delete();
178
+ `);
179
+
180
+ await applyTableRls(pool, 'secret_enterprise_sso_connector_relations');
181
+ },
182
+ down: async (pool) => {
183
+ // Drop all triggers
184
+ await pool.query(sql`
185
+ drop trigger if exists delete_secrets_before_social_connector_delete on connectors;
186
+ drop function if exists delete_secrets_on_social_connector_delete;
187
+
188
+ drop trigger if exists delete_secrets_before_sso_connector_delete on sso_connectors;
189
+ drop function if exists delete_secrets_on_sso_connector_delete;
190
+
191
+ drop trigger if exists delete_secret_before_sso_identity_delete on user_sso_identities;
192
+ drop function if exists delete_secret_on_sso_identity_delete();
193
+
194
+ drop trigger if exists delete_secrets_before_social_identity_delete on users;
195
+ drop function if exists delete_secrets_on_social_identity_delete();
196
+ `);
197
+
198
+ // Drop the new `secret_social_connector_relations` table
199
+ await dropTableRls(pool, 'secret_social_connector_relations');
200
+ await pool.query(sql`
201
+ drop table if exists secret_social_connector_relations;
202
+ `);
203
+
204
+ // Drop the new `secret_enterprise_sso_connector_relations` table
205
+ await dropTableRls(pool, 'secret_enterprise_sso_connector_relations');
206
+ await pool.query(sql`
207
+ drop table if exists secret_enterprise_sso_connector_relations;
208
+ `);
209
+
210
+ // Create secret_connector_relations
211
+ await pool.query(sql`
212
+ create table secret_connector_relations (
213
+ tenant_id varchar(21) not null
214
+ references tenants (id) on update cascade on delete cascade,
215
+ secret_id varchar(21) not null
216
+ references secrets (id) on update cascade on delete cascade,
217
+ /** 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.*/
218
+ connector_id varchar(128)
219
+ references connectors (id) on update cascade,
220
+ /** 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.*/
221
+ sso_connector_id varchar(128)
222
+ references sso_connectors (id) on update cascade,
223
+ /** The target of the social connector. e.g. 'github', 'google', etc. */
224
+ social_connector_target varchar(256),
225
+ /** User social identity ID foreign reference. Only present for secrets that store social identity tokens. */
226
+ social_identity_id varchar(128),
227
+ /** User sso connector issuer. Only present for secrets that store SSO connector tokens. */
228
+ sso_connector_issuer varchar(256),
229
+ /** User SSO identity ID. Only present for secrets that store SSO identity tokens. */
230
+ sso_identity_id varchar(128),
231
+ primary key (tenant_id, secret_id),
232
+ /** Ensures that each social identity is associated with only one secret. */
233
+ constraint secret_connector_relations__target__social_identity_id
234
+ unique (tenant_id, social_connector_target, social_identity_id),
235
+ /** Ensures that each SSO identity is associated with only one secret. */
236
+ foreign key (tenant_id, sso_connector_issuer, sso_identity_id)
237
+ references user_sso_identities (tenant_id, issuer, identity_id) on update cascade,
238
+ /** Ensure that each secret is associated with a social connector or SSO connector, but not both at the same time. */
239
+ constraint secret_connector_relations__connector_id__sso_connector_id
240
+ check (
241
+ (
242
+ connector_id is not null and social_connector_target is not null and social_identity_id is not null and
243
+ sso_connector_id is null and sso_identity_id is null
244
+ ) or (
245
+ connector_id is null and social_connector_target is null and social_identity_id is null and
246
+ sso_connector_id is not null and sso_identity_id is not null
247
+ )
248
+ )
249
+ );
250
+ `);
251
+
252
+ await applyTableRls(pool, 'secret_connector_relations');
253
+
254
+ /** Trigger function to delete secrets when the social connector is deleted. */
255
+ await pool.query(sql`
256
+ create function delete_secrets_on_social_connector_delete()
257
+ returns trigger as $$
258
+ begin
259
+ delete from secrets
260
+ where id in (
261
+ select secret_id from secret_connector_relations
262
+ where tenant_id = old.tenant_id and connector_id = old.id
263
+ );
264
+ return old;
265
+ end;
266
+ $$ language plpgsql;
267
+
268
+ create trigger delete_secrets_before_social_connector_delete
269
+ before delete on connectors
270
+ for each row
271
+ execute procedure delete_secrets_on_social_connector_delete();
272
+ `);
273
+
274
+ /** Trigger function to delete secrets when the SSO connector is deleted. */
275
+ await pool.query(sql`
276
+ create function delete_secrets_on_sso_connector_delete()
277
+ returns trigger as $$
278
+ begin
279
+ delete from secrets
280
+ where id in (
281
+ select secret_id from secret_connector_relations
282
+ where tenant_id = old.tenant_id and sso_connector_id = old.id
283
+ );
284
+ return old;
285
+ end;
286
+ $$ language plpgsql;
287
+
288
+ create trigger delete_secrets_before_sso_connector_delete
289
+ before delete on sso_connectors
290
+ for each row
291
+ execute procedure delete_secrets_on_sso_connector_delete();
292
+ `);
293
+
294
+ /** Trigger function to delete secret when the SSO identity is deleted. */
295
+ await pool.query(sql`
296
+ create function delete_secret_on_sso_identity_delete()
297
+ returns trigger as $$
298
+ begin
299
+ delete from secrets
300
+ where id in (
301
+ select secret_id from secret_connector_relations
302
+ where tenant_id = old.tenant_id
303
+ and sso_connector_issuer = old.issuer
304
+ and sso_identity_id = old.identity_id
305
+ )
306
+ -- we also need to ensure that the secret is associated with the correct user
307
+ and user_id = old.user_id;
308
+ return old;
309
+ end;
310
+ $$ language plpgsql;
311
+
312
+ create trigger delete_secret_before_sso_identity_delete
313
+ before delete on user_sso_identities
314
+ for each row
315
+ execute procedure delete_secret_on_sso_identity_delete();
316
+ `);
317
+
318
+ /** Trigger function to delete associated secrets when social identities are deleted. */
319
+ await pool.query(sql`
320
+ create function delete_secrets_on_social_identity_delete()
321
+ returns trigger as $$
322
+ declare
323
+ target text;
324
+ old_identity jsonb;
325
+ new_identity jsonb;
326
+ begin
327
+ -- Loop over old identities to detect deletions or modifications
328
+ for target in select jsonb_object_keys(old.identities)
329
+ loop
330
+ old_identity := old.identities -> target;
331
+ new_identity := new.identities -> target;
332
+
333
+ -- If the identity was deleted or modified, delete the associated secret
334
+ if new_identity is null or (new_identity->>'userId') is distinct from (old_identity->>'userId') then
335
+ -- Identity was removed or changed, delete the corresponding secrets
336
+ delete from secrets
337
+ using secret_connector_relations
338
+ where secrets.id = secret_connector_relations.secret_id
339
+ -- Ensure we are deleting the correct social identity
340
+ and secret_connector_relations.social_connector_target = target
341
+ and secret_connector_relations.social_identity_id = old_identity->>'userId'
342
+ -- Ensure we delete the correct user's secret
343
+ and secrets.user_id = old.id;
344
+ end if;
345
+ end loop;
346
+
347
+ return new;
348
+ end;
349
+ $$ language plpgsql;
350
+
351
+ create trigger delete_secrets_before_social_identity_delete
352
+ before update of identities on users
353
+ for each row
354
+ execute procedure delete_secrets_on_social_identity_delete();
355
+ `);
356
+ },
357
+ };
358
+
359
+ 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 users
9
+ add column require_mfa_on_sign_in boolean not null default true;
10
+ `);
11
+ },
12
+ down: async (pool) => {
13
+ await pool.query(sql`
14
+ alter table users
15
+ drop column require_mfa_on_sign_in;
16
+ `);
17
+ },
18
+ };
19
+
20
+ export default alteration;
@@ -0,0 +1,21 @@
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
+ // No need to migrate existing data, as the feature is not released yet.
8
+ await pool.query(sql`
9
+ alter table users
10
+ drop column require_mfa_on_sign_in;
11
+ `);
12
+ },
13
+ down: async (pool) => {
14
+ await pool.query(sql`
15
+ alter table users
16
+ add column require_mfa_on_sign_in boolean not null default true;
17
+ `);
18
+ },
19
+ };
20
+
21
+ 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 sso_connectors
9
+ add column enable_token_storage boolean not null default FALSE;
10
+ `);
11
+ },
12
+ down: async (pool) => {
13
+ await pool.query(sql`
14
+ alter table sso_connectors
15
+ drop column if exists enable_token_storage;
16
+ `);
17
+ },
18
+ };
19
+
20
+ 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 account_centers
9
+ alter column enabled set default true;
10
+ `);
11
+ },
12
+ down: async (pool) => {
13
+ await pool.query(sql`
14
+ alter table account_centers
15
+ alter column enabled set default false;
16
+ `);
17
+ },
18
+ };
19
+
20
+ export default alteration;
@@ -0,0 +1,46 @@
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
+ // Drop the existing index in users table
8
+ await pool.query(sql`
9
+ drop index if exists users__id;
10
+ `);
11
+
12
+ // Create a new unique index in users table
13
+ await pool.query(sql`
14
+ create unique index users__id
15
+ on users (tenant_id, id);
16
+ `);
17
+
18
+ // Apply the foreign key constraint to organization_user_relations table
19
+ await pool.query(sql`
20
+ alter table organization_user_relations
21
+ add constraint organization_user_relations__user_id__fk
22
+ foreign key (tenant_id, user_id)
23
+ references users (tenant_id, id)
24
+ on update cascade on delete cascade;
25
+ `);
26
+ },
27
+ down: async (pool) => {
28
+ await pool.query(sql`
29
+ alter table organization_user_relations
30
+ drop constraint organization_user_relations__user_id__fk;
31
+ `);
32
+
33
+ // Drop the unique index in users table
34
+ await pool.query(sql`
35
+ drop index if exists users__id;
36
+ `);
37
+
38
+ // Recreate the old index in users table
39
+ await pool.query(sql`
40
+ create index users__id
41
+ on users (tenant_id, id);
42
+ `);
43
+ },
44
+ };
45
+
46
+ 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;