@logto/schemas 1.11.0 → 1.13.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 (158) hide show
  1. package/alterations/1.12.0-1700031616-update-org-role-foreign-keys.ts +35 -0
  2. package/alterations/1.12.0-1701054133-add-unique-constraint-to-the-sso-connector-name.ts +21 -0
  3. package/alterations/1.12.0-1701245520-add-single-sign-on-enabled-flag-to-sie.ts +20 -0
  4. package/alterations/1.13.0-1702274830-add-new-third-party-column-to-applications-table.ts +20 -0
  5. package/alterations/1.13.0-1702372401-add-application-permissions-tables.ts +93 -0
  6. package/alterations/1.13.0-1702544178-sync-tenant-orgs.ts +296 -0
  7. package/alterations/1.13.0-1702871078-protected-application-type.ts +24 -0
  8. package/alterations/1.13.0-1702877515-protected-app-configs.ts +18 -0
  9. package/alterations/1.13.0-1702978120-application-sign-in-experience-table.ts +61 -0
  10. package/alterations/1.13.0-1703229996-daily-token-usage.ts +62 -0
  11. package/alterations/1.13.0-1703230000-update-tenant-roles.ts +94 -0
  12. package/alterations/1.13.0-1704692973-remove-legacy-resources.ts +147 -0
  13. package/alterations/1.13.0-1704934999-add-magic-links-table.ts +37 -0
  14. package/alterations/1.13.0-1704935001-add-organization-invitation-tables.ts +78 -0
  15. package/alterations/1.13.0-1705288654-add-application-user-consent-organizations-table.ts +62 -0
  16. package/alterations/1.13.0-1705991158-update-invitation-indices.ts +32 -0
  17. package/alterations/1.13.0-1706449174-update-organization-invitation-column.ts +24 -0
  18. package/alterations/1.13.0-1706510290-protected-app-host-index.ts +21 -0
  19. package/alterations/1.13.0-1706512952-restore-get-started-page.ts +17 -0
  20. package/alterations/1.13.0-1706528755-remove-magic-links.ts +46 -0
  21. package/alterations/1.13.0-1706585206-protected-app-custom-domain-unique.ts +21 -0
  22. package/alterations/utils/1704934999-tables.ts +49 -0
  23. package/alterations/utils/README.md +9 -0
  24. package/alterations-js/1.12.0-1700031616-update-org-role-foreign-keys.d.ts +3 -0
  25. package/alterations-js/1.12.0-1700031616-update-org-role-foreign-keys.js +31 -0
  26. package/alterations-js/1.12.0-1701054133-add-unique-constraint-to-the-sso-connector-name.d.ts +3 -0
  27. package/alterations-js/1.12.0-1701054133-add-unique-constraint-to-the-sso-connector-name.js +17 -0
  28. package/alterations-js/1.12.0-1701245520-add-single-sign-on-enabled-flag-to-sie.d.ts +3 -0
  29. package/alterations-js/1.12.0-1701245520-add-single-sign-on-enabled-flag-to-sie.js +16 -0
  30. package/alterations-js/1.13.0-1702274830-add-new-third-party-column-to-applications-table.d.ts +3 -0
  31. package/alterations-js/1.13.0-1702274830-add-new-third-party-column-to-applications-table.js +16 -0
  32. package/alterations-js/1.13.0-1702372401-add-application-permissions-tables.d.ts +3 -0
  33. package/alterations-js/1.13.0-1702372401-add-application-permissions-tables.js +79 -0
  34. package/alterations-js/1.13.0-1702544178-sync-tenant-orgs.d.ts +18 -0
  35. package/alterations-js/1.13.0-1702544178-sync-tenant-orgs.js +225 -0
  36. package/alterations-js/1.13.0-1702871078-protected-application-type.d.ts +3 -0
  37. package/alterations-js/1.13.0-1702871078-protected-application-type.js +20 -0
  38. package/alterations-js/1.13.0-1702877515-protected-app-configs.d.ts +3 -0
  39. package/alterations-js/1.13.0-1702877515-protected-app-configs.js +14 -0
  40. package/alterations-js/1.13.0-1702978120-application-sign-in-experience-table.d.ts +3 -0
  41. package/alterations-js/1.13.0-1702978120-application-sign-in-experience-table.js +51 -0
  42. package/alterations-js/1.13.0-1703229996-daily-token-usage.d.ts +3 -0
  43. package/alterations-js/1.13.0-1703229996-daily-token-usage.js +51 -0
  44. package/alterations-js/1.13.0-1703230000-update-tenant-roles.d.ts +11 -0
  45. package/alterations-js/1.13.0-1703230000-update-tenant-roles.js +87 -0
  46. package/alterations-js/1.13.0-1704692973-remove-legacy-resources.d.ts +3 -0
  47. package/alterations-js/1.13.0-1704692973-remove-legacy-resources.js +124 -0
  48. package/alterations-js/1.13.0-1704934999-add-magic-links-table.d.ts +3 -0
  49. package/alterations-js/1.13.0-1704934999-add-magic-links-table.js +32 -0
  50. package/alterations-js/1.13.0-1704935001-add-organization-invitation-tables.d.ts +3 -0
  51. package/alterations-js/1.13.0-1704935001-add-organization-invitation-tables.js +72 -0
  52. package/alterations-js/1.13.0-1705288654-add-application-user-consent-organizations-table.d.ts +3 -0
  53. package/alterations-js/1.13.0-1705288654-add-application-user-consent-organizations-table.js +52 -0
  54. package/alterations-js/1.13.0-1705991158-update-invitation-indices.d.ts +7 -0
  55. package/alterations-js/1.13.0-1705991158-update-invitation-indices.js +27 -0
  56. package/alterations-js/1.13.0-1706449174-update-organization-invitation-column.d.ts +3 -0
  57. package/alterations-js/1.13.0-1706449174-update-organization-invitation-column.js +20 -0
  58. package/alterations-js/1.13.0-1706510290-protected-app-host-index.d.ts +3 -0
  59. package/alterations-js/1.13.0-1706510290-protected-app-host-index.js +17 -0
  60. package/alterations-js/1.13.0-1706512952-restore-get-started-page.d.ts +3 -0
  61. package/alterations-js/1.13.0-1706512952-restore-get-started-page.js +13 -0
  62. package/alterations-js/1.13.0-1706528755-remove-magic-links.d.ts +3 -0
  63. package/alterations-js/1.13.0-1706528755-remove-magic-links.js +41 -0
  64. package/alterations-js/1.13.0-1706585206-protected-app-custom-domain-unique.d.ts +3 -0
  65. package/alterations-js/1.13.0-1706585206-protected-app-custom-domain-unique.js +17 -0
  66. package/alterations-js/utils/1704934999-tables.d.ts +11 -0
  67. package/alterations-js/utils/1704934999-tables.js +43 -0
  68. package/lib/consts/index.d.ts +1 -0
  69. package/lib/consts/index.js +1 -0
  70. package/lib/consts/subscriptions.d.ts +6 -0
  71. package/lib/consts/subscriptions.js +7 -0
  72. package/lib/db-entries/application-sign-in-experience.d.ts +26 -0
  73. package/lib/db-entries/application-sign-in-experience.js +42 -0
  74. package/lib/db-entries/application-user-consent-organization-scope.d.ts +24 -0
  75. package/lib/db-entries/application-user-consent-organization-scope.js +29 -0
  76. package/lib/db-entries/application-user-consent-organization.d.ts +22 -0
  77. package/lib/db-entries/application-user-consent-organization.js +33 -0
  78. package/lib/db-entries/application-user-consent-resource-scope.d.ts +24 -0
  79. package/lib/db-entries/application-user-consent-resource-scope.js +29 -0
  80. package/lib/db-entries/application-user-consent-user-scope.d.ts +24 -0
  81. package/lib/db-entries/application-user-consent-user-scope.js +29 -0
  82. package/lib/db-entries/application.d.ts +6 -2
  83. package/lib/db-entries/application.js +9 -1
  84. package/lib/db-entries/custom-types.d.ts +8 -1
  85. package/lib/db-entries/custom-types.js +8 -0
  86. package/lib/db-entries/daily-token-usage.d.ts +20 -0
  87. package/lib/db-entries/daily-token-usage.js +33 -0
  88. package/lib/db-entries/index.d.ts +8 -0
  89. package/lib/db-entries/index.js +8 -0
  90. package/lib/db-entries/organization-invitation-role-relation.d.ts +24 -0
  91. package/lib/db-entries/organization-invitation-role-relation.js +29 -0
  92. package/lib/db-entries/organization-invitation.d.ts +53 -0
  93. package/lib/db-entries/organization-invitation.js +58 -0
  94. package/lib/db-entries/sign-in-experience.d.ts +3 -1
  95. package/lib/db-entries/sign-in-experience.js +4 -0
  96. package/lib/db-entries/sso-connector.d.ts +2 -2
  97. package/lib/foundations/jsonb-types/applications.d.ts +380 -0
  98. package/lib/foundations/jsonb-types/applications.js +29 -0
  99. package/lib/foundations/jsonb-types/custom-domain.d.ts +37 -89
  100. package/lib/foundations/jsonb-types/custom-domain.js +4 -9
  101. package/lib/foundations/jsonb-types/index.d.ts +1 -0
  102. package/lib/foundations/jsonb-types/index.js +1 -0
  103. package/lib/foundations/jsonb-types/sso-connector.d.ts +3 -0
  104. package/lib/foundations/jsonb-types/sso-connector.js +1 -0
  105. package/lib/models/tenants.d.ts +1 -1
  106. package/lib/seeds/application.d.ts +1 -1
  107. package/lib/seeds/application.js +3 -1
  108. package/lib/seeds/cloud-api.d.ts +0 -2
  109. package/lib/seeds/cloud-api.js +0 -3
  110. package/lib/seeds/management-api.d.ts +77 -6
  111. package/lib/seeds/management-api.js +14 -10
  112. package/lib/types/application.d.ts +576 -1
  113. package/lib/types/application.js +42 -1
  114. package/lib/types/connector.js +1 -1
  115. package/lib/types/consent.d.ts +568 -0
  116. package/lib/types/consent.js +47 -0
  117. package/lib/types/domain.d.ts +21 -65
  118. package/lib/types/hook.d.ts +1 -0
  119. package/lib/types/index.d.ts +3 -0
  120. package/lib/types/index.js +3 -0
  121. package/lib/types/interactions.d.ts +6 -6
  122. package/lib/types/logto-config.d.ts +32 -6
  123. package/lib/types/logto-config.js +12 -2
  124. package/lib/types/mapi-proxy.d.ts +30 -0
  125. package/lib/types/mapi-proxy.js +49 -0
  126. package/lib/types/organization.d.ts +10 -1
  127. package/lib/types/organization.js +4 -1
  128. package/lib/types/sso-connector.d.ts +63 -66
  129. package/lib/types/sso-connector.js +41 -7
  130. package/lib/types/system.d.ts +28 -1
  131. package/lib/types/system.js +17 -0
  132. package/lib/types/tenant-organization.d.ts +107 -0
  133. package/lib/types/tenant-organization.js +145 -0
  134. package/lib/types/tenant.d.ts +0 -1
  135. package/lib/types/tenant.js +2 -1
  136. package/lib/types/user-assets.d.ts +5 -5
  137. package/lib/types/user-assets.js +1 -0
  138. package/lib/types/user.d.ts +17 -15
  139. package/lib/types/user.js +2 -2
  140. package/lib/utils/domain.d.ts +10 -0
  141. package/lib/utils/domain.js +28 -0
  142. package/lib/utils/domain.test.d.ts +1 -0
  143. package/lib/utils/domain.test.js +34 -0
  144. package/lib/utils/index.d.ts +1 -0
  145. package/lib/utils/index.js +1 -0
  146. package/package.json +15 -15
  147. package/tables/application_sign_in_experiences.sql +15 -0
  148. package/tables/application_user_consent_organization_scopes.sql +14 -0
  149. package/tables/application_user_consent_organizations.sql +16 -0
  150. package/tables/application_user_consent_resource_scopes.sql +14 -0
  151. package/tables/application_user_consent_user_scopes.sql +13 -0
  152. package/tables/applications.sql +16 -1
  153. package/tables/daily_token_usage.sql +11 -0
  154. package/tables/organization_invitation_role_relations.sql +14 -0
  155. package/tables/organization_invitations.sql +36 -0
  156. package/tables/organization_role_user_relations.sql +8 -6
  157. package/tables/sign_in_experiences.sql +1 -0
  158. package/tables/sso_connectors.sql +4 -2
