@logto/schemas 1.0.0-rc.0 → 1.0.7

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 (196) hide show
  1. package/LICENSE +6 -0
  2. package/README.md +24 -0
  3. package/alterations/1.0.0-1677208902-update-admin-console-config.ts +108 -0
  4. package/alterations/1.0.0-1677765137-seed-for-admin-tenant.ts +127 -0
  5. package/alterations/1.0.0-1677907982-allow-admin-create-multiple-tenants.ts +56 -0
  6. package/alterations/1.0.0-1678157950-privacy-policy-url.ts +20 -0
  7. package/alterations/1.0.0-1678199795-add-verification-status-table.ts +60 -0
  8. package/alterations/1.0.0-1678259693-remove-branding-style-config.ts +112 -0
  9. package/alterations/1.0.0-1678269972-use-restrictive-policies.ts +85 -0
  10. package/alterations/1.0.0-1678284778-restrict-internal-roles.ts +62 -0
  11. package/alterations/1.0.0-1678425761-m2m-app-for-tenants.ts +179 -0
  12. package/alterations/1.0.0-1678450233-support-custom-content.ts +20 -0
  13. package/alterations/1.0.0-1678716747-service-logs.ts +51 -0
  14. package/alterations/1.0.0-1678928481-remove-deprecated-logto-config-item.ts +84 -0
  15. package/alterations/1.0.0-1678953179-update-get-started-task-config.ts +102 -0
  16. package/alterations/1.0.0-1679209413-drop-connector-database-storage.ts +18 -0
  17. package/alterations/1.0.0_rc.1-1675788753-multi-tenancy-rls.ts +181 -0
  18. package/alterations/1.0.0_rc.1-1676115897-add-admin-tenant.ts +212 -0
  19. package/alterations/1.0.0_rc.1-1676185899-fix-logs-index.ts +32 -0
  20. package/alterations/1.0.0_rc.1-1676190092-migrate-admin-data.ts +208 -0
  21. package/alterations/1.0.0_rc.1-1676823841-update-sie-primary-key.ts +26 -0
  22. package/alterations/1.0.0_rc.1-1676874936-support-custom-css.ts +20 -0
  23. package/alterations/1.0.0_rc.1-1676886855-connector-database-read-write.ts +18 -0
  24. package/alterations/1.0.0_rc.1-1676906977-remove-demo-app.ts +50 -0
  25. package/alterations/1.0.0_rc.1-1676956206-move-console-sie-to-database.ts +92 -0
  26. package/alterations/1.0.0_rc.1-1677059985-move-console-application-to-database.ts +37 -0
  27. package/alterations-js/1.0.0-1677208902-update-admin-console-config.d.ts +3 -0
  28. package/alterations-js/1.0.0-1677208902-update-admin-console-config.js +41 -0
  29. package/alterations-js/1.0.0-1677765137-seed-for-admin-tenant.d.ts +3 -0
  30. package/alterations-js/1.0.0-1677765137-seed-for-admin-tenant.js +117 -0
  31. package/alterations-js/1.0.0-1677907982-allow-admin-create-multiple-tenants.d.ts +3 -0
  32. package/alterations-js/1.0.0-1677907982-allow-admin-create-multiple-tenants.js +48 -0
  33. package/alterations-js/1.0.0-1678157950-privacy-policy-url.d.ts +3 -0
  34. package/alterations-js/1.0.0-1678157950-privacy-policy-url.js +16 -0
  35. package/alterations-js/1.0.0-1678199795-add-verification-status-table.d.ts +3 -0
  36. package/alterations-js/1.0.0-1678199795-add-verification-status-table.js +51 -0
  37. package/alterations-js/1.0.0-1678259693-remove-branding-style-config.d.ts +3 -0
  38. package/alterations-js/1.0.0-1678259693-remove-branding-style-config.js +45 -0
  39. package/alterations-js/1.0.0-1678269972-use-restrictive-policies.d.ts +3 -0
  40. package/alterations-js/1.0.0-1678269972-use-restrictive-policies.js +70 -0
  41. package/alterations-js/1.0.0-1678284778-restrict-internal-roles.d.ts +3 -0
  42. package/alterations-js/1.0.0-1678284778-restrict-internal-roles.js +58 -0
  43. package/alterations-js/1.0.0-1678425761-m2m-app-for-tenants.d.ts +3 -0
  44. package/alterations-js/1.0.0-1678425761-m2m-app-for-tenants.js +158 -0
  45. package/alterations-js/1.0.0-1678450233-support-custom-content.d.ts +3 -0
  46. package/alterations-js/1.0.0-1678450233-support-custom-content.js +16 -0
  47. package/alterations-js/1.0.0-1678716747-service-logs.d.ts +3 -0
  48. package/alterations-js/1.0.0-1678716747-service-logs.js +42 -0
  49. package/alterations-js/1.0.0-1678928481-remove-deprecated-logto-config-item.d.ts +3 -0
  50. package/alterations-js/1.0.0-1678928481-remove-deprecated-logto-config-item.js +34 -0
  51. package/alterations-js/1.0.0-1678953179-update-get-started-task-config.d.ts +3 -0
  52. package/alterations-js/1.0.0-1678953179-update-get-started-task-config.js +35 -0
  53. package/alterations-js/1.0.0-1679209413-drop-connector-database-storage.d.ts +3 -0
  54. package/alterations-js/1.0.0-1679209413-drop-connector-database-storage.js +14 -0
  55. package/alterations-js/1.0.0_rc.1-1675788753-multi-tenancy-rls.d.ts +3 -0
  56. package/alterations-js/1.0.0_rc.1-1675788753-multi-tenancy-rls.js +152 -0
  57. package/alterations-js/1.0.0_rc.1-1676115897-add-admin-tenant.d.ts +3 -0
  58. package/alterations-js/1.0.0_rc.1-1676115897-add-admin-tenant.js +189 -0
  59. package/alterations-js/1.0.0_rc.1-1676185899-fix-logs-index.d.ts +3 -0
  60. package/alterations-js/1.0.0_rc.1-1676185899-fix-logs-index.js +28 -0
  61. package/alterations-js/1.0.0_rc.1-1676190092-migrate-admin-data.d.ts +3 -0
  62. package/alterations-js/1.0.0_rc.1-1676190092-migrate-admin-data.js +150 -0
  63. package/alterations-js/1.0.0_rc.1-1676823841-update-sie-primary-key.d.ts +3 -0
  64. package/alterations-js/1.0.0_rc.1-1676823841-update-sie-primary-key.js +22 -0
  65. package/alterations-js/1.0.0_rc.1-1676874936-support-custom-css.d.ts +3 -0
  66. package/alterations-js/1.0.0_rc.1-1676874936-support-custom-css.js +16 -0
  67. package/alterations-js/1.0.0_rc.1-1676886855-connector-database-read-write.d.ts +3 -0
  68. package/alterations-js/1.0.0_rc.1-1676886855-connector-database-read-write.js +14 -0
  69. package/alterations-js/1.0.0_rc.1-1676906977-remove-demo-app.d.ts +3 -0
  70. package/alterations-js/1.0.0_rc.1-1676906977-remove-demo-app.js +42 -0
  71. package/alterations-js/1.0.0_rc.1-1676956206-move-console-sie-to-database.d.ts +3 -0
  72. package/alterations-js/1.0.0_rc.1-1676956206-move-console-sie-to-database.js +86 -0
  73. package/alterations-js/1.0.0_rc.1-1677059985-move-console-application-to-database.d.ts +3 -0
  74. package/alterations-js/1.0.0_rc.1-1677059985-move-console-application-to-database.js +33 -0
  75. package/lib/api/error.d.ts +2 -2
  76. package/lib/consts/index.d.ts +2 -0
  77. package/lib/consts/index.js +2 -0
  78. package/lib/consts/oidc.d.ts +1 -0
  79. package/lib/consts/oidc.js +1 -0
  80. package/lib/consts/system.d.ts +11 -0
  81. package/lib/consts/system.js +11 -0
  82. package/lib/db-entries/-after-all.d.ts +1 -0
  83. package/lib/db-entries/-after-all.js +2 -0
  84. package/lib/db-entries/-after-each.d.ts +1 -0
  85. package/lib/db-entries/-after-each.js +2 -0
  86. package/lib/db-entries/-before-all.d.ts +1 -0
  87. package/lib/db-entries/-before-all.js +2 -0
  88. package/lib/db-entries/application.d.ts +1 -1
  89. package/lib/db-entries/applications-role.d.ts +1 -1
  90. package/lib/db-entries/connector.d.ts +1 -1
  91. package/lib/db-entries/custom-phrase.d.ts +1 -1
  92. package/lib/db-entries/hook.d.ts +16 -0
  93. package/lib/db-entries/hook.js +37 -0
  94. package/lib/db-entries/index.d.ts +6 -0
  95. package/lib/db-entries/index.js +6 -0
  96. package/lib/db-entries/log.d.ts +1 -1
  97. package/lib/db-entries/logto-config.d.ts +1 -1
  98. package/lib/db-entries/oidc-model-instance.d.ts +1 -1
  99. package/lib/db-entries/passcode.d.ts +1 -1
  100. package/lib/db-entries/resource.d.ts +1 -1
  101. package/lib/db-entries/role.d.ts +1 -1
  102. package/lib/db-entries/roles-scope.d.ts +1 -1
  103. package/lib/db-entries/scope.d.ts +1 -1
  104. package/lib/db-entries/service-log.d.ts +16 -0
  105. package/lib/db-entries/service-log.js +37 -0
  106. package/lib/db-entries/sign-in-experience.d.ts +8 -2
  107. package/lib/db-entries/sign-in-experience.js +13 -1
  108. package/lib/db-entries/system.d.ts +1 -1
  109. package/lib/db-entries/user.d.ts +1 -1
  110. package/lib/db-entries/users-role.d.ts +1 -1
  111. package/lib/db-entries/verification-status.d.ts +14 -0
  112. package/lib/db-entries/verification-status.js +32 -0
  113. package/lib/foundations/jsonb-types.d.ts +33 -40
  114. package/lib/foundations/jsonb-types.js +23 -32
  115. package/lib/foundations/schemas.d.ts +2 -2
  116. package/lib/index.d.ts +2 -0
  117. package/lib/index.js +2 -0
  118. package/lib/models/index.d.ts +0 -1
  119. package/lib/models/index.js +0 -1
  120. package/lib/models/tenants.d.ts +1 -0
  121. package/lib/models/tenants.js +5 -1
  122. package/lib/seeds/application.d.ts +6 -2
  123. package/lib/seeds/application.js +40 -6
  124. package/lib/seeds/cloud-api.d.ts +12 -0
  125. package/lib/seeds/cloud-api.js +46 -0
  126. package/lib/seeds/index.d.ts +2 -3
  127. package/lib/seeds/index.js +2 -3
  128. package/lib/seeds/logto-config.d.ts +4 -3
  129. package/lib/seeds/logto-config.js +8 -8
  130. package/lib/seeds/management-api.d.ts +50 -0
  131. package/lib/seeds/management-api.js +116 -0
  132. package/lib/seeds/sign-in-experience.d.ts +3 -1
  133. package/lib/seeds/sign-in-experience.js +19 -15
  134. package/lib/seeds/tenant.d.ts +1 -1
  135. package/lib/seeds/tenant.js +0 -4
  136. package/lib/types/connector.d.ts +6 -2
  137. package/lib/types/hook.d.ts +13 -0
  138. package/lib/types/hook.js +1 -0
  139. package/lib/types/index.d.ts +5 -0
  140. package/lib/types/index.js +5 -0
  141. package/lib/types/interactions.d.ts +30 -30
  142. package/lib/types/log/hook.d.ts +1 -1
  143. package/lib/types/logto-config.d.ts +26 -15
  144. package/lib/types/logto-config.js +17 -12
  145. package/lib/types/role.d.ts +1 -1
  146. package/lib/types/service-log.d.ts +4 -0
  147. package/lib/types/service-log.js +5 -0
  148. package/lib/types/system.d.ts +89 -3
  149. package/lib/types/system.js +59 -0
  150. package/lib/types/tenant.d.ts +4 -0
  151. package/lib/types/tenant.js +1 -0
  152. package/lib/types/theme.d.ts +4 -0
  153. package/lib/types/theme.js +5 -0
  154. package/lib/types/user-assets.d.ts +28 -0
  155. package/lib/types/user-assets.js +22 -0
  156. package/lib/types/user.d.ts +20 -4
  157. package/lib/types/user.js +22 -4
  158. package/lib/types/verification-code.d.ts +8 -8
  159. package/lib/utils/index.d.ts +2 -0
  160. package/lib/utils/index.js +2 -0
  161. package/lib/utils/management-api.d.ts +1 -0
  162. package/lib/utils/management-api.js +1 -0
  163. package/lib/utils/role.d.ts +2 -0
  164. package/lib/utils/role.js +2 -0
  165. package/package.json +17 -15
  166. package/tables/_after_all.sql +61 -0
  167. package/tables/_after_each.sql +13 -0
  168. package/tables/_before_all.sql +3 -0
  169. package/tables/_functions.sql +8 -6
  170. package/tables/applications.sql +0 -3
  171. package/tables/applications_roles.sql +0 -3
  172. package/tables/connectors.sql +0 -3
  173. package/tables/custom_phrases.sql +0 -3
  174. package/tables/hooks.sql +13 -0
  175. package/tables/logs.sql +2 -5
  176. package/tables/logto_configs.sql +0 -3
  177. package/tables/oidc_model_instances.sql +0 -3
  178. package/tables/passcodes.sql +1 -4
  179. package/tables/resources.sql +0 -3
  180. package/tables/roles.sql +0 -3
  181. package/tables/roles_scopes.sql +0 -3
  182. package/tables/scopes.sql +0 -3
  183. package/tables/service_logs.sql +17 -0
  184. package/tables/sign_in_experiences.sql +4 -7
  185. package/tables/systems.sql +2 -0
  186. package/tables/users.sql +10 -7
  187. package/tables/users_roles.sql +0 -3
  188. package/tables/verification_statuses.sql +15 -0
  189. package/lib/models/hooks.d.ts +0 -44
  190. package/lib/models/hooks.js +0 -28
  191. package/lib/seeds/resource.d.ts +0 -3
  192. package/lib/seeds/resource.js +0 -13
  193. package/lib/seeds/roles.d.ts +0 -8
  194. package/lib/seeds/roles.js +0 -20
  195. package/lib/seeds/scope.d.ts +0 -3
  196. package/lib/seeds/scope.js +0 -10