@@ -100,13 +100,30 @@ export const demoSocialGuard = Object.freeze({
100
100
  export const hostnameProviderDataGuard = z.object({
101
101
  zoneId: z.string(),
102
102
  apiToken: z.string(), // Requires zone permission for "SSL and Certificates Edit"
103
+ blockedDomains: z.string().array().optional(), // Optional list of blocked domains
104
+ });
105
+ // Cloudflare KV for protected app config
106
+ export const protectedAppConfigProviderDataGuard = z.object({
107
+ /* Cloudflare Workers & Pages account ID */
108
+ accountIdentifier: z.string(),
109
+ /* KV namespace ID */
110
+ namespaceIdentifier: z.string(),
111
+ /* Key prefix for protected app config */
112
+ keyName: z.string(),
113
+ /* The default domain (e.g protected.app) for the protected app */
114
+ domain: z.string(),
115
+ apiToken: z.string(), // Requires account permission for "KV Storage Edit"
103
116
  });
104
117
  export var CloudflareKey;
105
118
  (function (CloudflareKey) {
106
119
  CloudflareKey["HostnameProvider"] = "cloudflareHostnameProvider";
120
+ CloudflareKey["ProtectedAppConfigProvider"] = "cloudflareProtectedAppConfigProvider";
121
+ CloudflareKey["ProtectedAppHostnameProvider"] = "cloudflareProtectedAppHostnameProvider";
107
122
  })(CloudflareKey || (CloudflareKey = {}));
108
123
  export const cloudflareGuard = Object.freeze({
109
124
  [CloudflareKey.HostnameProvider]: hostnameProviderDataGuard,
125
+ [CloudflareKey.ProtectedAppConfigProvider]: protectedAppConfigProviderDataGuard,
126
+ [CloudflareKey.ProtectedAppHostnameProvider]: hostnameProviderDataGuard,
110
127
  });
111
128
  export const systemKeys = Object.freeze([
112
129
  ...Object.values(AlterationStateKey),
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @fileoverview
3
+ * Tenant organizations are organizations in the admin tenant that represent tenants. They are
4
+ * created when a tenant is created, and are used to define the roles and scopes for the users in
5
+ * the tenant.
6
+ *
7
+ * This module provides utilities to manage tenant organizations.
8
+ */
9
+ import { type CreateOrganization, type OrganizationRole, type OrganizationScope } from '../db-entries/index.js';
10
+ /** Given a tenant ID, return the corresponding organization ID in the admin tenant. */
11
+ export declare const getTenantOrganizationId: (tenantId: string) => string;
12
+ /**
13
+ * Given a tenant ID, return the organization create data for the admin tenant. It follows a
14
+ * convention to generate the organization ID and name which can be used across the system.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const tenantId = 'test-tenant';
19
+ * const createData = getCreateData(tenantId);
20
+ *
21
+ * expect(createData).toEqual({
22
+ * tenantId: 'admin',
23
+ * id: 't-test-tenant',
24
+ * name: 'Tenant test-tenant',
25
+ * });
26
+ * ```
27
+ *
28
+ * @see {@link getId} for the convention of generating the organization ID.
29
+ */
30
+ export declare const getTenantOrganizationCreateData: (tenantId: string) => Readonly<CreateOrganization>;
31
+ /**
32
+ * Scope names in organization template for managing tenants.
33
+ *
34
+ * @remarks
35
+ * Should sync JSDoc descriptions with {@link tenantScopeDescriptions}.
36
+ */
37
+ export declare enum TenantScope {
38
+ /** Read the tenant data. */
39
+ ReadData = "read:data",
40
+ /** Write the tenant data, including creating and updating the tenant. */
41
+ WriteData = "write:data",
42
+ /** Delete data of the tenant. */
43
+ DeleteData = "delete:data",
44
+ /** Invite members to the tenant. */
45
+ InviteMember = "invite:member",
46
+ /** Remove members from the tenant. */
47
+ RemoveMember = "remove:member",
48
+ /** Update the role of a member in the tenant. */
49
+ UpdateMemberRole = "update:member:role",
50
+ /** Manage the tenant settings, including name, billing, etc. */
51
+ ManageTenant = "manage:tenant"
52
+ }
53
+ /**
54
+ * Given a tenant scope, return the corresponding organization scope data in the admin tenant.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const scope = TenantScope.ReadData; // 'read:data'
59
+ * const scopeData = getTenantScope(scope);
60
+ *
61
+ * expect(scopeData).toEqual({
62
+ * tenantId: 'admin',
63
+ * id: 'read-data',
64
+ * name: 'read:data',
65
+ * description: 'Read the tenant data.',
66
+ * });
67
+ * ```
68
+ *
69
+ * @see {@link tenantScopeDescriptions} for scope descriptions of each scope.
70
+ */
71
+ export declare const getTenantScope: (scope: TenantScope) => Readonly<OrganizationScope>;
72
+ /**
73
+ * Role names in organization template for managing tenants.
74
+ *
75
+ * @remarks
76
+ * Should sync JSDoc descriptions with {@link tenantRoleDescriptions}.
77
+ */
78
+ export declare enum TenantRole {
79
+ /** Admin of the tenant, who has all permissions. */
80
+ Admin = "admin",
81
+ /** Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings. */
82
+ Member = "member"
83
+ }
84
+ /**
85
+ * Given a tenant role, return the corresponding organization role data in the admin tenant.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const role = TenantRole.Member; // 'member'
90
+ * const roleData = getTenantRole(role);
91
+ *
92
+ * expect(roleData).toEqual({
93
+ * tenantId: 'admin',
94
+ * id: 'member',
95
+ * name: 'member',
96
+ * description: 'Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings.',
97
+ * });
98
+ * ```
99
+ *
100
+ * @see {@link tenantRoleDescriptions} for scope descriptions of each role.
101
+ */
102
+ export declare const getTenantRole: (role: TenantRole) => Readonly<OrganizationRole>;
103
+ /**
104
+ * The dictionary of tenant roles and their corresponding scopes.
105
+ * @see {TenantRole} for scope descriptions of each role.
106
+ */
107
+ export declare const tenantRoleScopes: Readonly<Record<TenantRole, Readonly<TenantScope[]>>>;
@@ -0,0 +1,145 @@
1
+ /**
2
+ * @fileoverview
3
+ * Tenant organizations are organizations in the admin tenant that represent tenants. They are
4
+ * created when a tenant is created, and are used to define the roles and scopes for the users in
5
+ * the tenant.
6
+ *
7
+ * This module provides utilities to manage tenant organizations.
8
+ */
9
+ import { adminTenantId } from '../seeds/tenant.js';
10
+ /** Given a tenant ID, return the corresponding organization ID in the admin tenant. */
11
+ export const getTenantOrganizationId = (tenantId) => `t-${tenantId}`;
12
+ /**
13
+ * Given a tenant ID, return the organization create data for the admin tenant. It follows a
14
+ * convention to generate the organization ID and name which can be used across the system.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const tenantId = 'test-tenant';
19
+ * const createData = getCreateData(tenantId);
20
+ *
21
+ * expect(createData).toEqual({
22
+ * tenantId: 'admin',
23
+ * id: 't-test-tenant',
24
+ * name: 'Tenant test-tenant',
25
+ * });
26
+ * ```
27
+ *
28
+ * @see {@link getId} for the convention of generating the organization ID.
29
+ */
30
+ export const getTenantOrganizationCreateData = (tenantId) => Object.freeze({
31
+ tenantId: adminTenantId,
32
+ id: getTenantOrganizationId(tenantId),
33
+ name: `Tenant ${tenantId}`,
34
+ });
35
+ /**
36
+ * Scope names in organization template for managing tenants.
37
+ *
38
+ * @remarks
39
+ * Should sync JSDoc descriptions with {@link tenantScopeDescriptions}.
40
+ */
41
+ export var TenantScope;
42
+ (function (TenantScope) {
43
+ /** Read the tenant data. */
44
+ TenantScope["ReadData"] = "read:data";
45
+ /** Write the tenant data, including creating and updating the tenant. */
46
+ TenantScope["WriteData"] = "write:data";
47
+ /** Delete data of the tenant. */
48
+ TenantScope["DeleteData"] = "delete:data";
49
+ /** Invite members to the tenant. */
50
+ TenantScope["InviteMember"] = "invite:member";
51
+ /** Remove members from the tenant. */
52
+ TenantScope["RemoveMember"] = "remove:member";
53
+ /** Update the role of a member in the tenant. */
54
+ TenantScope["UpdateMemberRole"] = "update:member:role";
55
+ /** Manage the tenant settings, including name, billing, etc. */
56
+ TenantScope["ManageTenant"] = "manage:tenant";
57
+ })(TenantScope || (TenantScope = {}));
58
+ const allTenantScopes = Object.freeze(Object.values(TenantScope));
59
+ /**
60
+ * Given a tenant scope, return the corresponding organization scope data in the admin tenant.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const scope = TenantScope.ReadData; // 'read:data'
65
+ * const scopeData = getTenantScope(scope);
66
+ *
67
+ * expect(scopeData).toEqual({
68
+ * tenantId: 'admin',
69
+ * id: 'read-data',
70
+ * name: 'read:data',
71
+ * description: 'Read the tenant data.',
72
+ * });
73
+ * ```
74
+ *
75
+ * @see {@link tenantScopeDescriptions} for scope descriptions of each scope.
76
+ */
77
+ export const getTenantScope = (scope) => Object.freeze({
78
+ tenantId: adminTenantId,
79
+ id: scope.replaceAll(':', '-'),
80
+ name: scope,
81
+ description: tenantScopeDescriptions[scope],
82
+ });
83
+ const tenantScopeDescriptions = Object.freeze({
84
+ [TenantScope.ReadData]: 'Read the tenant data.',
85
+ [TenantScope.WriteData]: 'Write the tenant data, including creating and updating the tenant.',
86
+ [TenantScope.DeleteData]: 'Delete data of the tenant.',
87
+ [TenantScope.InviteMember]: 'Invite members to the tenant.',
88
+ [TenantScope.RemoveMember]: 'Remove members from the tenant.',
89
+ [TenantScope.UpdateMemberRole]: 'Update the role of a member in the tenant.',
90
+ [TenantScope.ManageTenant]: 'Manage the tenant settings, including name, billing, etc.',
91
+ });
92
+ /**
93
+ * Role names in organization template for managing tenants.
94
+ *
95
+ * @remarks
96
+ * Should sync JSDoc descriptions with {@link tenantRoleDescriptions}.
97
+ */
98
+ export var TenantRole;
99
+ (function (TenantRole) {
100
+ /** Admin of the tenant, who has all permissions. */
101
+ TenantRole["Admin"] = "admin";
102
+ /** Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings. */
103
+ TenantRole["Member"] = "member";
104
+ })(TenantRole || (TenantRole = {}));
105
+ const tenantRoleDescriptions = Object.freeze({
106
+ [TenantRole.Admin]: 'Admin of the tenant, who has all permissions.',
107
+ [TenantRole.Member]: 'Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings.',
108
+ });
109
+ /**
110
+ * Given a tenant role, return the corresponding organization role data in the admin tenant.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * const role = TenantRole.Member; // 'member'
115
+ * const roleData = getTenantRole(role);
116
+ *
117
+ * expect(roleData).toEqual({
118
+ * tenantId: 'admin',
119
+ * id: 'member',
120
+ * name: 'member',
121
+ * description: 'Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings.',
122
+ * });
123
+ * ```
124
+ *
125
+ * @see {@link tenantRoleDescriptions} for scope descriptions of each role.
126
+ */
127
+ export const getTenantRole = (role) => Object.freeze({
128
+ tenantId: adminTenantId,
129
+ id: role,
130
+ name: role,
131
+ description: tenantRoleDescriptions[role],
132
+ });
133
+ /**
134
+ * The dictionary of tenant roles and their corresponding scopes.
135
+ * @see {TenantRole} for scope descriptions of each role.
136
+ */
137
+ export const tenantRoleScopes = Object.freeze({
138
+ [TenantRole.Admin]: allTenantScopes,
139
+ [TenantRole.Member]: [
140
+ TenantScope.ReadData,
141
+ TenantScope.WriteData,
142
+ TenantScope.DeleteData,
143
+ TenantScope.InviteMember,
144
+ ],
145
+ });
@@ -1,5 +1,4 @@
1
1
  export declare enum TenantTag {
2
2
  Development = "development",
3
- Staging = "staging",
4
3
  Production = "production"
5
4
  }
@@ -1,6 +1,7 @@
1
1
  export var TenantTag;
2
2
  (function (TenantTag) {
3
+ /* Development tenants are free to use but are not meant to be used as production environment. */
3
4
  TenantTag["Development"] = "development";
4
- TenantTag["Staging"] = "staging";
5
+ /* A production tenant must have an associated subscription plan, even if it's a free plan. */
5
6
  TenantTag["Production"] = "production";
6
7
  })(TenantTag || (TenantTag = {}));
@@ -1,19 +1,19 @@
1
1
  import { z } from 'zod';
2
2
  export declare const maxUploadFileSize: number;
3
- export declare const allowUploadMimeTypes: readonly ["image/jpeg", "image/png", "image/gif", "image/vnd.microsoft.icon", "image/svg+xml", "image/tiff", "image/webp", "image/bmp"];
4
- declare const allowUploadMimeTypeGuard: z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/vnd.microsoft.icon", "image/svg+xml", "image/tiff", "image/webp", "image/bmp"]>;
3
+ export declare const allowUploadMimeTypes: readonly ["image/jpeg", "image/png", "image/gif", "image/vnd.microsoft.icon", "image/x-icon", "image/svg+xml", "image/tiff", "image/webp", "image/bmp"];
4
+ declare const allowUploadMimeTypeGuard: z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/vnd.microsoft.icon", "image/x-icon", "image/svg+xml", "image/tiff", "image/webp", "image/bmp"]>;
5
5
  export type AllowedUploadMimeType = z.infer<typeof allowUploadMimeTypeGuard>;
6
6
  export declare const userAssetsServiceStatusGuard: z.ZodObject<{
7
7
  status: z.ZodUnion<[z.ZodLiteral<"ready">, z.ZodLiteral<"not_configured">]>;
8
- allowUploadMimeTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/vnd.microsoft.icon", "image/svg+xml", "image/tiff", "image/webp", "image/bmp"]>, "many">>;
8
+ allowUploadMimeTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<["image/jpeg", "image/png", "image/gif", "image/vnd.microsoft.icon", "image/x-icon", "image/svg+xml", "image/tiff", "image/webp", "image/bmp"]>, "many">>;
9
9
  maxUploadFileSize: z.ZodOptional<z.ZodNumber>;
10
10
  }, "strip", z.ZodTypeAny, {
11
11
  status: "ready" | "not_configured";
12
- allowUploadMimeTypes?: ("image/jpeg" | "image/png" | "image/gif" | "image/vnd.microsoft.icon" | "image/svg+xml" | "image/tiff" | "image/webp" | "image/bmp")[] | undefined;
12
+ allowUploadMimeTypes?: ("image/jpeg" | "image/png" | "image/gif" | "image/vnd.microsoft.icon" | "image/x-icon" | "image/svg+xml" | "image/tiff" | "image/webp" | "image/bmp")[] | undefined;
13
13
  maxUploadFileSize?: number | undefined;
14
14
  }, {
15
15
  status: "ready" | "not_configured";
16
- allowUploadMimeTypes?: ("image/jpeg" | "image/png" | "image/gif" | "image/vnd.microsoft.icon" | "image/svg+xml" | "image/tiff" | "image/webp" | "image/bmp")[] | undefined;
16
+ allowUploadMimeTypes?: ("image/jpeg" | "image/png" | "image/gif" | "image/vnd.microsoft.icon" | "image/x-icon" | "image/svg+xml" | "image/tiff" | "image/webp" | "image/bmp")[] | undefined;
17
17
  maxUploadFileSize?: number | undefined;
18
18
  }>;
19
19
  export type UserAssetsServiceStatus = z.infer<typeof userAssetsServiceStatusGuard>;
@@ -6,6 +6,7 @@ export const allowUploadMimeTypes = [
6
6
  'image/png',
7
7
  'image/gif',
8
8
  'image/vnd.microsoft.icon',
9
+ 'image/x-icon',
9
10
  'image/svg+xml',
10
11
  'image/tiff',
11
12
  'image/webp',
@@ -20,8 +20,8 @@ export declare const userInfoGuard: z.ZodObject<Pick<{
20
20
  userId: string;
21
21
  details?: Record<string, unknown> | undefined;
22
22
  }>>;
23
- customData: z.ZodType<import("../foundations/index.js").JsonObject, z.ZodTypeDef, import("../foundations/index.js").JsonObject>;
24
- logtoConfig: z.ZodType<import("../foundations/index.js").JsonObject, z.ZodTypeDef, import("../foundations/index.js").JsonObject>;
23
+ customData: z.ZodType<import("@withtyped/server/lib/types.js").JsonObject, z.ZodTypeDef, import("@withtyped/server/lib/types.js").JsonObject>;
24
+ logtoConfig: z.ZodType<import("@withtyped/server/lib/types.js").JsonObject, z.ZodTypeDef, import("@withtyped/server/lib/types.js").JsonObject>;
25
25
  mfaVerifications: z.ZodType<({
26
26
  type: MfaFactor.TOTP;
27
27
  id: string;
@@ -92,8 +92,8 @@ export declare const userInfoGuard: z.ZodObject<Pick<{
92
92
  userId: string;
93
93
  details?: Record<string, unknown> | undefined;
94
94
  }>;
95
- customData: import("../foundations/index.js").JsonObject;
96
- logtoConfig: import("../foundations/index.js").JsonObject;
95
+ customData: import("@withtyped/server/lib/types.js").JsonObject;
96
+ logtoConfig: import("@withtyped/server/lib/types.js").JsonObject;
97
97
  mfaVerifications: ({
98
98
  type: MfaFactor.TOTP;
99
99
  id: string;
@@ -138,8 +138,8 @@ export declare const userInfoGuard: z.ZodObject<Pick<{
138
138
  userId: string;
139
139
  details?: Record<string, unknown> | undefined;
140
140
  }>;
141
- customData: import("../foundations/index.js").JsonObject;
142
- logtoConfig: import("../foundations/index.js").JsonObject;
141
+ customData: import("@withtyped/server/lib/types.js").JsonObject;
142
+ logtoConfig: import("@withtyped/server/lib/types.js").JsonObject;
143
143
  mfaVerifications: ({
144
144
  type: MfaFactor.TOTP;
145
145
  id: string;
@@ -189,8 +189,8 @@ export declare const userProfileResponseGuard: z.ZodObject<{
189
189
  userId: string;
190
190
  details?: Record<string, unknown> | undefined;
191
191
  }>>;
192
- customData: z.ZodType<import("../foundations/index.js").JsonObject, z.ZodTypeDef, import("../foundations/index.js").JsonObject>;
193
- logtoConfig: z.ZodType<import("../foundations/index.js").JsonObject, z.ZodTypeDef, import("../foundations/index.js").JsonObject>;
192
+ customData: z.ZodType<import("@withtyped/server/lib/types.js").JsonObject, z.ZodTypeDef, import("@withtyped/server/lib/types.js").JsonObject>;
193
+ logtoConfig: z.ZodType<import("@withtyped/server/lib/types.js").JsonObject, z.ZodTypeDef, import("@withtyped/server/lib/types.js").JsonObject>;
194
194
  mfaVerifications: z.ZodType<({
195
195
  type: MfaFactor.TOTP;
196
196
  id: string;
@@ -245,6 +245,7 @@ export declare const userProfileResponseGuard: z.ZodObject<{
245
245
  isSuspended: z.ZodType<boolean, z.ZodTypeDef, boolean>;
246
246
  lastSignInAt: z.ZodType<number | null, z.ZodTypeDef, number | null>;
247
247
  hasPassword: z.ZodOptional<z.ZodBoolean>;
248
+ ssoIdentities: z.ZodOptional<z.ZodArray<import("../foundations/schemas.js").Guard<import("../db-entries/user-sso-identity.js").UserSsoIdentity>, "many">>;
248
249
  }, "strip", z.ZodTypeAny, {
249
250
  name: string | null;
250
251
  id: string;
@@ -261,8 +262,8 @@ export declare const userProfileResponseGuard: z.ZodObject<{
261
262
  userId: string;
262
263
  details?: Record<string, unknown> | undefined;
263
264
  }>;
264
- customData: import("../foundations/index.js").JsonObject;
265
- logtoConfig: import("../foundations/index.js").JsonObject;
265
+ customData: import("@withtyped/server/lib/types.js").JsonObject;
266
+ logtoConfig: import("@withtyped/server/lib/types.js").JsonObject;
266
267
  mfaVerifications: ({
267
268
  type: MfaFactor.TOTP;
268
269
  id: string;
@@ -292,6 +293,7 @@ export declare const userProfileResponseGuard: z.ZodObject<{
292
293
  isSuspended: boolean;
293
294
  lastSignInAt: number | null;
294
295
  hasPassword?: boolean | undefined;
296
+ ssoIdentities?: import("../db-entries/user-sso-identity.js").UserSsoIdentity[] | undefined;
295
297
  }, {
296
298
  name: string | null;
297
299
  id: string;
@@ -308,8 +310,8 @@ export declare const userProfileResponseGuard: z.ZodObject<{
308
310
  userId: string;
309
311
  details?: Record<string, unknown> | undefined;
310
312
  }>;
311
- customData: import("../foundations/index.js").JsonObject;
312
- logtoConfig: import("../foundations/index.js").JsonObject;
313
+ customData: import("@withtyped/server/lib/types.js").JsonObject;
314
+ logtoConfig: import("@withtyped/server/lib/types.js").JsonObject;
313
315
  mfaVerifications: ({
314
316
  type: MfaFactor.TOTP;
315
317
  id: string;
@@ -339,6 +341,7 @@ export declare const userProfileResponseGuard: z.ZodObject<{
339
341
  isSuspended: boolean;
340
342
  lastSignInAt: number | null;
341
343
  hasPassword?: boolean | undefined;
344
+ ssoIdentities?: import("../db-entries/user-sso-identity.js").UserSsoIdentity[] | undefined;
342
345
  }>;
343
346
  export type UserProfileResponse = z.infer<typeof userProfileResponseGuard>;
344
347
  export declare const userMfaVerificationResponseGuard: z.ZodArray<z.ZodObject<{
@@ -371,7 +374,6 @@ export declare enum InternalRole {
371
374
  Admin = "#internal:admin"
372
375
  }
373
376
  export declare enum AdminTenantRole {
374
- Admin = "admin",
375
377
  /** Common user role in admin tenant. */
376
378
  User = "user",
377
379
  /** The role for machine to machine applications that represent a user tenant and send requests to Logto Cloud. */
@@ -404,8 +406,8 @@ export declare const featuredUserGuard: z.ZodObject<Pick<{
404
406
  userId: string;
405
407
  details?: Record<string, unknown> | undefined;
406
408
  }>>;
407
- customData: z.ZodType<import("../foundations/index.js").JsonObject, z.ZodTypeDef, import("../foundations/index.js").JsonObject>;
408
- logtoConfig: z.ZodType<import("../foundations/index.js").JsonObject, z.ZodTypeDef, import("../foundations/index.js").JsonObject>;
409
+ customData: z.ZodType<import("@withtyped/server/lib/types.js").JsonObject, z.ZodTypeDef, import("@withtyped/server/lib/types.js").JsonObject>;
410
+ logtoConfig: z.ZodType<import("@withtyped/server/lib/types.js").JsonObject, z.ZodTypeDef, import("@withtyped/server/lib/types.js").JsonObject>;
409
411
  mfaVerifications: z.ZodType<({
410
412
  type: MfaFactor.TOTP;
411
413
  id: string;
package/lib/types/user.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { Users } from '../db-entries/index.js';
2
+ import { Users, UserSsoIdentities } from '../db-entries/index.js';
3
3
  import { MfaFactor } from '../foundations/index.js';
4
4
  export const userInfoSelectFields = Object.freeze([
5
5
  'id',
@@ -18,6 +18,7 @@ export const userInfoSelectFields = Object.freeze([
18
18
  export const userInfoGuard = Users.guard.pick(Object.fromEntries(userInfoSelectFields.map((key) => [key, true])));
19
19
  export const userProfileResponseGuard = userInfoGuard.extend({
20
20
  hasPassword: z.boolean().optional(),
21
+ ssoIdentities: z.array(UserSsoIdentities.guard).optional(),
21
22
  });
22
23
  export const userMfaVerificationResponseGuard = z
23
24
  .object({
@@ -40,7 +41,6 @@ export var InternalRole;
40
41
  })(InternalRole || (InternalRole = {}));
41
42
  export var AdminTenantRole;
42
43
  (function (AdminTenantRole) {
43
- AdminTenantRole["Admin"] = "admin";
44
44
  /** Common user role in admin tenant. */
45
45
  AdminTenantRole["User"] = "user";
46
46
  /** The role for machine to machine applications that represent a user tenant and send requests to Logto Cloud. */
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Find duplicated domains and blocked domains using the domain blacklist.
3
+ *
4
+ * @param domains Array of email domains.
5
+ * @returns
6
+ */
7
+ export declare const findDuplicatedOrBlockedEmailDomains: (domains?: string[]) => {
8
+ duplicatedDomains: Set<string>;
9
+ forbiddenDomains: Set<string>;
10
+ };
@@ -0,0 +1,28 @@
1
+ import { singleSignOnDomainBlackList } from '../types/sso-connector.js';
2
+ /**
3
+ * Find duplicated domains and blocked domains using the domain blacklist.
4
+ *
5
+ * @param domains Array of email domains.
6
+ * @returns
7
+ */
8
+ export const findDuplicatedOrBlockedEmailDomains = (domains) => {
9
+ const blackListSet = new Set(singleSignOnDomainBlackList);
10
+ const validDomainSet = new Set();
11
+ const duplicatedDomains = new Set();
12
+ const forbiddenDomains = new Set();
13
+ for (const domain of domains ?? []) {
14
+ if (blackListSet.has(domain)) {
15
+ forbiddenDomains.add(domain);
16
+ }
17
+ if (validDomainSet.has(domain)) {
18
+ duplicatedDomains.add(domain);
19
+ }
20
+ else {
21
+ validDomainSet.add(domain);
22
+ }
23
+ }
24
+ return {
25
+ duplicatedDomains,
26
+ forbiddenDomains,
27
+ };
28
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import { findDuplicatedOrBlockedEmailDomains } from './domain.js';
2
+ describe('findDuplicatedOrBlockedEmailDomains', () => {
3
+ it('should return blocked domains and duplicated domains correctly', () => {
4
+ const { duplicatedDomains, forbiddenDomains } = findDuplicatedOrBlockedEmailDomains([
5
+ 'gmail.com',
6
+ 'silverhand.io',
7
+ 'logto.io',
8
+ 'yahoo.com',
9
+ 'outlook.com',
10
+ 'logto.io',
11
+ ]);
12
+ expect(duplicatedDomains).toEqual(new Set(['logto.io']));
13
+ expect(forbiddenDomains).toEqual(new Set(['gmail.com', 'yahoo.com', 'outlook.com']));
14
+ });
15
+ it('should return empty `duplicatedDomains` and `forbiddenDomains` sets if all domains are valid', () => {
16
+ const { duplicatedDomains, forbiddenDomains } = findDuplicatedOrBlockedEmailDomains([
17
+ 'silverhand.io',
18
+ 'logto.io',
19
+ 'metalhand.io',
20
+ ]);
21
+ expect(duplicatedDomains).toEqual(new Set());
22
+ expect(forbiddenDomains).toEqual(new Set());
23
+ });
24
+ it('should return empty `duplicatedDomains` and `forbiddenDomains` sets if input is undefined', () => {
25
+ const { duplicatedDomains, forbiddenDomains } = findDuplicatedOrBlockedEmailDomains();
26
+ expect(duplicatedDomains).toEqual(new Set());
27
+ expect(forbiddenDomains).toEqual(new Set());
28
+ });
29
+ it('should return empty `duplicatedDomains` and `forbiddenDomains` sets if input is empty array', () => {
30
+ const { duplicatedDomains, forbiddenDomains } = findDuplicatedOrBlockedEmailDomains([]);
31
+ expect(duplicatedDomains).toEqual(new Set());
32
+ expect(forbiddenDomains).toEqual(new Set());
33
+ });
34
+ });
@@ -1,2 +1,3 @@
1
1
  export * from './role.js';
2
2
  export * from './management-api.js';
3
+ export * from './domain.js';
@@ -1,2 +1,3 @@
1
1
  export * from './role.js';
2
2
  export * from './management-api.js';
3
+ export * from './domain.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logto/schemas",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "author": "Silverhand Inc. <contact@silverhand.io>",
5
5
  "license": "MPL-2.0",
6
6
  "type": "module",
@@ -21,27 +21,27 @@
21
21
  "access": "public"
22
22
  },
23
23
  "engines": {
24
- "node": "^18.12.0"
24
+ "node": "^20.9.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@silverhand/eslint-config": "4.0.1",
28
- "@silverhand/essentials": "^2.8.4",
29
- "@silverhand/ts-config": "4.0.0",
27
+ "@silverhand/eslint-config": "5.0.0",
28
+ "@silverhand/essentials": "^2.9.0",
29
+ "@silverhand/ts-config": "5.0.0",
30
30
  "@types/inquirer": "^9.0.0",
31
31
  "@types/jest": "^29.4.0",
32
- "@types/node": "^18.11.18",
33
- "@types/pluralize": "^0.0.32",
32
+ "@types/node": "^20.9.5",
33
+ "@types/pluralize": "^0.0.33",
34
34
  "camelcase": "^8.0.0",
35
35
  "chalk": "^5.0.0",
36
36
  "eslint": "^8.44.0",
37
- "jest": "^29.5.0",
37
+ "jest": "^29.7.0",
38
38
  "lint-staged": "^15.0.0",
39
39
  "pluralize": "^8.0.0",
40
40
  "prettier": "^3.0.0",
41
41
  "roarr": "^7.11.0",
42
42
  "slonik": "^30.0.0",
43
43
  "slonik-sql-tag-raw": "^1.1.4",
44
- "typescript": "^5.0.0"
44
+ "typescript": "^5.3.3"
45
45
  },
46
46
  "eslintConfig": {
47
47
  "extends": "@silverhand",
@@ -64,12 +64,12 @@
64
64
  },
65
65
  "prettier": "@silverhand/eslint-config/.prettierrc",
66
66
  "dependencies": {
67
- "@logto/connector-kit": "^2.0.0",
68
- "@logto/core-kit": "^2.2.0",
69
- "@logto/language-kit": "^1.0.0",
70
- "@logto/phrases": "^1.7.0",
71
- "@logto/phrases-experience": "^1.4.0",
72
- "@logto/shared": "^3.0.0",
67
+ "@logto/connector-kit": "^2.1.0",
68
+ "@logto/core-kit": "^2.3.0",
69
+ "@logto/language-kit": "^1.1.0",
70
+ "@logto/phrases": "^1.9.0",
71
+ "@logto/phrases-experience": "^1.6.0",
72
+ "@logto/shared": "^3.1.0",
73
73
  "@withtyped/server": "^0.12.9"
74
74
  },
75
75
  "peerDependencies": {
@@ -0,0 +1,15 @@
1
+ /* init_order = 2 */
2
+
3
+ /** Application level sign-in experience configuration. */
4
+ create table application_sign_in_experiences (
5
+ tenant_id varchar(21) not null
6
+ references tenants (id) on update cascade on delete cascade,
7
+ application_id varchar(21) not null
8
+ references applications (id) on update cascade on delete cascade,
9
+ branding jsonb /* @use Branding */ not null default '{}'::jsonb,
10
+ terms_of_use_url varchar(2048),
11
+ privacy_policy_url varchar(2048),
12
+ display_name varchar(256),
13
+
14
+ primary key (tenant_id, application_id)
15
+ );
@@ -0,0 +1,14 @@
1
+ /* init_order = 2 */
2
+
3
+ /** The organization scopes (permissions) assigned to an application. */
4
+ create table application_user_consent_organization_scopes (
5
+ tenant_id varchar(21) not null
6
+ references tenants (id) on update cascade on delete cascade,
7
+ /** The globally unique identifier of the application. */
8
+ application_id varchar(21) not null
9
+ references applications (id) on update cascade on delete cascade,
10
+ /** The globally unique identifier of the organization scope. */
11
+ organization_scope_id varchar(21) not null
12
+ references organization_scopes (id) on update cascade on delete cascade,
13
+ primary key (application_id, organization_scope_id)
14
+ );