package/LICENSE CHANGED
@@ -1,3 +1,9 @@
1
+ Portions of this software are licensed as follows:
2
+
3
+ * All content that resides under the "packages/cloud" directory of this repository, if that directory exists, is licensed under the license defined in "packages/cloud/LICENSE" (Elastic-2.0).
4
+ * All third party components incorporated into this software are licensed under the original license provided by the owner of the applicable component.
5
+ * Content outside of the above mentioned directories or restrictions above is available under the "MPL-2.0" license as defined below.
6
+
1
7
  Mozilla Public License Version 2.0
2
8
  ==================================
3
9
 
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # @logto/schemas
2
+
3
+ The central packages for all database schemas and their TypeScript definitions and utilities.
4
+
5
+ ## Table init
6
+
7
+ The Logto CLI will pick up all necessary SQL queries in `tables/` and `src/models/` and run them in the following order:
8
+
9
+ 1. Run `tables/_before_all.sql`
10
+ 2. Run `tables/*.sql` with the snippet `/* init_order = <number> */` in ascending order of `<number>`
11
+ 3. Run `tables/*.sql` without the `init_order` snippet in ascending order of filename (`tables/`) or table name (`src/models/`)
12
+ 4. Run `tables/_after_all.sql`
13
+
14
+ Additional rules for step 2 and 3:
15
+
16
+ - If no snippet `/* no_after_each */` found, run `tables/_after_each.sql` after each SQL file
17
+ - Exclude lifecycle scripts `tables/_[lifecycle].sql` where `[lifecycle]` could be one of:
18
+ - `after_all`
19
+ - `after_each`
20
+ - `before_all`
21
+
22
+ In the `after_each` lifecycle script, you can use `${name}` to represent the current filename (`tables/`) or table name (`src/models/`).
23
+
24
+ In all lifecycle scripts, you can use `${database}` to represent the current database.
@@ -0,0 +1,108 @@
1
+ import type { DatabaseTransactionConnection } from 'slonik';
2
+ import { sql } from 'slonik';
3
+
4
+ import type { AlterationScript } from '../lib/types/alteration.js';
5
+
6
+ const adminConsoleConfigKey = 'adminConsole';
7
+
8
+ type DeprecatedAdminConsoleData = {
9
+ demoChecked: boolean;
10
+ applicationCreated: boolean;
11
+ signInExperienceCustomized: boolean;
12
+ passwordlessConfigured: boolean;
13
+ socialSignInConfigured: boolean;
14
+ furtherReadingsChecked: boolean;
15
+ } & Record<string, unknown>;
16
+
17
+ type DeprecatedLogtoAdminConsoleConfig = {
18
+ tenantId: string;
19
+ value: DeprecatedAdminConsoleData;
20
+ };
21
+
22
+ type AdminConsoleData = {
23
+ livePreviewChecked: boolean;
24
+ applicationCreated: boolean;
25
+ signInExperienceCustomized: boolean;
26
+ passwordlessConfigured: boolean;
27
+ selfHostingChecked: boolean;
28
+ communityChecked: boolean;
29
+ m2mApplicationCreated: boolean;
30
+ } & Record<string, unknown>;
31
+
32
+ type LogtoAdminConsoleConfig = {
33
+ tenantId: string;
34
+ value: AdminConsoleData;
35
+ };
36
+
37
+ const alterAdminConsoleData = async (
38
+ logtoConfig: DeprecatedLogtoAdminConsoleConfig,
39
+ pool: DatabaseTransactionConnection
40
+ ) => {
41
+ const { tenantId, value: adminConsoleConfig } = logtoConfig;
42
+
43
+ const {
44
+ demoChecked,
45
+ socialSignInConfigured, // Extract to remove from config
46
+ furtherReadingsChecked, // Extract to remove from config
47
+ ...others
48
+ } = adminConsoleConfig;
49
+
50
+ const newAdminConsoleData: AdminConsoleData = {
51
+ ...others,
52
+ livePreviewChecked: demoChecked,
53
+ selfHostingChecked: false,
54
+ communityChecked: false,
55
+ m2mApplicationCreated: false,
56
+ };
57
+
58
+ await pool.query(
59
+ sql`update logto_configs set value = ${JSON.stringify(
60
+ newAdminConsoleData
61
+ )} where tenant_id = ${tenantId} and key = ${adminConsoleConfigKey}`
62
+ );
63
+ };
64
+
65
+ const rollbackAdminConsoleData = async (
66
+ logtoConfig: LogtoAdminConsoleConfig,
67
+ pool: DatabaseTransactionConnection
68
+ ) => {
69
+ const { tenantId, value: adminConsoleConfig } = logtoConfig;
70
+
71
+ const {
72
+ livePreviewChecked,
73
+ selfHostingChecked, // Extract to remove from config
74
+ communityChecked, // Extract to remove from config
75
+ m2mApplicationCreated, // Extract to remove from config
76
+ ...others
77
+ } = adminConsoleConfig;
78
+
79
+ const originAdminConsoleData: DeprecatedAdminConsoleData = {
80
+ ...others,
81
+ demoChecked: livePreviewChecked,
82
+ socialSignInConfigured: false,
83
+ furtherReadingsChecked: false,
84
+ };
85
+
86
+ await pool.query(
87
+ sql`update logto_configs set value = ${JSON.stringify(
88
+ originAdminConsoleData
89
+ )} where tenant_id = ${tenantId} and key = ${adminConsoleConfigKey}`
90
+ );
91
+ };
92
+
93
+ const alteration: AlterationScript = {
94
+ up: async (pool) => {
95
+ const rows = await pool.many<DeprecatedLogtoAdminConsoleConfig>(
96
+ sql`select * from logto_configs where key = ${adminConsoleConfigKey}`
97
+ );
98
+ await Promise.all(rows.map(async (row) => alterAdminConsoleData(row, pool)));
99
+ },
100
+ down: async (pool) => {
101
+ const rows = await pool.many<LogtoAdminConsoleConfig>(
102
+ sql`select * from logto_configs where key = ${adminConsoleConfigKey}`
103
+ );
104
+ await Promise.all(rows.map(async (row) => rollbackAdminConsoleData(row, pool)));
105
+ },
106
+ };
107
+
108
+ export default alteration;
@@ -0,0 +1,127 @@
1
+ import { generateStandardId } from '@logto/core-kit';
2
+ import type { CommonQueryMethods } from 'slonik';
3
+ import { sql } from 'slonik';
4
+
5
+ import type { AlterationScript } from '../lib/types/alteration.js';
6
+
7
+ const adminTenantId = 'admin';
8
+
9
+ const addApiData = async (pool: CommonQueryMethods) => {
10
+ const adminApi = {
11
+ resourceId: generateStandardId(),
12
+ scopeId: generateStandardId(),
13
+ };
14
+ const cloudApi = {
15
+ resourceId: generateStandardId(),
16
+ scopeId: generateStandardId(),
17
+ };
18
+ const adminRole = {
19
+ id: generateStandardId(),
20
+ name: 'admin:admin',
21
+ description: 'Admin role for Logto.',
22
+ };
23
+
24
+ await pool.query(sql`
25
+ insert into resources (tenant_id, id, indicator, name)
26
+ values (
27
+ ${adminTenantId},
28
+ ${adminApi.resourceId},
29
+ 'https://admin.logto.app/api',
30
+ 'Logto Management API for tenant admin'
31
+ ), (
32
+ ${adminTenantId},
33
+ ${cloudApi.resourceId},
34
+ 'https://cloud.logto.io/api',
35
+ 'Logto Cloud API'
36
+ );
37
+ `);
38
+ await pool.query(sql`
39
+ insert into scopes (tenant_id, id, name, description, resource_id)
40
+ values (
41
+ ${adminTenantId},
42
+ ${adminApi.scopeId},
43
+ 'all',
44
+ 'Default scope for Management API, allows all permissions.',
45
+ ${adminApi.resourceId}
46
+ ), (
47
+ ${adminTenantId},
48
+ ${cloudApi.scopeId},
49
+ 'create:tenant',
50
+ 'Allow creating new tenants.',
51
+ ${cloudApi.resourceId}
52
+ );
53
+ `);
54
+ await pool.query(sql`
55
+ insert into roles (tenant_id, id, name, description)
56
+ values (
57
+ ${adminTenantId},
58
+ ${adminRole.id},
59
+ ${adminRole.name},
60
+ ${adminRole.description}
61
+ );
62
+ `);
63
+
64
+ const { id: userRoleId } = await pool.one<{ id: string }>(sql`
65
+ select id from roles
66
+ where tenant_id = ${adminTenantId}
67
+ and name = 'user'
68
+ `);
69
+
70
+ await pool.query(sql`
71
+ insert into roles_scopes (tenant_id, id, role_id, scope_id)
72
+ values (
73
+ ${adminTenantId},
74
+ ${generateStandardId()},
75
+ ${userRoleId},
76
+ ${cloudApi.scopeId}
77
+ ), (
78
+ ${adminTenantId},
79
+ ${generateStandardId()},
80
+ ${adminRole.id},
81
+ ${adminApi.scopeId}
82
+ );
83
+ `);
84
+ };
85
+
86
+ const alteration: AlterationScript = {
87
+ up: async (pool) => {
88
+ await addApiData(pool);
89
+ await pool.query(sql`
90
+ insert into logto_configs (tenant_id, key, value)
91
+ values (
92
+ ${adminTenantId},
93
+ 'adminConsole',
94
+ ${sql.jsonb({
95
+ language: 'en',
96
+ appearanceMode: 'system',
97
+ livePreviewChecked: false,
98
+ applicationCreated: false,
99
+ signInExperienceCustomized: false,
100
+ passwordlessConfigured: false,
101
+ selfHostingChecked: false,
102
+ communityChecked: false,
103
+ m2mApplicationCreated: false,
104
+ })}
105
+ );
106
+ `);
107
+ },
108
+ down: async (pool) => {
109
+ await pool.query(sql`
110
+ delete from resources
111
+ where tenant_id = ${adminTenantId}
112
+ and indicator in ('https://admin.logto.app/api', 'https://cloud.logto.io/api');
113
+ `);
114
+ await pool.query(sql`
115
+ delete from roles
116
+ where tenant_id = ${adminTenantId}
117
+ and name = 'admin:admin';
118
+ `);
119
+ await pool.query(sql`
120
+ delete from logto_configs
121
+ where tenant_id = ${adminTenantId}
122
+ and key = 'adminConsole';
123
+ `);
124
+ },
125
+ };
126
+
127
+ export default alteration;
@@ -0,0 +1,56 @@
1
+ import { generateStandardId } from '@logto/core-kit';
2
+ import { sql } from 'slonik';
3
+
4
+ import type { AlterationScript } from '../lib/types/alteration.js';
5
+
6
+ const adminTenantId = 'admin';
7
+
8
+ const alteration: AlterationScript = {
9
+ up: async (pool) => {
10
+ const scopeId = generateStandardId();
11
+ const { id: resourceId } = await pool.one<{ id: string }>(sql`
12
+ select id from resources
13
+ where tenant_id = ${adminTenantId}
14
+ and indicator = 'https://cloud.logto.io/api'
15
+ `);
16
+
17
+ await pool.query(sql`
18
+ insert into scopes (tenant_id, id, name, description, resource_id)
19
+ values (
20
+ ${adminTenantId},
21
+ ${scopeId},
22
+ 'manage:tenant',
23
+ 'Allow managing existing tenants, including create without limitation, update, and delete.',
24
+ ${resourceId}
25
+ );
26
+ `);
27
+
28
+ const { id: roleId } = await pool.one<{ id: string }>(sql`
29
+ select id from roles
30
+ where tenant_id = ${adminTenantId}
31
+ and name = 'admin:admin'
32
+ `);
33
+
34
+ await pool.query(sql`
35
+ insert into roles_scopes (tenant_id, id, role_id, scope_id)
36
+ values (
37
+ ${adminTenantId},
38
+ ${generateStandardId()},
39
+ ${roleId},
40
+ ${scopeId}
41
+ );
42
+ `);
43
+ },
44
+ down: async (pool) => {
45
+ await pool.query(sql`
46
+ delete from scopes
47
+ using resources
48
+ where resources.id = scopes.resource_id
49
+ and scopes.tenant_id = ${adminTenantId}
50
+ and resources.indicator = 'https://cloud.logto.io/api'
51
+ and scopes.name='manage:tenant';
52
+ `);
53
+ },
54
+ };
55
+
56
+ export default alteration;
@@ -0,0 +1,20 @@
1
+ import { sql } from '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 sign_in_experiences
9
+ add column if not exists privacy_policy_url varchar(2048);
10
+ `);
11
+ },
12
+ down: async (pool) => {
13
+ await pool.query(sql`
14
+ alter table sign_in_experiences
15
+ drop column privacy_policy_url;
16
+ `);
17
+ },
18
+ };
19
+
20
+ export default alteration;
@@ -0,0 +1,60 @@
1
+ import type { CommonQueryMethods } from 'slonik';
2
+ import { sql } from 'slonik';
3
+
4
+ import type { AlterationScript } from '../lib/types/alteration.js';
5
+
6
+ const getId = (value: string) => sql.identifier([value]);
7
+
8
+ const getDatabaseName = async (pool: CommonQueryMethods) => {
9
+ const { currentDatabase } = await pool.one<{ currentDatabase: string }>(sql`
10
+ select current_database();
11
+ `);
12
+
13
+ return currentDatabase.replaceAll('-', '_');
14
+ };
15
+
16
+ const alteration: AlterationScript = {
17
+ up: async (pool) => {
18
+ const database = await getDatabaseName(pool);
19
+ const baseRoleId = getId(`logto_tenant_${database}`);
20
+
21
+ await pool.query(sql`
22
+ create table verification_statuses (
23
+ tenant_id varchar(21) not null
24
+ references tenants (id) on update cascade on delete cascade,
25
+ id varchar(21) not null,
26
+ user_id varchar(21) not null
27
+ references users (id) on update cascade on delete cascade,
28
+ created_at timestamptz not null default(now()),
29
+ primary key (id)
30
+ );
31
+
32
+ create index verification_statuses__id
33
+ on verification_statuses (tenant_id, id);
34
+
35
+ create index verification_statuses__user_id
36
+ on verification_statuses (tenant_id, user_id);
37
+
38
+ create trigger set_tenant_id before insert on verification_statuses
39
+ for each row execute procedure set_tenant_id();
40
+
41
+ alter table verification_statuses enable row level security;
42
+
43
+ create policy verification_statuses_tenant_id on verification_statuses to ${baseRoleId}
44
+ using (tenant_id = (select id from tenants where db_user = current_user));
45
+
46
+ grant select, insert, update, delete on verification_statuses to ${baseRoleId};
47
+ `);
48
+ },
49
+ down: async (pool) => {
50
+ await pool.query(sql`
51
+ drop policy verification_statuses_tenant_id on verification_statuses;
52
+
53
+ alter table verification_statuses disable row level security;
54
+
55
+ drop table verification_statuses;
56
+ `);
57
+ },
58
+ };
59
+
60
+ export default alteration;
@@ -0,0 +1,112 @@
1
+ import type { DatabaseTransactionConnection } from 'slonik';
2
+ import { sql } from 'slonik';
3
+
4
+ import type { AlterationScript } from '../lib/types/alteration.js';
5
+
6
+ enum DeprecatedBrandingStyle {
7
+ Logo = 'Logo',
8
+ Logo_Slogan = 'Logo_Slogan',
9
+ }
10
+
11
+ const deprecatedDefaultBrandingStyle = DeprecatedBrandingStyle.Logo_Slogan;
12
+ const deprecatedDefaultSlogan = 'admin_console.welcome.title';
13
+
14
+ type DeprecatedBranding = {
15
+ style?: DeprecatedBrandingStyle;
16
+ logoUrl?: string;
17
+ darkLogoUrl?: string;
18
+ favicon?: string;
19
+ slogan?: string;
20
+ };
21
+
22
+ type DeprecatedSignInExperience = {
23
+ id: string;
24
+ tenantId: string;
25
+ branding: DeprecatedBranding;
26
+ };
27
+
28
+ type Branding = {
29
+ logoUrl?: string;
30
+ darkLogoUrl?: string;
31
+ favicon?: string;
32
+ };
33
+
34
+ type SignInExperience = {
35
+ id: string;
36
+ tenantId: string;
37
+ branding: Branding;
38
+ };
39
+
40
+ const alterBranding = async (
41
+ signInExperience: DeprecatedSignInExperience,
42
+ pool: DatabaseTransactionConnection
43
+ ) => {
44
+ const { id, tenantId, branding: originBranding } = signInExperience;
45
+
46
+ const {
47
+ style, // Extract to remove from branding
48
+ slogan, // Extract to remove from branding
49
+ logoUrl,
50
+ darkLogoUrl,
51
+ favicon,
52
+ } = originBranding;
53
+
54
+ const branding: Branding = { logoUrl, darkLogoUrl, favicon };
55
+
56
+ await pool.query(
57
+ sql`update sign_in_experiences set branding = ${JSON.stringify(
58
+ branding
59
+ )} where id = ${id} and tenant_id = ${tenantId}`
60
+ );
61
+ };
62
+
63
+ const rollbackBranding = async (
64
+ signInExperience: SignInExperience,
65
+ pool: DatabaseTransactionConnection
66
+ ) => {
67
+ const {
68
+ id,
69
+ tenantId,
70
+ branding: { logoUrl, darkLogoUrl, favicon },
71
+ } = signInExperience;
72
+
73
+ const adminBranding: DeprecatedBranding = {
74
+ style: DeprecatedBrandingStyle.Logo_Slogan,
75
+ slogan: 'admin_console.welcome.title',
76
+ logoUrl,
77
+ darkLogoUrl,
78
+ favicon,
79
+ };
80
+
81
+ const defaultBranding: DeprecatedBranding = {
82
+ style: DeprecatedBrandingStyle.Logo,
83
+ logoUrl,
84
+ darkLogoUrl,
85
+ favicon,
86
+ };
87
+
88
+ const branding: DeprecatedBranding = tenantId === 'admin' ? adminBranding : defaultBranding;
89
+
90
+ await pool.query(
91
+ sql`update sign_in_experiences set branding = ${JSON.stringify(
92
+ branding
93
+ )} where id = ${id} and tenant_id = ${tenantId}`
94
+ );
95
+ };
96
+
97
+ const alteration: AlterationScript = {
98
+ up: async (pool) => {
99
+ const rows = await pool.many<DeprecatedSignInExperience>(
100
+ sql`select * from sign_in_experiences`
101
+ );
102
+
103
+ await Promise.all(rows.map(async (row) => alterBranding(row, pool)));
104
+ },
105
+ down: async (pool) => {
106
+ const rows = await pool.many<SignInExperience>(sql`select * from sign_in_experiences`);
107
+
108
+ await Promise.all(rows.map(async (row) => rollbackBranding(row, pool)));
109
+ },
110
+ };
111
+
112
+ export default alteration;
@@ -0,0 +1,85 @@
1
+ import type { CommonQueryMethods } from 'slonik';
2
+ import { sql } from 'slonik';
3
+
4
+ import type { AlterationScript } from '../lib/types/alteration.js';
5
+
6
+ const tables = [
7
+ 'applications_roles',
8
+ 'applications',
9
+ 'connectors',
10
+ 'custom_phrases',
11
+ 'logs',
12
+ 'logto_configs',
13
+ 'oidc_model_instances',
14
+ 'passcodes',
15
+ 'resources',
16
+ 'roles_scopes',
17
+ 'roles',
18
+ 'scopes',
19
+ 'sign_in_experiences',
20
+ 'users_roles',
21
+ 'users',
22
+ 'verification_statuses',
23
+ 'hooks',
24
+ ];
25
+
26
+ const getDatabaseName = async (pool: CommonQueryMethods) => {
27
+ const { currentDatabase } = await pool.one<{ currentDatabase: string }>(sql`
28
+ select current_database();
29
+ `);
30
+
31
+ return currentDatabase.replaceAll('-', '_');
32
+ };
33
+
34
+ const alteration: AlterationScript = {
35
+ up: async (pool) => {
36
+ await Promise.all(
37
+ tables.map(async (tableRaw) => {
38
+ const table = sql.identifier([tableRaw]);
39
+ const tenantIdPolicy = sql.identifier([`${tableRaw}_tenant_id`]);
40
+ const modificationPolicy = sql.identifier([`${tableRaw}_modification`]);
41
+
42
+ await pool.query(sql`
43
+ drop policy ${tenantIdPolicy} on ${table};
44
+ create policy ${tenantIdPolicy} on ${table}
45
+ as restrictive
46
+ using (tenant_id = (select id from tenants where db_user = current_user));
47
+ create policy ${modificationPolicy} on ${table}
48
+ using (true);
49
+ `);
50
+ })
51
+ );
52
+ await pool.query(sql`
53
+ drop policy tenants_tenant_id on tenants;
54
+ create policy tenants_tenant_id on tenants
55
+ using (db_user = current_user);
56
+ `);
57
+ },
58
+ down: async (pool) => {
59
+ const role = sql.identifier([`logto_tenant_${await getDatabaseName(pool)}`]);
60
+
61
+ await Promise.all(
62
+ tables.map(async (tableRaw) => {
63
+ const table = sql.identifier([tableRaw]);
64
+ const tenantIdPolicy = sql.identifier([`${tableRaw}_tenant_id`]);
65
+ const modificationPolicy = sql.identifier([`${tableRaw}_modification`]);
66
+
67
+ await pool.query(sql`
68
+ drop policy ${tenantIdPolicy} on ${table};
69
+ drop policy ${modificationPolicy} on ${table};
70
+ create policy ${tenantIdPolicy} on ${table}
71
+ to ${role}
72
+ using (tenant_id = (select id from tenants where db_user = current_user));
73
+ `);
74
+ })
75
+ );
76
+ await pool.query(sql`
77
+ drop policy tenants_tenant_id on tenants;
78
+ create policy tenants_tenant_id on tenants
79
+ to ${role}
80
+ using (db_user = current_user);
81
+ `);
82
+ },
83
+ };
84
+
85
+ export default alteration;
@@ -0,0 +1,62 @@
1
+ import { sql } from '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
+ update roles
9
+ set name = '#internal:admin', description = 'Internal admin role for Logto tenant ' || tenant_id || '.'
10
+ where name = 'admin'
11
+ and tenant_id != 'admin';
12
+
13
+ update roles
14
+ set description = 'Admin tenant admin role for Logto tenant ' || substring(name from 0 for strpos(name, ':admin')) || '.'
15
+ where name like '%:admin'
16
+ and tenant_id = 'admin';
17
+
18
+ -- Restrict direct role modification
19
+ create policy roles_select on roles
20
+ for select using (true);
21
+
22
+ drop policy roles_modification on roles;
23
+ create policy roles_modification on roles
24
+ using (not starts_with(name, '#internal:'));
25
+
26
+ -- Restrict role - scope modification
27
+ create policy roles_scopes_select on roles_scopes
28
+ for select using (true);
29
+
30
+ drop policy roles_scopes_modification on roles_scopes;
31
+ create policy roles_scopes_modification on roles_scopes
32
+ using (not starts_with((select roles.name from roles where roles.id = role_id), '#internal:'));
33
+ `);
34
+ },
35
+ down: async (pool) => {
36
+ await pool.query(sql`
37
+ update roles
38
+ set name = 'admin', description = 'Admin role for Logto.'
39
+ where name = '#internal:admin'
40
+ and tenant_id != 'admin';
41
+
42
+ update roles
43
+ set description = 'Admin role for Logto.'
44
+ where name like '%:admin'
45
+ and tenant_id = 'admin';
46
+
47
+ drop policy roles_select on roles;
48
+ drop policy roles_modification on roles;
49
+
50
+ create policy roles_modification on roles
51
+ using (true);
52
+
53
+ drop policy roles_scopes_select on roles_scopes;
54
+ drop policy roles_scopes_modification on roles_scopes;
55
+
56
+ create policy roles_scopes_modification on roles_scopes
57
+ using (true);
58
+ `);
59
+ },
60
+ };
61
+
62
+ export default alteration;