@contember/engine-tenant-api 2.2.0-alpha.5 → 2.2.0-alpha.6

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 (232) hide show
  1. package/CLAUDE.md +1 -0
  2. package/dist/development/index.cjs +2 -0
  3. package/dist/development/index.cjs.map +1 -1
  4. package/dist/development/index.js +2 -0
  5. package/dist/development/index.js.map +1 -1
  6. package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs +18 -0
  7. package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs.map +1 -0
  8. package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js +19 -0
  9. package/dist/development/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js.map +1 -0
  10. package/dist/development/src/migrations/runner.cjs +3 -1
  11. package/dist/development/src/migrations/runner.cjs.map +1 -1
  12. package/dist/development/src/migrations/runner.js +3 -1
  13. package/dist/development/src/migrations/runner.js.map +1 -1
  14. package/dist/development/src/migrations/snapshot.cjs +2 -1
  15. package/dist/development/src/migrations/snapshot.cjs.map +1 -1
  16. package/dist/development/src/migrations/snapshot.js +2 -1
  17. package/dist/development/src/migrations/snapshot.js.map +1 -1
  18. package/dist/development/src/model/commands/idp/CreateIdpCommand.cjs +8 -2
  19. package/dist/development/src/model/commands/idp/CreateIdpCommand.cjs.map +1 -1
  20. package/dist/development/src/model/commands/idp/CreateIdpCommand.js +8 -2
  21. package/dist/development/src/model/commands/idp/CreateIdpCommand.js.map +1 -1
  22. package/dist/development/src/model/commands/idp/UpdateIdpCommand.cjs +6 -2
  23. package/dist/development/src/model/commands/idp/UpdateIdpCommand.cjs.map +1 -1
  24. package/dist/development/src/model/commands/idp/UpdateIdpCommand.js +6 -2
  25. package/dist/development/src/model/commands/idp/UpdateIdpCommand.js.map +1 -1
  26. package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs +21 -0
  27. package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs.map +1 -0
  28. package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js +21 -0
  29. package/dist/development/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js.map +1 -0
  30. package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.cjs +1 -1
  31. package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.cjs.map +1 -1
  32. package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.js +1 -1
  33. package/dist/development/src/model/queries/idp/PersonIdentityProvidersQuery.js.map +1 -1
  34. package/dist/development/src/model/queries/idp/helpers.cjs +3 -3
  35. package/dist/development/src/model/queries/idp/helpers.cjs.map +1 -1
  36. package/dist/development/src/model/queries/idp/helpers.js +3 -3
  37. package/dist/development/src/model/queries/idp/helpers.js.map +1 -1
  38. package/dist/development/src/model/service/PasswordResetManager.cjs +5 -0
  39. package/dist/development/src/model/service/PasswordResetManager.cjs.map +1 -1
  40. package/dist/development/src/model/service/PasswordResetManager.js +5 -0
  41. package/dist/development/src/model/service/PasswordResetManager.js.map +1 -1
  42. package/dist/development/src/model/service/PasswordlessSignInManager.cjs +19 -0
  43. package/dist/development/src/model/service/PasswordlessSignInManager.cjs.map +1 -1
  44. package/dist/development/src/model/service/PasswordlessSignInManager.js +19 -0
  45. package/dist/development/src/model/service/PasswordlessSignInManager.js.map +1 -1
  46. package/dist/development/src/model/service/SignInManager.cjs +5 -0
  47. package/dist/development/src/model/service/SignInManager.cjs.map +1 -1
  48. package/dist/development/src/model/service/SignInManager.js +5 -0
  49. package/dist/development/src/model/service/SignInManager.js.map +1 -1
  50. package/dist/development/src/model/service/idp/PersonIdentityProviderManager.cjs +6 -0
  51. package/dist/development/src/model/service/idp/PersonIdentityProviderManager.cjs.map +1 -1
  52. package/dist/development/src/model/service/idp/PersonIdentityProviderManager.js +6 -0
  53. package/dist/development/src/model/service/idp/PersonIdentityProviderManager.js.map +1 -1
  54. package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs +2 -1
  55. package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs.map +1 -1
  56. package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.js +2 -1
  57. package/dist/development/src/resolvers/mutation/idp/AddIDPMutationResolver.js.map +1 -1
  58. package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs +2 -1
  59. package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs.map +1 -1
  60. package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js +2 -1
  61. package/dist/development/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js.map +1 -1
  62. package/dist/development/src/resolvers/mutation/idp/audit.cjs +1 -0
  63. package/dist/development/src/resolvers/mutation/idp/audit.cjs.map +1 -1
  64. package/dist/development/src/resolvers/mutation/idp/audit.js +1 -0
  65. package/dist/development/src/resolvers/mutation/idp/audit.js.map +1 -1
  66. package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs +4 -0
  67. package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs.map +1 -1
  68. package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.js +4 -0
  69. package/dist/development/src/resolvers/mutation/person/PasswordlessMutationResolver.js.map +1 -1
  70. package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.cjs +2 -2
  71. package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.cjs.map +1 -1
  72. package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.js +2 -2
  73. package/dist/development/src/resolvers/mutation/person/SignInMutationResolver.js.map +1 -1
  74. package/dist/development/src/schema/tenant.graphql.cjs +28 -0
  75. package/dist/development/src/schema/tenant.graphql.cjs.map +1 -1
  76. package/dist/development/src/schema/tenant.graphql.js +28 -0
  77. package/dist/development/src/schema/tenant.graphql.js.map +1 -1
  78. package/dist/production/index.cjs +2 -0
  79. package/dist/production/index.cjs.map +1 -1
  80. package/dist/production/index.js +2 -0
  81. package/dist/production/index.js.map +1 -1
  82. package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs +18 -0
  83. package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.cjs.map +1 -0
  84. package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js +19 -0
  85. package/dist/production/src/migrations/2026-09-04-120000-idp-disable-local-authentication.js.map +1 -0
  86. package/dist/production/src/migrations/runner.cjs +3 -1
  87. package/dist/production/src/migrations/runner.cjs.map +1 -1
  88. package/dist/production/src/migrations/runner.js +3 -1
  89. package/dist/production/src/migrations/runner.js.map +1 -1
  90. package/dist/production/src/migrations/snapshot.cjs +2 -1
  91. package/dist/production/src/migrations/snapshot.cjs.map +1 -1
  92. package/dist/production/src/migrations/snapshot.js +2 -1
  93. package/dist/production/src/migrations/snapshot.js.map +1 -1
  94. package/dist/production/src/model/commands/idp/CreateIdpCommand.cjs +8 -2
  95. package/dist/production/src/model/commands/idp/CreateIdpCommand.cjs.map +1 -1
  96. package/dist/production/src/model/commands/idp/CreateIdpCommand.js +8 -2
  97. package/dist/production/src/model/commands/idp/CreateIdpCommand.js.map +1 -1
  98. package/dist/production/src/model/commands/idp/UpdateIdpCommand.cjs +6 -2
  99. package/dist/production/src/model/commands/idp/UpdateIdpCommand.cjs.map +1 -1
  100. package/dist/production/src/model/commands/idp/UpdateIdpCommand.js +6 -2
  101. package/dist/production/src/model/commands/idp/UpdateIdpCommand.js.map +1 -1
  102. package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs +21 -0
  103. package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.cjs.map +1 -0
  104. package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js +21 -0
  105. package/dist/production/src/model/queries/idp/LocalAuthDisablingIdpsQuery.js.map +1 -0
  106. package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.cjs +1 -1
  107. package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.cjs.map +1 -1
  108. package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.js +1 -1
  109. package/dist/production/src/model/queries/idp/PersonIdentityProvidersQuery.js.map +1 -1
  110. package/dist/production/src/model/queries/idp/helpers.cjs +3 -3
  111. package/dist/production/src/model/queries/idp/helpers.cjs.map +1 -1
  112. package/dist/production/src/model/queries/idp/helpers.js +3 -3
  113. package/dist/production/src/model/queries/idp/helpers.js.map +1 -1
  114. package/dist/production/src/model/service/PasswordResetManager.cjs +5 -0
  115. package/dist/production/src/model/service/PasswordResetManager.cjs.map +1 -1
  116. package/dist/production/src/model/service/PasswordResetManager.js +5 -0
  117. package/dist/production/src/model/service/PasswordResetManager.js.map +1 -1
  118. package/dist/production/src/model/service/PasswordlessSignInManager.cjs +19 -0
  119. package/dist/production/src/model/service/PasswordlessSignInManager.cjs.map +1 -1
  120. package/dist/production/src/model/service/PasswordlessSignInManager.js +19 -0
  121. package/dist/production/src/model/service/PasswordlessSignInManager.js.map +1 -1
  122. package/dist/production/src/model/service/SignInManager.cjs +5 -0
  123. package/dist/production/src/model/service/SignInManager.cjs.map +1 -1
  124. package/dist/production/src/model/service/SignInManager.js +5 -0
  125. package/dist/production/src/model/service/SignInManager.js.map +1 -1
  126. package/dist/production/src/model/service/idp/PersonIdentityProviderManager.cjs +6 -0
  127. package/dist/production/src/model/service/idp/PersonIdentityProviderManager.cjs.map +1 -1
  128. package/dist/production/src/model/service/idp/PersonIdentityProviderManager.js +6 -0
  129. package/dist/production/src/model/service/idp/PersonIdentityProviderManager.js.map +1 -1
  130. package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs +2 -1
  131. package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.cjs.map +1 -1
  132. package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.js +2 -1
  133. package/dist/production/src/resolvers/mutation/idp/AddIDPMutationResolver.js.map +1 -1
  134. package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs +2 -1
  135. package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.cjs.map +1 -1
  136. package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js +2 -1
  137. package/dist/production/src/resolvers/mutation/idp/UpdateIDPMutationResolver.js.map +1 -1
  138. package/dist/production/src/resolvers/mutation/idp/audit.cjs +1 -0
  139. package/dist/production/src/resolvers/mutation/idp/audit.cjs.map +1 -1
  140. package/dist/production/src/resolvers/mutation/idp/audit.js +1 -0
  141. package/dist/production/src/resolvers/mutation/idp/audit.js.map +1 -1
  142. package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs +4 -0
  143. package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.cjs.map +1 -1
  144. package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.js +4 -0
  145. package/dist/production/src/resolvers/mutation/person/PasswordlessMutationResolver.js.map +1 -1
  146. package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.cjs +2 -2
  147. package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.cjs.map +1 -1
  148. package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.js +2 -2
  149. package/dist/production/src/resolvers/mutation/person/SignInMutationResolver.js.map +1 -1
  150. package/dist/production/src/schema/tenant.graphql.cjs +28 -0
  151. package/dist/production/src/schema/tenant.graphql.cjs.map +1 -1
  152. package/dist/production/src/schema/tenant.graphql.js +28 -0
  153. package/dist/production/src/schema/tenant.graphql.js.map +1 -1
  154. package/dist/tests/cases/integration/mocked/gql/passwordless.d.ts +3 -0
  155. package/dist/tests/cases/integration/mocked/gql/passwordless.d.ts.map +1 -1
  156. package/dist/tests/cases/integration/mocked/localAuthenticationDisabled.test.d.ts +2 -0
  157. package/dist/tests/cases/integration/mocked/localAuthenticationDisabled.test.d.ts.map +1 -0
  158. package/dist/tests/cases/integration/mocked/sql/localAuthDisablingIdpsSql.d.ts +10 -0
  159. package/dist/tests/cases/integration/mocked/sql/localAuthDisablingIdpsSql.d.ts.map +1 -0
  160. package/dist/tests/cases/integration/mocked/sql/personIdentityProvidersSql.d.ts +1 -0
  161. package/dist/tests/cases/integration/mocked/sql/personIdentityProvidersSql.d.ts.map +1 -1
  162. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  163. package/dist/types/migrations/2026-09-04-120000-idp-disable-local-authentication.d.ts +3 -0
  164. package/dist/types/migrations/2026-09-04-120000-idp-disable-local-authentication.d.ts.map +1 -0
  165. package/dist/types/migrations/runner.d.ts.map +1 -1
  166. package/dist/types/migrations/snapshot.d.ts.map +1 -1
  167. package/dist/types/model/commands/idp/CreateIdpCommand.d.ts.map +1 -1
  168. package/dist/types/model/commands/idp/UpdateIdpCommand.d.ts.map +1 -1
  169. package/dist/types/model/queries/idp/LocalAuthDisablingIdpsQuery.d.ts +18 -0
  170. package/dist/types/model/queries/idp/LocalAuthDisablingIdpsQuery.d.ts.map +1 -0
  171. package/dist/types/model/queries/idp/PersonIdentityProvidersQuery.d.ts +1 -0
  172. package/dist/types/model/queries/idp/PersonIdentityProvidersQuery.d.ts.map +1 -1
  173. package/dist/types/model/queries/idp/helpers.d.ts +1 -1
  174. package/dist/types/model/queries/idp/helpers.d.ts.map +1 -1
  175. package/dist/types/model/queries/idp/index.d.ts +1 -0
  176. package/dist/types/model/queries/idp/index.d.ts.map +1 -1
  177. package/dist/types/model/queries/idp/types.d.ts +1 -0
  178. package/dist/types/model/queries/idp/types.d.ts.map +1 -1
  179. package/dist/types/model/service/PasswordResetManager.d.ts.map +1 -1
  180. package/dist/types/model/service/PasswordlessSignInManager.d.ts.map +1 -1
  181. package/dist/types/model/service/SignInManager.d.ts.map +1 -1
  182. package/dist/types/model/service/idp/PersonIdentityProviderManager.d.ts.map +1 -1
  183. package/dist/types/model/type/IdentityProvider.d.ts +2 -0
  184. package/dist/types/model/type/IdentityProvider.d.ts.map +1 -1
  185. package/dist/types/resolvers/mutation/idp/AddIDPMutationResolver.d.ts.map +1 -1
  186. package/dist/types/resolvers/mutation/idp/UpdateIDPMutationResolver.d.ts.map +1 -1
  187. package/dist/types/resolvers/mutation/idp/audit.d.ts.map +1 -1
  188. package/dist/types/resolvers/mutation/person/PasswordlessMutationResolver.d.ts.map +1 -1
  189. package/dist/types/schema/index.d.ts +33 -4
  190. package/dist/types/schema/index.d.ts.map +1 -1
  191. package/dist/types/schema/tenant.graphql.d.ts.map +1 -1
  192. package/dist/types/tsconfig.tsbuildinfo +1 -1
  193. package/package.json +12 -12
  194. package/src/migrations/2026-09-04-120000-idp-disable-local-authentication.ts +18 -0
  195. package/src/migrations/runner.ts +2 -0
  196. package/src/migrations/snapshot.ts +2 -1
  197. package/src/model/commands/idp/CreateIdpCommand.ts +7 -1
  198. package/src/model/commands/idp/UpdateIdpCommand.ts +5 -1
  199. package/src/model/queries/idp/LocalAuthDisablingIdpsQuery.ts +41 -0
  200. package/src/model/queries/idp/PersonIdentityProvidersQuery.ts +2 -0
  201. package/src/model/queries/idp/helpers.ts +3 -2
  202. package/src/model/queries/idp/index.ts +1 -0
  203. package/src/model/queries/idp/types.ts +1 -0
  204. package/src/model/service/PasswordResetManager.ts +9 -1
  205. package/src/model/service/PasswordlessSignInManager.ts +23 -1
  206. package/src/model/service/SignInManager.ts +9 -1
  207. package/src/model/service/idp/PersonIdentityProviderManager.ts +8 -0
  208. package/src/model/type/IdentityProvider.ts +2 -0
  209. package/src/resolvers/mutation/idp/AddIDPMutationResolver.ts +1 -0
  210. package/src/resolvers/mutation/idp/UpdateIDPMutationResolver.ts +1 -0
  211. package/src/resolvers/mutation/idp/audit.ts +1 -0
  212. package/src/resolvers/mutation/person/PasswordlessMutationResolver.ts +7 -0
  213. package/src/resolvers/mutation/person/SignInMutationResolver.ts +2 -2
  214. package/src/schema/index.ts +29 -0
  215. package/src/schema/tenant.graphql.ts +28 -0
  216. package/tests/cases/integration/mocked/gql/passwordless.ts +10 -0
  217. package/tests/cases/integration/mocked/idpClaimMappingConfig.test.ts +4 -4
  218. package/tests/cases/integration/mocked/localAuthenticationDisabled.test.ts +182 -0
  219. package/tests/cases/integration/mocked/personIdentityProviders.test.ts +67 -0
  220. package/tests/cases/integration/mocked/signInAnomalyDetection.test.ts +11 -0
  221. package/tests/cases/integration/mocked/signInIdpClaimMapping.test.ts +14 -0
  222. package/tests/cases/integration/mocked/signInIdpClaimMappingFixes.test.ts +4 -0
  223. package/tests/cases/integration/mocked/signInIdpClaimMappingSafety.test.ts +6 -0
  224. package/tests/cases/integration/mocked/signInIdpMutation.test.ts +5 -0
  225. package/tests/cases/integration/mocked/signInMfaEnforcement.test.ts +7 -0
  226. package/tests/cases/integration/mocked/signInMutation.test.ts +14 -0
  227. package/tests/cases/integration/mocked/signInPasswordlessMutation.test.ts +36 -0
  228. package/tests/cases/integration/mocked/sql/getIdpBySlugSql.ts +1 -1
  229. package/tests/cases/integration/mocked/sql/localAuthDisablingIdpsSql.ts +21 -0
  230. package/tests/cases/integration/mocked/sql/personIdentityProvidersSql.ts +3 -1
  231. package/tests/cases/integration/mocked/trustForwardedClientInfo.test.ts +3 -0
  232. package/tests/cases/unit/idp/idpManagerUnknownConfigKeys.test.ts +8 -1
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sources":["../../../../../packages/engine-tenant-api/src/migrations/snapshot.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { TenantMigrationArgs } from './types.js'\nimport { createCredentials } from './tenantCredentials.js'\n\nexport default async function(builder: MigrationBuilder, args: TenantMigrationArgs) {\n\tbuilder.sql(`\nCREATE TYPE \"auth_log_type\" AS ENUM (\n 'login',\n 'create_session_token',\n 'idp_login',\n 'password_reset_init',\n 'password_reset',\n 'password_change',\n 'email_change',\n '2fa_disable',\n '2fa_enable',\n 'passwordless_login_init',\n 'passwordless_login_exchange',\n 'passwordless_login',\n 'person_disable',\n 'session_revoked_by_user',\n 'forced_sign_out',\n 'global_role_grant',\n 'global_role_revoke',\n 'project_membership_create',\n 'project_membership_update',\n 'project_membership_remove',\n 'api_key_create',\n 'api_key_disable',\n 'idp_create',\n 'idp_update',\n 'idp_disable',\n 'idp_enable',\n 'project_create',\n 'project_update',\n 'project_secret_change',\n 'mail_template_change',\n 'tenant_config_change',\n 'person_invite',\n 'backup_code_generated',\n 'backup_code_used',\n 'backup_code_regenerated',\n 'email_otp_sent',\n 'mfa_enrollment_required',\n 'mfa_reset',\n 'session_expired_idle',\n 'session_policy_applied',\n 'auth_policy_change',\n 'email_verify_init',\n 'email_verify_complete',\n 'email_change_init',\n 'email_change_complete',\n 'idp_session_revalidated',\n 'idp_session_revoked',\n 'idp_session_revalidation_failed',\n 'unusual_login_detected',\n 'step_up_required',\n 'idp_logout_initiated',\n 'idp_backchannel_logout',\n 'idp_role_mapped',\n 'idp_role_mapping_failed',\n 'person_enable'\n);\nCREATE TYPE \"config_policy\" AS ENUM (\n 'always',\n 'never',\n 'optIn',\n 'optOut'\n);\nCREATE TYPE \"config_singleton\" AS ENUM (\n 'singleton'\n);\nCREATE TYPE \"person_token_type\" AS ENUM (\n 'password_reset',\n 'passwordless',\n 'mfa_email_otp',\n 'email_verification',\n 'email_change'\n);\nCREATE FUNCTION \"project_deleted\"() RETURNS \"trigger\"\n LANGUAGE \"plpgsql\"\n AS $$\nBEGIN\n\tPERFORM pg_notify('project_updated', old.id::text);\n\tRETURN NULL;\nEND;\n$$;\nCREATE FUNCTION \"project_secret_updated\"() RETURNS \"trigger\"\n LANGUAGE \"plpgsql\"\n AS $$\nBEGIN\n\tUPDATE project SET updated_at = 'now' WHERE id = COALESCE(new.project_id, old.project_id);\n\tPERFORM pg_notify('project_updated', COALESCE(new.project_id, old.project_id)::TEXT);\n\tRETURN NULL;\nEND;\n$$;\nCREATE FUNCTION \"project_updated\"() RETURNS \"trigger\"\n LANGUAGE \"plpgsql\"\n AS $$\nBEGIN\n\tNEW.updated_at = 'now';\n\tPERFORM pg_notify('project_updated', new.id::text);\n\tRETURN new;\nEND;\n$$;\nCREATE TABLE \"api_key\" (\n \"id\" \"uuid\" NOT NULL,\n \"token_hash\" \"text\" NOT NULL,\n \"type\" \"text\" NOT NULL,\n \"identity_id\" \"uuid\" NOT NULL,\n \"expires_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone NOT NULL,\n \"expiration\" integer,\n \"disabled_at\" timestamp with time zone,\n \"last_ip\" \"inet\",\n \"last_user_agent\" \"text\",\n \"last_used_at\" timestamp with time zone,\n \"created_ip\" \"inet\",\n \"created_user_agent\" \"text\",\n \"trust_forwarded_info\" boolean DEFAULT false NOT NULL,\n \"issued_at\" timestamp with time zone,\n \"idle_timeout\" interval,\n \"max_expires_at\" timestamp with time zone\n);\nCREATE TABLE \"auth_policy\" (\n \"id\" \"uuid\" NOT NULL,\n \"scope\" \"text\" NOT NULL,\n \"project_id\" \"uuid\",\n \"roles\" \"text\"[] NOT NULL,\n \"mfa_required\" boolean,\n \"token_expiration\" interval,\n \"idle_timeout\" interval,\n \"remember_me_allowed\" boolean,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"grace_duration\" interval\n);\nCREATE TABLE \"config\" (\n \"id\" \"config_singleton\" DEFAULT 'singleton'::\"config_singleton\" NOT NULL,\n \"passwordless_enabled\" \"config_policy\" DEFAULT 'never'::\"config_policy\" NOT NULL,\n \"passwordless_url\" \"text\",\n \"passwordless_expiration\" interval DEFAULT '00:05:00'::interval NOT NULL,\n \"password_min_length\" integer DEFAULT 8 NOT NULL,\n \"password_require_uppercase\" integer DEFAULT 1 NOT NULL,\n \"password_require_lowercase\" integer DEFAULT 1 NOT NULL,\n \"password_require_digit\" integer DEFAULT 1 NOT NULL,\n \"password_require_special\" integer DEFAULT 0 NOT NULL,\n \"password_pattern\" \"text\",\n \"password_check_blacklist\" boolean DEFAULT true NOT NULL,\n \"login_base_backoff\" interval DEFAULT '00:00:01'::interval NOT NULL,\n \"login_max_backoff\" interval DEFAULT '00:01:00'::interval NOT NULL,\n \"login_attempt_window\" interval DEFAULT '00:05:00'::interval NOT NULL,\n \"login_reveal_user_exits\" boolean DEFAULT true NOT NULL,\n \"login_default_token_expiration\" interval DEFAULT '00:30:00'::interval NOT NULL,\n \"login_max_token_expiration\" interval DEFAULT '6 mons'::interval,\n \"password_check_hibp\" boolean DEFAULT false NOT NULL,\n \"captcha_provider\" \"text\",\n \"captcha_secret\" \"bytea\",\n \"captcha_secret_version\" integer,\n \"captcha_threshold\" double precision,\n \"rate_limit_sign_up_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_sign_up_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"rate_limit_login_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_login_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"rate_limit_password_reset_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_password_reset_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"rate_limit_passwordless_init_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_passwordless_init_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"login_reveal_login_method\" boolean DEFAULT true NOT NULL,\n \"login_mfa_grace_duration\" interval DEFAULT '00:00:00'::interval NOT NULL,\n \"rate_limit_email_otp_per_person_limit\" integer DEFAULT 10 NOT NULL,\n \"rate_limit_email_otp_per_person_window\" interval DEFAULT '00:10:00'::interval NOT NULL,\n \"signup_require_email_verification\" boolean DEFAULT false NOT NULL,\n \"require_email_change_verification\" boolean DEFAULT false NOT NULL,\n \"rate_limit_email_verification_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_email_verification_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"captcha_protect_sign_up\" boolean DEFAULT true NOT NULL,\n \"captcha_protect_password_reset\" boolean DEFAULT true NOT NULL,\n \"captcha_protect_passwordless_init\" boolean DEFAULT true NOT NULL,\n \"captcha_protect_email_verification\" boolean DEFAULT false NOT NULL,\n \"login_anomaly_detection_enabled\" boolean DEFAULT false NOT NULL,\n \"login_anomaly_history_size\" integer DEFAULT 10 NOT NULL,\n \"login_anomaly_email_threshold\" integer DEFAULT 1 NOT NULL,\n \"login_anomaly_step_up_threshold\" integer DEFAULT 3 NOT NULL,\n \"panel_global_roles\" \"text\"[] DEFAULT '{super_admin,project_admin}'::\"text\"[] NOT NULL,\n \"panel_project_roles\" \"text\"[] DEFAULT '{admin}'::\"text\"[] NOT NULL,\n CONSTRAINT \"config_captcha_complete\" CHECK (((\"captcha_provider\" IS NULL) OR ((\"captcha_secret\" IS NOT NULL) AND (\"captcha_secret_version\" IS NOT NULL)))),\n CONSTRAINT \"config_captcha_provider_check\" CHECK (((\"captcha_provider\" IS NULL) OR (\"captcha_provider\" = ANY (ARRAY['turnstile'::\"text\", 'hcaptcha'::\"text\", 'recaptchaV3'::\"text\"]))))\n);\nCREATE TABLE \"identity\" (\n \"id\" \"uuid\" NOT NULL,\n \"parent_id\" \"uuid\",\n \"roles\" \"jsonb\" NOT NULL,\n \"description\" \"text\",\n \"created_at\" timestamp with time zone NOT NULL\n);\nCREATE TABLE \"identity_provider\" (\n \"id\" \"uuid\" NOT NULL,\n \"slug\" \"text\" NOT NULL,\n \"type\" \"text\" NOT NULL,\n \"configuration\" \"jsonb\" NOT NULL,\n \"disabled_at\" timestamp with time zone,\n \"auto_sign_up\" boolean DEFAULT false NOT NULL,\n \"exclusive\" boolean DEFAULT false,\n \"init_returns_config\" boolean DEFAULT false NOT NULL,\n \"require_verified_email\" boolean DEFAULT false NOT NULL,\n \"assume_email_verified\" boolean DEFAULT false NOT NULL\n);\nCREATE TABLE \"idp_session\" (\n \"id\" \"uuid\" NOT NULL,\n \"api_key_id\" \"uuid\" NOT NULL,\n \"identity_provider_id\" \"uuid\" NOT NULL,\n \"idp_session_id\" \"text\",\n \"tokens\" \"bytea\",\n \"tokens_version\" integer,\n \"idp_expires_at\" timestamp with time zone,\n \"token_obtained_at\" timestamp with time zone,\n \"last_validated_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nCREATE TABLE \"mail_template\" (\n \"id\" \"uuid\" NOT NULL,\n \"project_id\" \"uuid\",\n \"mail_type\" \"text\" NOT NULL,\n \"variant\" \"text\" NOT NULL,\n \"subject\" \"text\" NOT NULL,\n \"content\" \"text\" NOT NULL,\n \"use_layout\" boolean NOT NULL,\n \"reply_to\" \"text\"\n);\nCREATE TABLE \"person\" (\n \"id\" \"uuid\" NOT NULL,\n \"email\" \"text\",\n \"password_hash\" \"text\",\n \"identity_id\" \"uuid\" NOT NULL,\n \"name\" \"text\",\n \"idp_only\" boolean DEFAULT false NOT NULL,\n \"disabled_at\" timestamp with time zone,\n \"passwordless_enabled\" boolean,\n \"mfa_grace_until\" timestamp with time zone,\n \"email_verified_at\" timestamp with time zone,\n \"email_verification_required\" boolean DEFAULT false NOT NULL,\n CONSTRAINT \"idp_only_no_email\" CHECK (((\"idp_only\" = false) OR ((\"idp_only\" = true) AND (\"email\" IS NULL))))\n);\nCREATE TABLE \"person_auth_log\" (\n \"id\" \"uuid\" NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"invoked_by_id\" \"uuid\",\n \"person_id\" \"uuid\",\n \"person_token_id\" \"uuid\",\n \"person_input_identifier\" \"text\",\n \"type\" \"auth_log_type\" NOT NULL,\n \"success\" boolean NOT NULL,\n \"error_code\" \"text\",\n \"error_message\" \"text\",\n \"ip_address\" \"inet\",\n \"user_agent\" \"text\",\n \"identity_provider_id\" \"uuid\",\n \"metadata\" \"jsonb\",\n \"target_person_id\" \"uuid\",\n \"event_data\" \"jsonb\",\n \"geo_country\" \"text\",\n \"device_fingerprint\" \"text\"\n);\nCREATE TABLE \"person_backup_code\" (\n \"id\" \"uuid\" NOT NULL,\n \"person_id\" \"uuid\" NOT NULL,\n \"code_hash\" \"text\" NOT NULL,\n \"used_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nCREATE TABLE \"person_identity_provider\" (\n \"id\" \"uuid\" NOT NULL,\n \"person_id\" \"uuid\" NOT NULL,\n \"identity_provider_id\" \"uuid\" NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"external_identifier\" \"text\" NOT NULL\n);\nCREATE TABLE \"person_mfa\" (\n \"person_id\" \"uuid\" NOT NULL,\n \"totp_secret\" \"bytea\",\n \"totp_secret_version\" integer,\n \"totp_activated_at\" timestamp with time zone,\n \"totp_pending_secret\" \"bytea\",\n \"totp_pending_version\" integer,\n \"totp_pending_created_at\" timestamp with time zone,\n \"email_otp_enabled\" boolean DEFAULT false NOT NULL\n);\nCREATE TABLE \"person_token\" (\n \"id\" \"uuid\" NOT NULL,\n \"token_hash\" \"text\" NOT NULL,\n \"person_id\" \"uuid\" NOT NULL,\n \"expires_at\" timestamp with time zone NOT NULL,\n \"created_at\" timestamp with time zone NOT NULL,\n \"used_at\" timestamp with time zone,\n \"type\" \"person_token_type\" DEFAULT 'password_reset'::\"person_token_type\" NOT NULL,\n \"otp_hash\" \"text\",\n \"otp_attempts\" integer DEFAULT 0 NOT NULL,\n \"meta\" \"jsonb\"\n);\nCREATE TABLE \"project\" (\n \"id\" \"uuid\" NOT NULL,\n \"name\" \"text\" NOT NULL,\n \"slug\" \"text\" NOT NULL,\n \"config\" \"jsonb\" DEFAULT '{}'::\"jsonb\" NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nCREATE TABLE \"project_membership\" (\n \"id\" \"uuid\" NOT NULL,\n \"project_id\" \"uuid\" NOT NULL,\n \"identity_id\" \"uuid\" NOT NULL,\n \"role\" \"text\" NOT NULL\n);\nCREATE TABLE \"project_membership_variable\" (\n \"id\" \"uuid\" NOT NULL,\n \"membership_id\" \"uuid\" NOT NULL,\n \"variable\" \"text\" NOT NULL,\n \"value\" \"jsonb\" NOT NULL\n);\nCREATE TABLE \"project_secret\" (\n \"id\" \"uuid\" NOT NULL,\n \"project_id\" \"uuid\" NOT NULL,\n \"key\" \"text\" NOT NULL,\n \"created_at\" timestamp with time zone NOT NULL,\n \"updated_at\" timestamp with time zone NOT NULL,\n \"value\" \"bytea\" NOT NULL,\n \"version\" smallint NOT NULL\n);\nCREATE TABLE \"rate_limit_event\" (\n \"id\" \"uuid\" NOT NULL,\n \"scope\" \"text\" NOT NULL,\n \"key_hash\" \"bytea\" NOT NULL,\n \"occurred_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nALTER TABLE ONLY \"api_key\"\n ADD CONSTRAINT \"api_key_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"auth_policy\"\n ADD CONSTRAINT \"auth_policy_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"config\"\n ADD CONSTRAINT \"config_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"email_unique\" UNIQUE (\"email\");\nALTER TABLE ONLY \"identity\"\n ADD CONSTRAINT \"identity_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"identity_provider\"\n ADD CONSTRAINT \"identity_provider_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"identity_provider\"\n ADD CONSTRAINT \"identity_provider_slug_key\" UNIQUE (\"slug\");\nALTER TABLE ONLY \"idp_session\"\n ADD CONSTRAINT \"idp_session_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"mail_template\"\n ADD CONSTRAINT \"mail_template_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person_backup_code\"\n ADD CONSTRAINT \"person_backup_code_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"person_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"person_identity_id_key\" UNIQUE (\"identity_id\");\nALTER TABLE ONLY \"person_identity_provider\"\n ADD CONSTRAINT \"person_identity_provider_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person_mfa\"\n ADD CONSTRAINT \"person_mfa_pkey\" PRIMARY KEY (\"person_id\");\nALTER TABLE ONLY \"person_token\"\n ADD CONSTRAINT \"person_password_reset_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project\"\n ADD CONSTRAINT \"project_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project_membership\"\n ADD CONSTRAINT \"project_membership_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project_membership_variable\"\n ADD CONSTRAINT \"project_membership_variable_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project_membership_variable\"\n ADD CONSTRAINT \"project_membership_variable_unique\" UNIQUE (\"membership_id\", \"variable\");\nALTER TABLE ONLY \"project_secret\"\n ADD CONSTRAINT \"project_secret_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"rate_limit_event\"\n ADD CONSTRAINT \"rate_limit_event_pkey\" PRIMARY KEY (\"id\");\nCREATE INDEX \"api_key_identity_id\" ON \"api_key\" USING \"btree\" (\"identity_id\");\nCREATE UNIQUE INDEX \"api_key_token_hash\" ON \"api_key\" USING \"btree\" (\"token_hash\");\nCREATE INDEX \"auth_policy_project_id_idx\" ON \"auth_policy\" USING \"btree\" (\"project_id\");\nCREATE INDEX \"identity_parent_id\" ON \"identity\" USING \"btree\" (\"parent_id\");\nCREATE UNIQUE INDEX \"idp_session_api_key_id\" ON \"idp_session\" USING \"btree\" (\"api_key_id\");\nCREATE INDEX \"idp_session_sid\" ON \"idp_session\" USING \"btree\" (\"identity_provider_id\", \"idp_session_id\");\nCREATE UNIQUE INDEX \"mail_template_identifier\" ON \"mail_template\" USING \"btree\" (\"project_id\", \"mail_type\", \"variant\") WHERE (\"project_id\" IS NOT NULL);\nCREATE UNIQUE INDEX \"mail_template_identifier_global\" ON \"mail_template\" USING \"btree\" (\"mail_type\", \"variant\") WHERE (\"project_id\" IS NULL);\nCREATE INDEX \"mail_template_project_index\" ON \"mail_template\" USING \"btree\" (\"project_id\");\nCREATE INDEX \"person_auth_log_person_id_created_at_idx\" ON \"person_auth_log\" USING \"btree\" (\"person_id\", \"created_at\" DESC);\nCREATE INDEX \"person_auth_log_person_input_identifier_created_at_idx\" ON \"person_auth_log\" USING \"btree\" (\"person_input_identifier\", \"created_at\" DESC) WHERE ((\"type\" = 'login'::\"auth_log_type\") AND (\"success\" = false));\nCREATE INDEX \"person_auth_log_target_person_id_created_at_idx\" ON \"person_auth_log\" USING \"btree\" (\"target_person_id\", \"created_at\" DESC);\nCREATE INDEX \"person_backup_code_person_id_idx\" ON \"person_backup_code\" USING \"btree\" (\"person_id\");\nCREATE INDEX \"person_identity_id\" ON \"person\" USING \"btree\" (\"identity_id\");\nCREATE UNIQUE INDEX \"person_identity_provider_identifier\" ON \"person_identity_provider\" USING \"btree\" (\"identity_provider_id\", \"external_identifier\");\nCREATE INDEX \"person_identity_provider_person_id\" ON \"person_identity_provider\" USING \"btree\" (\"person_id\");\nCREATE UNIQUE INDEX \"person_password_reset_token\" ON \"person_token\" USING \"btree\" (\"token_hash\");\nCREATE INDEX \"project_alias\" ON \"project\" USING \"gin\" (((\"config\" -> 'alias'::\"text\")));\nCREATE INDEX \"project_membership_identity_index\" ON \"project_membership\" USING \"btree\" (\"identity_id\");\nCREATE UNIQUE INDEX \"project_membership_unique\" ON \"project_membership\" USING \"btree\" (\"project_id\", \"identity_id\", \"role\");\nCREATE INDEX \"project_secret_project_index\" ON \"project_secret\" USING \"btree\" (\"project_id\");\nCREATE UNIQUE INDEX \"project_secret_unique\" ON \"project_secret\" USING \"btree\" (\"project_id\", \"key\");\nCREATE UNIQUE INDEX \"project_slug\" ON \"project\" USING \"btree\" (\"slug\");\nCREATE INDEX \"rate_limit_event_lookup\" ON \"rate_limit_event\" USING \"btree\" (\"scope\", \"key_hash\", \"occurred_at\" DESC);\nCREATE INDEX \"rate_limit_event_occurred_at_brin\" ON \"rate_limit_event\" USING \"brin\" (\"occurred_at\");\nCREATE TRIGGER \"project_deleted\" AFTER DELETE ON \"project\" FOR EACH ROW EXECUTE FUNCTION \"project_deleted\"();\nCREATE TRIGGER \"project_secret_updated\" AFTER INSERT OR DELETE OR UPDATE ON \"project_secret\" FOR EACH ROW EXECUTE FUNCTION \"project_secret_updated\"();\nCREATE TRIGGER \"project_updated\" BEFORE INSERT OR UPDATE OF \"name\", \"slug\", \"config\" ON \"project\" FOR EACH ROW EXECUTE FUNCTION \"project_updated\"();\nALTER TABLE ONLY \"api_key\"\n ADD CONSTRAINT \"api_key_identity_id_fkey\" FOREIGN KEY (\"identity_id\") REFERENCES \"identity\"(\"id\");\nALTER TABLE ONLY \"auth_policy\"\n ADD CONSTRAINT \"auth_policy_project_id_fkey\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"identity\"\n ADD CONSTRAINT \"identity_parent_id_fkey\" FOREIGN KEY (\"parent_id\") REFERENCES \"identity\"(\"id\");\nALTER TABLE ONLY \"idp_session\"\n ADD CONSTRAINT \"idp_session_api_key\" FOREIGN KEY (\"api_key_id\") REFERENCES \"api_key\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"idp_session\"\n ADD CONSTRAINT \"idp_session_idp\" FOREIGN KEY (\"identity_provider_id\") REFERENCES \"identity_provider\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"mail_template\"\n ADD CONSTRAINT \"mail_template_project\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_identity_provider_id_fkey\" FOREIGN KEY (\"identity_provider_id\") REFERENCES \"identity_provider\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_invoked_by_id_fkey\" FOREIGN KEY (\"invoked_by_id\") REFERENCES \"identity\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_person_id_fkey\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_person_token_id_fkey\" FOREIGN KEY (\"person_token_id\") REFERENCES \"person_token\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_target_person_id_fkey\" FOREIGN KEY (\"target_person_id\") REFERENCES \"person\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_backup_code\"\n ADD CONSTRAINT \"person_backup_code_person_id_fkey\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"person_identity_id_fkey\" FOREIGN KEY (\"identity_id\") REFERENCES \"identity\"(\"id\");\nALTER TABLE ONLY \"person_identity_provider\"\n ADD CONSTRAINT \"person_identity_provider_idp\" FOREIGN KEY (\"identity_provider_id\") REFERENCES \"identity_provider\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_identity_provider\"\n ADD CONSTRAINT \"person_identity_provider_person\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_mfa\"\n ADD CONSTRAINT \"person_mfa_person_id_fkey\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_token\"\n ADD CONSTRAINT \"person_password_reset_person\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_membership\"\n ADD CONSTRAINT \"project_membership_identity\" FOREIGN KEY (\"identity_id\") REFERENCES \"identity\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_membership\"\n ADD CONSTRAINT \"project_membership_project\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_membership_variable\"\n ADD CONSTRAINT \"project_membership_variable_membership\" FOREIGN KEY (\"membership_id\") REFERENCES \"project_membership\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_secret\"\n ADD CONSTRAINT \"project_secret_project\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nINSERT INTO \"config\" (id)\nVALUES (DEFAULT);\n\nDO LANGUAGE plpgsql\n$$\n\tBEGIN\n\t\tEXECUTE FORMAT('ALTER FUNCTION project_secret_updated() SET SEARCH_PATH = %s', QUOTE_IDENT(CURRENT_SCHEMA()));\n\tEND\n$$;\n`)\n\n\tawait createCredentials(builder, args)\n}\n"],"names":[],"mappings":";AAIA,eAAA,SAA8B,SAA2B,MAA2B;AACnF,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAocZ;AAEA,QAAM,kBAAkB,SAAS,IAAI;AACtC;"}
1
+ {"version":3,"file":"snapshot.js","sources":["../../../../../packages/engine-tenant-api/src/migrations/snapshot.ts"],"sourcesContent":["import { MigrationBuilder } from '@contember/database-migrations'\nimport { TenantMigrationArgs } from './types.js'\nimport { createCredentials } from './tenantCredentials.js'\n\nexport default async function(builder: MigrationBuilder, args: TenantMigrationArgs) {\n\tbuilder.sql(`\nCREATE TYPE \"auth_log_type\" AS ENUM (\n 'login',\n 'create_session_token',\n 'idp_login',\n 'password_reset_init',\n 'password_reset',\n 'password_change',\n 'email_change',\n '2fa_disable',\n '2fa_enable',\n 'passwordless_login_init',\n 'passwordless_login_exchange',\n 'passwordless_login',\n 'person_disable',\n 'session_revoked_by_user',\n 'forced_sign_out',\n 'global_role_grant',\n 'global_role_revoke',\n 'project_membership_create',\n 'project_membership_update',\n 'project_membership_remove',\n 'api_key_create',\n 'api_key_disable',\n 'idp_create',\n 'idp_update',\n 'idp_disable',\n 'idp_enable',\n 'project_create',\n 'project_update',\n 'project_secret_change',\n 'mail_template_change',\n 'tenant_config_change',\n 'person_invite',\n 'backup_code_generated',\n 'backup_code_used',\n 'backup_code_regenerated',\n 'email_otp_sent',\n 'mfa_enrollment_required',\n 'mfa_reset',\n 'session_expired_idle',\n 'session_policy_applied',\n 'auth_policy_change',\n 'email_verify_init',\n 'email_verify_complete',\n 'email_change_init',\n 'email_change_complete',\n 'idp_session_revalidated',\n 'idp_session_revoked',\n 'idp_session_revalidation_failed',\n 'unusual_login_detected',\n 'step_up_required',\n 'idp_logout_initiated',\n 'idp_backchannel_logout',\n 'idp_role_mapped',\n 'idp_role_mapping_failed',\n 'person_enable'\n);\nCREATE TYPE \"config_policy\" AS ENUM (\n 'always',\n 'never',\n 'optIn',\n 'optOut'\n);\nCREATE TYPE \"config_singleton\" AS ENUM (\n 'singleton'\n);\nCREATE TYPE \"person_token_type\" AS ENUM (\n 'password_reset',\n 'passwordless',\n 'mfa_email_otp',\n 'email_verification',\n 'email_change'\n);\nCREATE FUNCTION \"project_deleted\"() RETURNS \"trigger\"\n LANGUAGE \"plpgsql\"\n AS $$\nBEGIN\n\tPERFORM pg_notify('project_updated', old.id::text);\n\tRETURN NULL;\nEND;\n$$;\nCREATE FUNCTION \"project_secret_updated\"() RETURNS \"trigger\"\n LANGUAGE \"plpgsql\"\n AS $$\nBEGIN\n\tUPDATE project SET updated_at = 'now' WHERE id = COALESCE(new.project_id, old.project_id);\n\tPERFORM pg_notify('project_updated', COALESCE(new.project_id, old.project_id)::TEXT);\n\tRETURN NULL;\nEND;\n$$;\nCREATE FUNCTION \"project_updated\"() RETURNS \"trigger\"\n LANGUAGE \"plpgsql\"\n AS $$\nBEGIN\n\tNEW.updated_at = 'now';\n\tPERFORM pg_notify('project_updated', new.id::text);\n\tRETURN new;\nEND;\n$$;\nCREATE TABLE \"api_key\" (\n \"id\" \"uuid\" NOT NULL,\n \"token_hash\" \"text\" NOT NULL,\n \"type\" \"text\" NOT NULL,\n \"identity_id\" \"uuid\" NOT NULL,\n \"expires_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone NOT NULL,\n \"expiration\" integer,\n \"disabled_at\" timestamp with time zone,\n \"last_ip\" \"inet\",\n \"last_user_agent\" \"text\",\n \"last_used_at\" timestamp with time zone,\n \"created_ip\" \"inet\",\n \"created_user_agent\" \"text\",\n \"trust_forwarded_info\" boolean DEFAULT false NOT NULL,\n \"issued_at\" timestamp with time zone,\n \"idle_timeout\" interval,\n \"max_expires_at\" timestamp with time zone\n);\nCREATE TABLE \"auth_policy\" (\n \"id\" \"uuid\" NOT NULL,\n \"scope\" \"text\" NOT NULL,\n \"project_id\" \"uuid\",\n \"roles\" \"text\"[] NOT NULL,\n \"mfa_required\" boolean,\n \"token_expiration\" interval,\n \"idle_timeout\" interval,\n \"remember_me_allowed\" boolean,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"grace_duration\" interval\n);\nCREATE TABLE \"config\" (\n \"id\" \"config_singleton\" DEFAULT 'singleton'::\"config_singleton\" NOT NULL,\n \"passwordless_enabled\" \"config_policy\" DEFAULT 'never'::\"config_policy\" NOT NULL,\n \"passwordless_url\" \"text\",\n \"passwordless_expiration\" interval DEFAULT '00:05:00'::interval NOT NULL,\n \"password_min_length\" integer DEFAULT 8 NOT NULL,\n \"password_require_uppercase\" integer DEFAULT 1 NOT NULL,\n \"password_require_lowercase\" integer DEFAULT 1 NOT NULL,\n \"password_require_digit\" integer DEFAULT 1 NOT NULL,\n \"password_require_special\" integer DEFAULT 0 NOT NULL,\n \"password_pattern\" \"text\",\n \"password_check_blacklist\" boolean DEFAULT true NOT NULL,\n \"login_base_backoff\" interval DEFAULT '00:00:01'::interval NOT NULL,\n \"login_max_backoff\" interval DEFAULT '00:01:00'::interval NOT NULL,\n \"login_attempt_window\" interval DEFAULT '00:05:00'::interval NOT NULL,\n \"login_reveal_user_exits\" boolean DEFAULT true NOT NULL,\n \"login_default_token_expiration\" interval DEFAULT '00:30:00'::interval NOT NULL,\n \"login_max_token_expiration\" interval DEFAULT '6 mons'::interval,\n \"password_check_hibp\" boolean DEFAULT false NOT NULL,\n \"captcha_provider\" \"text\",\n \"captcha_secret\" \"bytea\",\n \"captcha_secret_version\" integer,\n \"captcha_threshold\" double precision,\n \"rate_limit_sign_up_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_sign_up_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"rate_limit_login_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_login_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"rate_limit_password_reset_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_password_reset_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"rate_limit_passwordless_init_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_passwordless_init_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"login_reveal_login_method\" boolean DEFAULT true NOT NULL,\n \"login_mfa_grace_duration\" interval DEFAULT '00:00:00'::interval NOT NULL,\n \"rate_limit_email_otp_per_person_limit\" integer DEFAULT 10 NOT NULL,\n \"rate_limit_email_otp_per_person_window\" interval DEFAULT '00:10:00'::interval NOT NULL,\n \"signup_require_email_verification\" boolean DEFAULT false NOT NULL,\n \"require_email_change_verification\" boolean DEFAULT false NOT NULL,\n \"rate_limit_email_verification_per_ip_limit\" integer DEFAULT 0 NOT NULL,\n \"rate_limit_email_verification_per_ip_window\" interval DEFAULT '01:00:00'::interval NOT NULL,\n \"captcha_protect_sign_up\" boolean DEFAULT true NOT NULL,\n \"captcha_protect_password_reset\" boolean DEFAULT true NOT NULL,\n \"captcha_protect_passwordless_init\" boolean DEFAULT true NOT NULL,\n \"captcha_protect_email_verification\" boolean DEFAULT false NOT NULL,\n \"login_anomaly_detection_enabled\" boolean DEFAULT false NOT NULL,\n \"login_anomaly_history_size\" integer DEFAULT 10 NOT NULL,\n \"login_anomaly_email_threshold\" integer DEFAULT 1 NOT NULL,\n \"login_anomaly_step_up_threshold\" integer DEFAULT 3 NOT NULL,\n \"panel_global_roles\" \"text\"[] DEFAULT '{super_admin,project_admin}'::\"text\"[] NOT NULL,\n \"panel_project_roles\" \"text\"[] DEFAULT '{admin}'::\"text\"[] NOT NULL,\n CONSTRAINT \"config_captcha_complete\" CHECK (((\"captcha_provider\" IS NULL) OR ((\"captcha_secret\" IS NOT NULL) AND (\"captcha_secret_version\" IS NOT NULL)))),\n CONSTRAINT \"config_captcha_provider_check\" CHECK (((\"captcha_provider\" IS NULL) OR (\"captcha_provider\" = ANY (ARRAY['turnstile'::\"text\", 'hcaptcha'::\"text\", 'recaptchaV3'::\"text\"]))))\n);\nCREATE TABLE \"identity\" (\n \"id\" \"uuid\" NOT NULL,\n \"parent_id\" \"uuid\",\n \"roles\" \"jsonb\" NOT NULL,\n \"description\" \"text\",\n \"created_at\" timestamp with time zone NOT NULL\n);\nCREATE TABLE \"identity_provider\" (\n \"id\" \"uuid\" NOT NULL,\n \"slug\" \"text\" NOT NULL,\n \"type\" \"text\" NOT NULL,\n \"configuration\" \"jsonb\" NOT NULL,\n \"disabled_at\" timestamp with time zone,\n \"auto_sign_up\" boolean DEFAULT false NOT NULL,\n \"exclusive\" boolean DEFAULT false,\n \"init_returns_config\" boolean DEFAULT false NOT NULL,\n \"require_verified_email\" boolean DEFAULT false NOT NULL,\n \"assume_email_verified\" boolean DEFAULT false NOT NULL,\n \"disable_local_authentication\" boolean DEFAULT false NOT NULL\n);\nCREATE TABLE \"idp_session\" (\n \"id\" \"uuid\" NOT NULL,\n \"api_key_id\" \"uuid\" NOT NULL,\n \"identity_provider_id\" \"uuid\" NOT NULL,\n \"idp_session_id\" \"text\",\n \"tokens\" \"bytea\",\n \"tokens_version\" integer,\n \"idp_expires_at\" timestamp with time zone,\n \"token_obtained_at\" timestamp with time zone,\n \"last_validated_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nCREATE TABLE \"mail_template\" (\n \"id\" \"uuid\" NOT NULL,\n \"project_id\" \"uuid\",\n \"mail_type\" \"text\" NOT NULL,\n \"variant\" \"text\" NOT NULL,\n \"subject\" \"text\" NOT NULL,\n \"content\" \"text\" NOT NULL,\n \"use_layout\" boolean NOT NULL,\n \"reply_to\" \"text\"\n);\nCREATE TABLE \"person\" (\n \"id\" \"uuid\" NOT NULL,\n \"email\" \"text\",\n \"password_hash\" \"text\",\n \"identity_id\" \"uuid\" NOT NULL,\n \"name\" \"text\",\n \"idp_only\" boolean DEFAULT false NOT NULL,\n \"disabled_at\" timestamp with time zone,\n \"passwordless_enabled\" boolean,\n \"mfa_grace_until\" timestamp with time zone,\n \"email_verified_at\" timestamp with time zone,\n \"email_verification_required\" boolean DEFAULT false NOT NULL,\n CONSTRAINT \"idp_only_no_email\" CHECK (((\"idp_only\" = false) OR ((\"idp_only\" = true) AND (\"email\" IS NULL))))\n);\nCREATE TABLE \"person_auth_log\" (\n \"id\" \"uuid\" NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"invoked_by_id\" \"uuid\",\n \"person_id\" \"uuid\",\n \"person_token_id\" \"uuid\",\n \"person_input_identifier\" \"text\",\n \"type\" \"auth_log_type\" NOT NULL,\n \"success\" boolean NOT NULL,\n \"error_code\" \"text\",\n \"error_message\" \"text\",\n \"ip_address\" \"inet\",\n \"user_agent\" \"text\",\n \"identity_provider_id\" \"uuid\",\n \"metadata\" \"jsonb\",\n \"target_person_id\" \"uuid\",\n \"event_data\" \"jsonb\",\n \"geo_country\" \"text\",\n \"device_fingerprint\" \"text\"\n);\nCREATE TABLE \"person_backup_code\" (\n \"id\" \"uuid\" NOT NULL,\n \"person_id\" \"uuid\" NOT NULL,\n \"code_hash\" \"text\" NOT NULL,\n \"used_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nCREATE TABLE \"person_identity_provider\" (\n \"id\" \"uuid\" NOT NULL,\n \"person_id\" \"uuid\" NOT NULL,\n \"identity_provider_id\" \"uuid\" NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL,\n \"external_identifier\" \"text\" NOT NULL\n);\nCREATE TABLE \"person_mfa\" (\n \"person_id\" \"uuid\" NOT NULL,\n \"totp_secret\" \"bytea\",\n \"totp_secret_version\" integer,\n \"totp_activated_at\" timestamp with time zone,\n \"totp_pending_secret\" \"bytea\",\n \"totp_pending_version\" integer,\n \"totp_pending_created_at\" timestamp with time zone,\n \"email_otp_enabled\" boolean DEFAULT false NOT NULL\n);\nCREATE TABLE \"person_token\" (\n \"id\" \"uuid\" NOT NULL,\n \"token_hash\" \"text\" NOT NULL,\n \"person_id\" \"uuid\" NOT NULL,\n \"expires_at\" timestamp with time zone NOT NULL,\n \"created_at\" timestamp with time zone NOT NULL,\n \"used_at\" timestamp with time zone,\n \"type\" \"person_token_type\" DEFAULT 'password_reset'::\"person_token_type\" NOT NULL,\n \"otp_hash\" \"text\",\n \"otp_attempts\" integer DEFAULT 0 NOT NULL,\n \"meta\" \"jsonb\"\n);\nCREATE TABLE \"project\" (\n \"id\" \"uuid\" NOT NULL,\n \"name\" \"text\" NOT NULL,\n \"slug\" \"text\" NOT NULL,\n \"config\" \"jsonb\" DEFAULT '{}'::\"jsonb\" NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nCREATE TABLE \"project_membership\" (\n \"id\" \"uuid\" NOT NULL,\n \"project_id\" \"uuid\" NOT NULL,\n \"identity_id\" \"uuid\" NOT NULL,\n \"role\" \"text\" NOT NULL\n);\nCREATE TABLE \"project_membership_variable\" (\n \"id\" \"uuid\" NOT NULL,\n \"membership_id\" \"uuid\" NOT NULL,\n \"variable\" \"text\" NOT NULL,\n \"value\" \"jsonb\" NOT NULL\n);\nCREATE TABLE \"project_secret\" (\n \"id\" \"uuid\" NOT NULL,\n \"project_id\" \"uuid\" NOT NULL,\n \"key\" \"text\" NOT NULL,\n \"created_at\" timestamp with time zone NOT NULL,\n \"updated_at\" timestamp with time zone NOT NULL,\n \"value\" \"bytea\" NOT NULL,\n \"version\" smallint NOT NULL\n);\nCREATE TABLE \"rate_limit_event\" (\n \"id\" \"uuid\" NOT NULL,\n \"scope\" \"text\" NOT NULL,\n \"key_hash\" \"bytea\" NOT NULL,\n \"occurred_at\" timestamp with time zone DEFAULT \"now\"() NOT NULL\n);\nALTER TABLE ONLY \"api_key\"\n ADD CONSTRAINT \"api_key_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"auth_policy\"\n ADD CONSTRAINT \"auth_policy_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"config\"\n ADD CONSTRAINT \"config_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"email_unique\" UNIQUE (\"email\");\nALTER TABLE ONLY \"identity\"\n ADD CONSTRAINT \"identity_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"identity_provider\"\n ADD CONSTRAINT \"identity_provider_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"identity_provider\"\n ADD CONSTRAINT \"identity_provider_slug_key\" UNIQUE (\"slug\");\nALTER TABLE ONLY \"idp_session\"\n ADD CONSTRAINT \"idp_session_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"mail_template\"\n ADD CONSTRAINT \"mail_template_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person_backup_code\"\n ADD CONSTRAINT \"person_backup_code_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"person_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"person_identity_id_key\" UNIQUE (\"identity_id\");\nALTER TABLE ONLY \"person_identity_provider\"\n ADD CONSTRAINT \"person_identity_provider_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"person_mfa\"\n ADD CONSTRAINT \"person_mfa_pkey\" PRIMARY KEY (\"person_id\");\nALTER TABLE ONLY \"person_token\"\n ADD CONSTRAINT \"person_password_reset_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project\"\n ADD CONSTRAINT \"project_id\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project_membership\"\n ADD CONSTRAINT \"project_membership_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project_membership_variable\"\n ADD CONSTRAINT \"project_membership_variable_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"project_membership_variable\"\n ADD CONSTRAINT \"project_membership_variable_unique\" UNIQUE (\"membership_id\", \"variable\");\nALTER TABLE ONLY \"project_secret\"\n ADD CONSTRAINT \"project_secret_pkey\" PRIMARY KEY (\"id\");\nALTER TABLE ONLY \"rate_limit_event\"\n ADD CONSTRAINT \"rate_limit_event_pkey\" PRIMARY KEY (\"id\");\nCREATE INDEX \"api_key_identity_id\" ON \"api_key\" USING \"btree\" (\"identity_id\");\nCREATE UNIQUE INDEX \"api_key_token_hash\" ON \"api_key\" USING \"btree\" (\"token_hash\");\nCREATE INDEX \"auth_policy_project_id_idx\" ON \"auth_policy\" USING \"btree\" (\"project_id\");\nCREATE INDEX \"identity_parent_id\" ON \"identity\" USING \"btree\" (\"parent_id\");\nCREATE UNIQUE INDEX \"idp_session_api_key_id\" ON \"idp_session\" USING \"btree\" (\"api_key_id\");\nCREATE INDEX \"idp_session_sid\" ON \"idp_session\" USING \"btree\" (\"identity_provider_id\", \"idp_session_id\");\nCREATE UNIQUE INDEX \"mail_template_identifier\" ON \"mail_template\" USING \"btree\" (\"project_id\", \"mail_type\", \"variant\") WHERE (\"project_id\" IS NOT NULL);\nCREATE UNIQUE INDEX \"mail_template_identifier_global\" ON \"mail_template\" USING \"btree\" (\"mail_type\", \"variant\") WHERE (\"project_id\" IS NULL);\nCREATE INDEX \"mail_template_project_index\" ON \"mail_template\" USING \"btree\" (\"project_id\");\nCREATE INDEX \"person_auth_log_person_id_created_at_idx\" ON \"person_auth_log\" USING \"btree\" (\"person_id\", \"created_at\" DESC);\nCREATE INDEX \"person_auth_log_person_input_identifier_created_at_idx\" ON \"person_auth_log\" USING \"btree\" (\"person_input_identifier\", \"created_at\" DESC) WHERE ((\"type\" = 'login'::\"auth_log_type\") AND (\"success\" = false));\nCREATE INDEX \"person_auth_log_target_person_id_created_at_idx\" ON \"person_auth_log\" USING \"btree\" (\"target_person_id\", \"created_at\" DESC);\nCREATE INDEX \"person_backup_code_person_id_idx\" ON \"person_backup_code\" USING \"btree\" (\"person_id\");\nCREATE INDEX \"person_identity_id\" ON \"person\" USING \"btree\" (\"identity_id\");\nCREATE UNIQUE INDEX \"person_identity_provider_identifier\" ON \"person_identity_provider\" USING \"btree\" (\"identity_provider_id\", \"external_identifier\");\nCREATE INDEX \"person_identity_provider_person_id\" ON \"person_identity_provider\" USING \"btree\" (\"person_id\");\nCREATE UNIQUE INDEX \"person_password_reset_token\" ON \"person_token\" USING \"btree\" (\"token_hash\");\nCREATE INDEX \"project_alias\" ON \"project\" USING \"gin\" (((\"config\" -> 'alias'::\"text\")));\nCREATE INDEX \"project_membership_identity_index\" ON \"project_membership\" USING \"btree\" (\"identity_id\");\nCREATE UNIQUE INDEX \"project_membership_unique\" ON \"project_membership\" USING \"btree\" (\"project_id\", \"identity_id\", \"role\");\nCREATE INDEX \"project_secret_project_index\" ON \"project_secret\" USING \"btree\" (\"project_id\");\nCREATE UNIQUE INDEX \"project_secret_unique\" ON \"project_secret\" USING \"btree\" (\"project_id\", \"key\");\nCREATE UNIQUE INDEX \"project_slug\" ON \"project\" USING \"btree\" (\"slug\");\nCREATE INDEX \"rate_limit_event_lookup\" ON \"rate_limit_event\" USING \"btree\" (\"scope\", \"key_hash\", \"occurred_at\" DESC);\nCREATE INDEX \"rate_limit_event_occurred_at_brin\" ON \"rate_limit_event\" USING \"brin\" (\"occurred_at\");\nCREATE TRIGGER \"project_deleted\" AFTER DELETE ON \"project\" FOR EACH ROW EXECUTE FUNCTION \"project_deleted\"();\nCREATE TRIGGER \"project_secret_updated\" AFTER INSERT OR DELETE OR UPDATE ON \"project_secret\" FOR EACH ROW EXECUTE FUNCTION \"project_secret_updated\"();\nCREATE TRIGGER \"project_updated\" BEFORE INSERT OR UPDATE OF \"name\", \"slug\", \"config\" ON \"project\" FOR EACH ROW EXECUTE FUNCTION \"project_updated\"();\nALTER TABLE ONLY \"api_key\"\n ADD CONSTRAINT \"api_key_identity_id_fkey\" FOREIGN KEY (\"identity_id\") REFERENCES \"identity\"(\"id\");\nALTER TABLE ONLY \"auth_policy\"\n ADD CONSTRAINT \"auth_policy_project_id_fkey\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"identity\"\n ADD CONSTRAINT \"identity_parent_id_fkey\" FOREIGN KEY (\"parent_id\") REFERENCES \"identity\"(\"id\");\nALTER TABLE ONLY \"idp_session\"\n ADD CONSTRAINT \"idp_session_api_key\" FOREIGN KEY (\"api_key_id\") REFERENCES \"api_key\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"idp_session\"\n ADD CONSTRAINT \"idp_session_idp\" FOREIGN KEY (\"identity_provider_id\") REFERENCES \"identity_provider\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"mail_template\"\n ADD CONSTRAINT \"mail_template_project\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_identity_provider_id_fkey\" FOREIGN KEY (\"identity_provider_id\") REFERENCES \"identity_provider\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_invoked_by_id_fkey\" FOREIGN KEY (\"invoked_by_id\") REFERENCES \"identity\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_person_id_fkey\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_person_token_id_fkey\" FOREIGN KEY (\"person_token_id\") REFERENCES \"person_token\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_auth_log\"\n ADD CONSTRAINT \"person_auth_log_target_person_id_fkey\" FOREIGN KEY (\"target_person_id\") REFERENCES \"person\"(\"id\") ON DELETE SET NULL;\nALTER TABLE ONLY \"person_backup_code\"\n ADD CONSTRAINT \"person_backup_code_person_id_fkey\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person\"\n ADD CONSTRAINT \"person_identity_id_fkey\" FOREIGN KEY (\"identity_id\") REFERENCES \"identity\"(\"id\");\nALTER TABLE ONLY \"person_identity_provider\"\n ADD CONSTRAINT \"person_identity_provider_idp\" FOREIGN KEY (\"identity_provider_id\") REFERENCES \"identity_provider\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_identity_provider\"\n ADD CONSTRAINT \"person_identity_provider_person\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_mfa\"\n ADD CONSTRAINT \"person_mfa_person_id_fkey\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"person_token\"\n ADD CONSTRAINT \"person_password_reset_person\" FOREIGN KEY (\"person_id\") REFERENCES \"person\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_membership\"\n ADD CONSTRAINT \"project_membership_identity\" FOREIGN KEY (\"identity_id\") REFERENCES \"identity\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_membership\"\n ADD CONSTRAINT \"project_membership_project\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_membership_variable\"\n ADD CONSTRAINT \"project_membership_variable_membership\" FOREIGN KEY (\"membership_id\") REFERENCES \"project_membership\"(\"id\") ON DELETE CASCADE;\nALTER TABLE ONLY \"project_secret\"\n ADD CONSTRAINT \"project_secret_project\" FOREIGN KEY (\"project_id\") REFERENCES \"project\"(\"id\") ON DELETE CASCADE;\nINSERT INTO \"config\" (id)\nVALUES (DEFAULT);\n\nDO LANGUAGE plpgsql\n$$\n\tBEGIN\n\t\tEXECUTE FORMAT('ALTER FUNCTION project_secret_updated() SET SEARCH_PATH = %s', QUOTE_IDENT(CURRENT_SCHEMA()));\n\tEND\n$$;\n`)\n\n\tawait createCredentials(builder, args)\n}\n"],"names":[],"mappings":";AAIA,eAAA,SAA8B,SAA2B,MAA2B;AACnF,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAqcZ;AAEA,QAAM,kBAAkB,SAAS,IAAI;AACtC;"}
@@ -6,7 +6,12 @@ class CreateIdpCommand {
6
6
  this.data = data;
7
7
  }
8
8
  async execute({ db, providers }) {
9
- const { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified }, slug, type } = this.data;
9
+ const {
10
+ configuration,
11
+ options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication },
12
+ slug,
13
+ type
14
+ } = this.data;
10
15
  await Database.InsertBuilder.create().into("identity_provider").values({
11
16
  id: providers.uuid(),
12
17
  configuration,
@@ -16,7 +21,8 @@ class CreateIdpCommand {
16
21
  exclusive,
17
22
  init_returns_config: initReturnsConfig,
18
23
  require_verified_email: requireVerifiedEmail,
19
- assume_email_verified: assumeEmailVerified
24
+ assume_email_verified: assumeEmailVerified,
25
+ disable_local_authentication: disableLocalAuthentication
20
26
  }).execute(db);
21
27
  }
22
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CreateIdpCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/CreateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { InsertBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class CreateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate data: IdentityProviderData,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tconst { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified }, slug, type } = this.data\n\t\tawait InsertBuilder.create()\n\t\t\t.into('identity_provider')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tconfiguration,\n\t\t\t\tslug,\n\t\t\t\ttype,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";;;AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,MACP;AADO,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAM,EAAE,eAAe,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,oBAAA,GAAuB,MAAM,KAAA,IAAS,KAAK;AAC7I,UAAMA,SAAAA,cAAc,OAAA,EAClB,KAAK,mBAAmB,EACxB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,IAAA,CACvB,EACA,QAAQ,EAAE;AAAA,EACb;AACD;;"}
1
+ {"version":3,"file":"CreateIdpCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/CreateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { InsertBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class CreateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate data: IdentityProviderData,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tconst {\n\t\t\tconfiguration,\n\t\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication },\n\t\t\tslug,\n\t\t\ttype,\n\t\t} = this.data\n\t\tawait InsertBuilder.create()\n\t\t\t.into('identity_provider')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tconfiguration,\n\t\t\t\tslug,\n\t\t\t\ttype,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t\tdisable_local_authentication: disableLocalAuthentication,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";;;AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,MACP;AADO,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAM;AAAA,MACL;AAAA,MACA,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,qBAAqB,2BAAA;AAAA,MAChG;AAAA,MACA;AAAA,IAAA,IACG,KAAK;AACT,UAAMA,SAAAA,cAAc,OAAA,EAClB,KAAK,mBAAmB,EACxB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,8BAA8B;AAAA,IAAA,CAC9B,EACA,QAAQ,EAAE;AAAA,EACb;AACD;;"}
@@ -4,7 +4,12 @@ class CreateIdpCommand {
4
4
  this.data = data;
5
5
  }
6
6
  async execute({ db, providers }) {
7
- const { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified }, slug, type } = this.data;
7
+ const {
8
+ configuration,
9
+ options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication },
10
+ slug,
11
+ type
12
+ } = this.data;
8
13
  await InsertBuilder$1.create().into("identity_provider").values({
9
14
  id: providers.uuid(),
10
15
  configuration,
@@ -14,7 +19,8 @@ class CreateIdpCommand {
14
19
  exclusive,
15
20
  init_returns_config: initReturnsConfig,
16
21
  require_verified_email: requireVerifiedEmail,
17
- assume_email_verified: assumeEmailVerified
22
+ assume_email_verified: assumeEmailVerified,
23
+ disable_local_authentication: disableLocalAuthentication
18
24
  }).execute(db);
19
25
  }
20
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CreateIdpCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/CreateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { InsertBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class CreateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate data: IdentityProviderData,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tconst { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified }, slug, type } = this.data\n\t\tawait InsertBuilder.create()\n\t\t\t.into('identity_provider')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tconfiguration,\n\t\t\t\tslug,\n\t\t\t\ttype,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,MACP;AADO,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAM,EAAE,eAAe,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,oBAAA,GAAuB,MAAM,KAAA,IAAS,KAAK;AAC7I,UAAMA,gBAAc,OAAA,EAClB,KAAK,mBAAmB,EACxB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,IAAA,CACvB,EACA,QAAQ,EAAE;AAAA,EACb;AACD;"}
1
+ {"version":3,"file":"CreateIdpCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/CreateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { InsertBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class CreateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate data: IdentityProviderData,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tconst {\n\t\t\tconfiguration,\n\t\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication },\n\t\t\tslug,\n\t\t\ttype,\n\t\t} = this.data\n\t\tawait InsertBuilder.create()\n\t\t\t.into('identity_provider')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tconfiguration,\n\t\t\t\tslug,\n\t\t\t\ttype,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t\tdisable_local_authentication: disableLocalAuthentication,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,MACP;AADO,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAM;AAAA,MACL;AAAA,MACA,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,qBAAqB,2BAAA;AAAA,MAChG;AAAA,MACA;AAAA,IAAA,IACG,KAAK;AACT,UAAMA,gBAAc,OAAA,EAClB,KAAK,mBAAmB,EACxB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,8BAA8B;AAAA,IAAA,CAC9B,EACA,QAAQ,EAAE;AAAA,EACb;AACD;"}
@@ -7,14 +7,18 @@ class UpdateIdpCommand {
7
7
  this.data = data;
8
8
  }
9
9
  async execute({ db }) {
10
- const { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified } = {} } = this.data;
10
+ const {
11
+ configuration,
12
+ options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication } = {}
13
+ } = this.data;
11
14
  await Database.UpdateBuilder.create().table("identity_provider").values({
12
15
  configuration,
13
16
  auto_sign_up: autoSignUp,
14
17
  exclusive,
15
18
  init_returns_config: initReturnsConfig,
16
19
  require_verified_email: requireVerifiedEmail,
17
- assume_email_verified: assumeEmailVerified
20
+ assume_email_verified: assumeEmailVerified,
21
+ disable_local_authentication: disableLocalAuthentication
18
22
  }).where({
19
23
  id: this.id
20
24
  }).execute(db);
@@ -1 +1 @@
1
- {"version":3,"file":"UpdateIdpCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/UpdateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { UpdateBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class UpdateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate id: string,\n\t\tprivate data: UpdateIdpData,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<void> {\n\t\tconst { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified } = {} } = this.data\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('identity_provider')\n\t\t\t.values({\n\t\t\t\tconfiguration,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t})\n\t\t\t.where({\n\t\t\t\tid: this.id,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type UpdateIdpData = {\n\toptions?: Partial<IdentityProviderData['options']>\n\tconfiguration?: IdentityProviderData['configuration']\n\ttype?: string\n}\n"],"names":["UpdateBuilder"],"mappings":";;;AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,IACA,MACP;AAFO,SAAA,KAAA;AACA,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAmC;AAClD,UAAM,EAAE,eAAe,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,oBAAA,IAAwB,GAAC,IAAM,KAAK;AACtI,UAAMA,SAAAA,cAAc,OAAA,EAClB,MAAM,mBAAmB,EACzB,OAAO;AAAA,MACP;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,IAAA,CACvB,EACA,MAAM;AAAA,MACN,IAAI,KAAK;AAAA,IAAA,CACT,EACA,QAAQ,EAAE;AAAA,EACb;AACD;;"}
1
+ {"version":3,"file":"UpdateIdpCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/UpdateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { UpdateBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class UpdateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate id: string,\n\t\tprivate data: UpdateIdpData,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<void> {\n\t\tconst {\n\t\t\tconfiguration,\n\t\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication } = {},\n\t\t} = this.data\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('identity_provider')\n\t\t\t.values({\n\t\t\t\tconfiguration,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t\tdisable_local_authentication: disableLocalAuthentication,\n\t\t\t})\n\t\t\t.where({\n\t\t\t\tid: this.id,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type UpdateIdpData = {\n\toptions?: Partial<IdentityProviderData['options']>\n\tconfiguration?: IdentityProviderData['configuration']\n\ttype?: string\n}\n"],"names":["UpdateBuilder"],"mappings":";;;AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,IACA,MACP;AAFO,SAAA,KAAA;AACA,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAmC;AAClD,UAAM;AAAA,MACL;AAAA,MACA,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,qBAAqB,+BAA+B,CAAA;AAAA,IAAC,IAC7H,KAAK;AACT,UAAMA,SAAAA,cAAc,OAAA,EAClB,MAAM,mBAAmB,EACzB,OAAO;AAAA,MACP;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,8BAA8B;AAAA,IAAA,CAC9B,EACA,MAAM;AAAA,MACN,IAAI,KAAK;AAAA,IAAA,CACT,EACA,QAAQ,EAAE;AAAA,EACb;AACD;;"}
@@ -5,14 +5,18 @@ class UpdateIdpCommand {
5
5
  this.data = data;
6
6
  }
7
7
  async execute({ db }) {
8
- const { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified } = {} } = this.data;
8
+ const {
9
+ configuration,
10
+ options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication } = {}
11
+ } = this.data;
9
12
  await UpdateBuilder$1.create().table("identity_provider").values({
10
13
  configuration,
11
14
  auto_sign_up: autoSignUp,
12
15
  exclusive,
13
16
  init_returns_config: initReturnsConfig,
14
17
  require_verified_email: requireVerifiedEmail,
15
- assume_email_verified: assumeEmailVerified
18
+ assume_email_verified: assumeEmailVerified,
19
+ disable_local_authentication: disableLocalAuthentication
16
20
  }).where({
17
21
  id: this.id
18
22
  }).execute(db);
@@ -1 +1 @@
1
- {"version":3,"file":"UpdateIdpCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/UpdateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { UpdateBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class UpdateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate id: string,\n\t\tprivate data: UpdateIdpData,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<void> {\n\t\tconst { configuration, options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified } = {} } = this.data\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('identity_provider')\n\t\t\t.values({\n\t\t\t\tconfiguration,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t})\n\t\t\t.where({\n\t\t\t\tid: this.id,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type UpdateIdpData = {\n\toptions?: Partial<IdentityProviderData['options']>\n\tconfiguration?: IdentityProviderData['configuration']\n\ttype?: string\n}\n"],"names":["UpdateBuilder"],"mappings":";AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,IACA,MACP;AAFO,SAAA,KAAA;AACA,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAmC;AAClD,UAAM,EAAE,eAAe,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,oBAAA,IAAwB,GAAC,IAAM,KAAK;AACtI,UAAMA,gBAAc,OAAA,EAClB,MAAM,mBAAmB,EACzB,OAAO;AAAA,MACP;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,IAAA,CACvB,EACA,MAAM;AAAA,MACN,IAAI,KAAK;AAAA,IAAA,CACT,EACA,QAAQ,EAAE;AAAA,EACb;AACD;"}
1
+ {"version":3,"file":"UpdateIdpCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/UpdateIdpCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { UpdateBuilder } from '@contember/database'\nimport { IdentityProviderData } from '../../type/index.js'\n\nexport class UpdateIdpCommand implements Command<void> {\n\tconstructor(\n\t\tprivate id: string,\n\t\tprivate data: UpdateIdpData,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<void> {\n\t\tconst {\n\t\t\tconfiguration,\n\t\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication } = {},\n\t\t} = this.data\n\t\tawait UpdateBuilder.create()\n\t\t\t.table('identity_provider')\n\t\t\t.values({\n\t\t\t\tconfiguration,\n\t\t\t\tauto_sign_up: autoSignUp,\n\t\t\t\texclusive,\n\t\t\t\tinit_returns_config: initReturnsConfig,\n\t\t\t\trequire_verified_email: requireVerifiedEmail,\n\t\t\t\tassume_email_verified: assumeEmailVerified,\n\t\t\t\tdisable_local_authentication: disableLocalAuthentication,\n\t\t\t})\n\t\t\t.where({\n\t\t\t\tid: this.id,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nexport type UpdateIdpData = {\n\toptions?: Partial<IdentityProviderData['options']>\n\tconfiguration?: IdentityProviderData['configuration']\n\ttype?: string\n}\n"],"names":["UpdateBuilder"],"mappings":";AAIO,MAAM,iBAA0C;AAAA,EACtD,YACS,IACA,MACP;AAFO,SAAA,KAAA;AACA,SAAA,OAAA;AAAA,EAET;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAmC;AAClD,UAAM;AAAA,MACL;AAAA,MACA,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,qBAAqB,+BAA+B,CAAA;AAAA,IAAC,IAC7H,KAAK;AACT,UAAMA,gBAAc,OAAA,EAClB,MAAM,mBAAmB,EACzB,OAAO;AAAA,MACP;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,8BAA8B;AAAA,IAAA,CAC9B,EACA,MAAM;AAAA,MACN,IAAI,KAAK;AAAA,IAAA,CACT,EACA,QAAQ,EAAE;AAAA,EACb;AACD;"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const Database = require("@contember/database");
4
+ class LocalAuthDisablingIdpsQuery extends Database.DatabaseQuery {
5
+ constructor(personId) {
6
+ super();
7
+ this.personId = personId;
8
+ }
9
+ async fetch({ db }) {
10
+ const rows = await Database.SelectBuilder.create().select(["identity_provider", "slug"], "slug").from("person_identity_provider").join(
11
+ "identity_provider",
12
+ "identity_provider",
13
+ (expr) => expr.columnsEq(["identity_provider", "id"], ["person_identity_provider", "identity_provider_id"])
14
+ ).where(
15
+ (where) => where.compare(["person_identity_provider", "person_id"], Database.Operator.eq, this.personId).compare(["identity_provider", "disable_local_authentication"], Database.Operator.eq, true).isNull(["identity_provider", "disabled_at"])
16
+ ).orderBy(["identity_provider", "slug"]).getResult(db);
17
+ return rows.map((it) => it.slug);
18
+ }
19
+ }
20
+ exports.LocalAuthDisablingIdpsQuery = LocalAuthDisablingIdpsQuery;
21
+ //# sourceMappingURL=LocalAuthDisablingIdpsQuery.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalAuthDisablingIdpsQuery.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/LocalAuthDisablingIdpsQuery.ts"],"sourcesContent":["import { DatabaseQuery, DatabaseQueryable, Operator, SelectBuilder } from '@contember/database'\n\n/**\n * Slugs of the identity providers that forbid this person every local\n * authentication method — password sign-in, passwordless sign-in and the\n * password-reset mail. Empty means local authentication is available.\n *\n * The IdP link is the marker, so this also covers a person who predates the\n * provider and was linked to it by e-mail matching, not only one created by\n * auto-sign-up. A DISABLED provider does not count: turning the provider off\n * hands local authentication back to everyone linked to it, which is the\n * break-glass when the IdP is unreachable.\n */\nexport class LocalAuthDisablingIdpsQuery extends DatabaseQuery<string[]> {\n\tconstructor(\n\t\tprivate readonly personId: string,\n\t) {\n\t\tsuper()\n\t}\n\n\tasync fetch({ db }: DatabaseQueryable): Promise<string[]> {\n\t\tconst rows = await SelectBuilder.create<{ slug: string }>()\n\t\t\t.select(['identity_provider', 'slug'], 'slug')\n\t\t\t.from('person_identity_provider')\n\t\t\t.join(\n\t\t\t\t'identity_provider',\n\t\t\t\t'identity_provider',\n\t\t\t\texpr => expr.columnsEq(['identity_provider', 'id'], ['person_identity_provider', 'identity_provider_id']),\n\t\t\t)\n\t\t\t.where(where =>\n\t\t\t\twhere\n\t\t\t\t\t.compare(['person_identity_provider', 'person_id'], Operator.eq, this.personId)\n\t\t\t\t\t.compare(['identity_provider', 'disable_local_authentication'], Operator.eq, true)\n\t\t\t\t\t.isNull(['identity_provider', 'disabled_at'])\n\t\t\t)\n\t\t\t.orderBy(['identity_provider', 'slug'])\n\t\t\t.getResult(db)\n\n\t\treturn rows.map(it => it.slug)\n\t}\n}\n"],"names":["DatabaseQuery","SelectBuilder","Operator"],"mappings":";;;AAaO,MAAM,oCAAoCA,SAAAA,cAAwB;AAAA,EACxE,YACkB,UAChB;AACD,UAAA;AAFiB,SAAA,WAAA;AAAA,EAGlB;AAAA,EAEA,MAAM,MAAM,EAAE,MAA4C;AACzD,UAAM,OAAO,MAAMC,SAAAA,cAAc,OAAA,EAC/B,OAAO,CAAC,qBAAqB,MAAM,GAAG,MAAM,EAC5C,KAAK,0BAA0B,EAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAA,SAAQ,KAAK,UAAU,CAAC,qBAAqB,IAAI,GAAG,CAAC,4BAA4B,sBAAsB,CAAC;AAAA,IAAA,EAExG;AAAA,MAAM,CAAA,UACN,MACE,QAAQ,CAAC,4BAA4B,WAAW,GAAGC,SAAAA,SAAS,IAAI,KAAK,QAAQ,EAC7E,QAAQ,CAAC,qBAAqB,8BAA8B,GAAGA,kBAAS,IAAI,IAAI,EAChF,OAAO,CAAC,qBAAqB,aAAa,CAAC;AAAA,IAAA,EAE7C,QAAQ,CAAC,qBAAqB,MAAM,CAAC,EACrC,UAAU,EAAE;AAEd,WAAO,KAAK,IAAI,CAAA,OAAM,GAAG,IAAI;AAAA,EAC9B;AACD;;"}
@@ -0,0 +1,21 @@
1
+ import { DatabaseQuery, SelectBuilder, Operator } from "@contember/database";
2
+ class LocalAuthDisablingIdpsQuery extends DatabaseQuery {
3
+ constructor(personId) {
4
+ super();
5
+ this.personId = personId;
6
+ }
7
+ async fetch({ db }) {
8
+ const rows = await SelectBuilder.create().select(["identity_provider", "slug"], "slug").from("person_identity_provider").join(
9
+ "identity_provider",
10
+ "identity_provider",
11
+ (expr) => expr.columnsEq(["identity_provider", "id"], ["person_identity_provider", "identity_provider_id"])
12
+ ).where(
13
+ (where) => where.compare(["person_identity_provider", "person_id"], Operator.eq, this.personId).compare(["identity_provider", "disable_local_authentication"], Operator.eq, true).isNull(["identity_provider", "disabled_at"])
14
+ ).orderBy(["identity_provider", "slug"]).getResult(db);
15
+ return rows.map((it) => it.slug);
16
+ }
17
+ }
18
+ export {
19
+ LocalAuthDisablingIdpsQuery
20
+ };
21
+ //# sourceMappingURL=LocalAuthDisablingIdpsQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalAuthDisablingIdpsQuery.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/LocalAuthDisablingIdpsQuery.ts"],"sourcesContent":["import { DatabaseQuery, DatabaseQueryable, Operator, SelectBuilder } from '@contember/database'\n\n/**\n * Slugs of the identity providers that forbid this person every local\n * authentication method — password sign-in, passwordless sign-in and the\n * password-reset mail. Empty means local authentication is available.\n *\n * The IdP link is the marker, so this also covers a person who predates the\n * provider and was linked to it by e-mail matching, not only one created by\n * auto-sign-up. A DISABLED provider does not count: turning the provider off\n * hands local authentication back to everyone linked to it, which is the\n * break-glass when the IdP is unreachable.\n */\nexport class LocalAuthDisablingIdpsQuery extends DatabaseQuery<string[]> {\n\tconstructor(\n\t\tprivate readonly personId: string,\n\t) {\n\t\tsuper()\n\t}\n\n\tasync fetch({ db }: DatabaseQueryable): Promise<string[]> {\n\t\tconst rows = await SelectBuilder.create<{ slug: string }>()\n\t\t\t.select(['identity_provider', 'slug'], 'slug')\n\t\t\t.from('person_identity_provider')\n\t\t\t.join(\n\t\t\t\t'identity_provider',\n\t\t\t\t'identity_provider',\n\t\t\t\texpr => expr.columnsEq(['identity_provider', 'id'], ['person_identity_provider', 'identity_provider_id']),\n\t\t\t)\n\t\t\t.where(where =>\n\t\t\t\twhere\n\t\t\t\t\t.compare(['person_identity_provider', 'person_id'], Operator.eq, this.personId)\n\t\t\t\t\t.compare(['identity_provider', 'disable_local_authentication'], Operator.eq, true)\n\t\t\t\t\t.isNull(['identity_provider', 'disabled_at'])\n\t\t\t)\n\t\t\t.orderBy(['identity_provider', 'slug'])\n\t\t\t.getResult(db)\n\n\t\treturn rows.map(it => it.slug)\n\t}\n}\n"],"names":[],"mappings":";AAaO,MAAM,oCAAoC,cAAwB;AAAA,EACxE,YACkB,UAChB;AACD,UAAA;AAFiB,SAAA,WAAA;AAAA,EAGlB;AAAA,EAEA,MAAM,MAAM,EAAE,MAA4C;AACzD,UAAM,OAAO,MAAM,cAAc,OAAA,EAC/B,OAAO,CAAC,qBAAqB,MAAM,GAAG,MAAM,EAC5C,KAAK,0BAA0B,EAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAA,SAAQ,KAAK,UAAU,CAAC,qBAAqB,IAAI,GAAG,CAAC,4BAA4B,sBAAsB,CAAC;AAAA,IAAA,EAExG;AAAA,MAAM,CAAA,UACN,MACE,QAAQ,CAAC,4BAA4B,WAAW,GAAG,SAAS,IAAI,KAAK,QAAQ,EAC7E,QAAQ,CAAC,qBAAqB,8BAA8B,GAAG,SAAS,IAAI,IAAI,EAChF,OAAO,CAAC,qBAAqB,aAAa,CAAC;AAAA,IAAA,EAE7C,QAAQ,CAAC,qBAAqB,MAAM,CAAC,EACrC,UAAU,EAAE;AAEd,WAAO,KAAK,IAAI,CAAA,OAAM,GAAG,IAAI;AAAA,EAC9B;AACD;"}
@@ -7,7 +7,7 @@ class PersonIdentityProvidersQuery extends Database.DatabaseQuery {
7
7
  this.personId = personId;
8
8
  }
9
9
  async fetch({ db }) {
10
- return await Database.SelectBuilder.create().select(["person_identity_provider", "id"]).select(["person_identity_provider", "created_at"], "createdAt").select(["person_identity_provider", "external_identifier"], "externalIdentifier").select(["identity_provider", "slug"], "identityProviderSlug").select(["identity_provider", "type"], "identityProviderType").select(["identity_provider", "disabled_at"], "identityProviderDisabledAt").from("person_identity_provider").join(
10
+ return await Database.SelectBuilder.create().select(["person_identity_provider", "id"]).select(["person_identity_provider", "created_at"], "createdAt").select(["person_identity_provider", "external_identifier"], "externalIdentifier").select(["identity_provider", "slug"], "identityProviderSlug").select(["identity_provider", "type"], "identityProviderType").select(["identity_provider", "disabled_at"], "identityProviderDisabledAt").select(["identity_provider", "disable_local_authentication"], "identityProviderDisableLocalAuthentication").from("person_identity_provider").join(
11
11
  "identity_provider",
12
12
  "identity_provider",
13
13
  (expr) => expr.columnsEq(["identity_provider", "id"], ["person_identity_provider", "identity_provider_id"])
@@ -1 +1 @@
1
- {"version":3,"file":"PersonIdentityProvidersQuery.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/PersonIdentityProvidersQuery.ts"],"sourcesContent":["import { DatabaseQuery, DatabaseQueryable, SelectBuilder } from '@contember/database'\n\nexport interface PersonIdentityProviderRow {\n\treadonly id: string\n\treadonly createdAt: Date\n\treadonly externalIdentifier: string\n\treadonly identityProviderSlug: string\n\treadonly identityProviderType: string\n\treadonly identityProviderDisabledAt: Date | null\n}\n\n/**\n * Lists the external IdP connections of a single person, joined with the\n * identity provider they belong to. Used by the `Person.identityProviders`\n * field and by the disconnect flow to enforce ownership and lock-out protection.\n */\nexport class PersonIdentityProvidersQuery extends DatabaseQuery<PersonIdentityProviderRow[]> {\n\tconstructor(\n\t\tprivate readonly personId: string,\n\t) {\n\t\tsuper()\n\t}\n\n\tasync fetch({ db }: DatabaseQueryable): Promise<PersonIdentityProviderRow[]> {\n\t\treturn await SelectBuilder.create<PersonIdentityProviderRow>()\n\t\t\t.select(['person_identity_provider', 'id'])\n\t\t\t.select(['person_identity_provider', 'created_at'], 'createdAt')\n\t\t\t.select(['person_identity_provider', 'external_identifier'], 'externalIdentifier')\n\t\t\t.select(['identity_provider', 'slug'], 'identityProviderSlug')\n\t\t\t.select(['identity_provider', 'type'], 'identityProviderType')\n\t\t\t.select(['identity_provider', 'disabled_at'], 'identityProviderDisabledAt')\n\t\t\t.from('person_identity_provider')\n\t\t\t.join(\n\t\t\t\t'identity_provider',\n\t\t\t\t'identity_provider',\n\t\t\t\texpr => expr.columnsEq(['identity_provider', 'id'], ['person_identity_provider', 'identity_provider_id']),\n\t\t\t)\n\t\t\t.where({ person_id: this.personId })\n\t\t\t.orderBy(['person_identity_provider', 'created_at'])\n\t\t\t.orderBy(['person_identity_provider', 'id'])\n\t\t\t.getResult(db)\n\t}\n}\n"],"names":["DatabaseQuery","SelectBuilder"],"mappings":";;;AAgBO,MAAM,qCAAqCA,SAAAA,cAA2C;AAAA,EAC5F,YACkB,UAChB;AACD,UAAA;AAFiB,SAAA,WAAA;AAAA,EAGlB;AAAA,EAEA,MAAM,MAAM,EAAE,MAA+D;AAC5E,WAAO,MAAMC,SAAAA,cAAc,SACzB,OAAO,CAAC,4BAA4B,IAAI,CAAC,EACzC,OAAO,CAAC,4BAA4B,YAAY,GAAG,WAAW,EAC9D,OAAO,CAAC,4BAA4B,qBAAqB,GAAG,oBAAoB,EAChF,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,aAAa,GAAG,4BAA4B,EACzE,KAAK,0BAA0B,EAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAA,SAAQ,KAAK,UAAU,CAAC,qBAAqB,IAAI,GAAG,CAAC,4BAA4B,sBAAsB,CAAC;AAAA,IAAA,EAExG,MAAM,EAAE,WAAW,KAAK,SAAA,CAAU,EAClC,QAAQ,CAAC,4BAA4B,YAAY,CAAC,EAClD,QAAQ,CAAC,4BAA4B,IAAI,CAAC,EAC1C,UAAU,EAAE;AAAA,EACf;AACD;;"}
1
+ {"version":3,"file":"PersonIdentityProvidersQuery.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/PersonIdentityProvidersQuery.ts"],"sourcesContent":["import { DatabaseQuery, DatabaseQueryable, SelectBuilder } from '@contember/database'\n\nexport interface PersonIdentityProviderRow {\n\treadonly id: string\n\treadonly createdAt: Date\n\treadonly externalIdentifier: string\n\treadonly identityProviderSlug: string\n\treadonly identityProviderType: string\n\treadonly identityProviderDisabledAt: Date | null\n\treadonly identityProviderDisableLocalAuthentication: boolean\n}\n\n/**\n * Lists the external IdP connections of a single person, joined with the\n * identity provider they belong to. Used by the `Person.identityProviders`\n * field and by the disconnect flow to enforce ownership and lock-out protection.\n */\nexport class PersonIdentityProvidersQuery extends DatabaseQuery<PersonIdentityProviderRow[]> {\n\tconstructor(\n\t\tprivate readonly personId: string,\n\t) {\n\t\tsuper()\n\t}\n\n\tasync fetch({ db }: DatabaseQueryable): Promise<PersonIdentityProviderRow[]> {\n\t\treturn await SelectBuilder.create<PersonIdentityProviderRow>()\n\t\t\t.select(['person_identity_provider', 'id'])\n\t\t\t.select(['person_identity_provider', 'created_at'], 'createdAt')\n\t\t\t.select(['person_identity_provider', 'external_identifier'], 'externalIdentifier')\n\t\t\t.select(['identity_provider', 'slug'], 'identityProviderSlug')\n\t\t\t.select(['identity_provider', 'type'], 'identityProviderType')\n\t\t\t.select(['identity_provider', 'disabled_at'], 'identityProviderDisabledAt')\n\t\t\t.select(['identity_provider', 'disable_local_authentication'], 'identityProviderDisableLocalAuthentication')\n\t\t\t.from('person_identity_provider')\n\t\t\t.join(\n\t\t\t\t'identity_provider',\n\t\t\t\t'identity_provider',\n\t\t\t\texpr => expr.columnsEq(['identity_provider', 'id'], ['person_identity_provider', 'identity_provider_id']),\n\t\t\t)\n\t\t\t.where({ person_id: this.personId })\n\t\t\t.orderBy(['person_identity_provider', 'created_at'])\n\t\t\t.orderBy(['person_identity_provider', 'id'])\n\t\t\t.getResult(db)\n\t}\n}\n"],"names":["DatabaseQuery","SelectBuilder"],"mappings":";;;AAiBO,MAAM,qCAAqCA,SAAAA,cAA2C;AAAA,EAC5F,YACkB,UAChB;AACD,UAAA;AAFiB,SAAA,WAAA;AAAA,EAGlB;AAAA,EAEA,MAAM,MAAM,EAAE,MAA+D;AAC5E,WAAO,MAAMC,SAAAA,cAAc,OAAA,EACzB,OAAO,CAAC,4BAA4B,IAAI,CAAC,EACzC,OAAO,CAAC,4BAA4B,YAAY,GAAG,WAAW,EAC9D,OAAO,CAAC,4BAA4B,qBAAqB,GAAG,oBAAoB,EAChF,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,aAAa,GAAG,4BAA4B,EACzE,OAAO,CAAC,qBAAqB,8BAA8B,GAAG,4CAA4C,EAC1G,KAAK,0BAA0B,EAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAA,SAAQ,KAAK,UAAU,CAAC,qBAAqB,IAAI,GAAG,CAAC,4BAA4B,sBAAsB,CAAC;AAAA,IAAA,EAExG,MAAM,EAAE,WAAW,KAAK,SAAA,CAAU,EAClC,QAAQ,CAAC,4BAA4B,YAAY,CAAC,EAClD,QAAQ,CAAC,4BAA4B,IAAI,CAAC,EAC1C,UAAU,EAAE;AAAA,EACf;AACD;;"}
@@ -5,7 +5,7 @@ class PersonIdentityProvidersQuery extends DatabaseQuery {
5
5
  this.personId = personId;
6
6
  }
7
7
  async fetch({ db }) {
8
- return await SelectBuilder.create().select(["person_identity_provider", "id"]).select(["person_identity_provider", "created_at"], "createdAt").select(["person_identity_provider", "external_identifier"], "externalIdentifier").select(["identity_provider", "slug"], "identityProviderSlug").select(["identity_provider", "type"], "identityProviderType").select(["identity_provider", "disabled_at"], "identityProviderDisabledAt").from("person_identity_provider").join(
8
+ return await SelectBuilder.create().select(["person_identity_provider", "id"]).select(["person_identity_provider", "created_at"], "createdAt").select(["person_identity_provider", "external_identifier"], "externalIdentifier").select(["identity_provider", "slug"], "identityProviderSlug").select(["identity_provider", "type"], "identityProviderType").select(["identity_provider", "disabled_at"], "identityProviderDisabledAt").select(["identity_provider", "disable_local_authentication"], "identityProviderDisableLocalAuthentication").from("person_identity_provider").join(
9
9
  "identity_provider",
10
10
  "identity_provider",
11
11
  (expr) => expr.columnsEq(["identity_provider", "id"], ["person_identity_provider", "identity_provider_id"])
@@ -1 +1 @@
1
- {"version":3,"file":"PersonIdentityProvidersQuery.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/PersonIdentityProvidersQuery.ts"],"sourcesContent":["import { DatabaseQuery, DatabaseQueryable, SelectBuilder } from '@contember/database'\n\nexport interface PersonIdentityProviderRow {\n\treadonly id: string\n\treadonly createdAt: Date\n\treadonly externalIdentifier: string\n\treadonly identityProviderSlug: string\n\treadonly identityProviderType: string\n\treadonly identityProviderDisabledAt: Date | null\n}\n\n/**\n * Lists the external IdP connections of a single person, joined with the\n * identity provider they belong to. Used by the `Person.identityProviders`\n * field and by the disconnect flow to enforce ownership and lock-out protection.\n */\nexport class PersonIdentityProvidersQuery extends DatabaseQuery<PersonIdentityProviderRow[]> {\n\tconstructor(\n\t\tprivate readonly personId: string,\n\t) {\n\t\tsuper()\n\t}\n\n\tasync fetch({ db }: DatabaseQueryable): Promise<PersonIdentityProviderRow[]> {\n\t\treturn await SelectBuilder.create<PersonIdentityProviderRow>()\n\t\t\t.select(['person_identity_provider', 'id'])\n\t\t\t.select(['person_identity_provider', 'created_at'], 'createdAt')\n\t\t\t.select(['person_identity_provider', 'external_identifier'], 'externalIdentifier')\n\t\t\t.select(['identity_provider', 'slug'], 'identityProviderSlug')\n\t\t\t.select(['identity_provider', 'type'], 'identityProviderType')\n\t\t\t.select(['identity_provider', 'disabled_at'], 'identityProviderDisabledAt')\n\t\t\t.from('person_identity_provider')\n\t\t\t.join(\n\t\t\t\t'identity_provider',\n\t\t\t\t'identity_provider',\n\t\t\t\texpr => expr.columnsEq(['identity_provider', 'id'], ['person_identity_provider', 'identity_provider_id']),\n\t\t\t)\n\t\t\t.where({ person_id: this.personId })\n\t\t\t.orderBy(['person_identity_provider', 'created_at'])\n\t\t\t.orderBy(['person_identity_provider', 'id'])\n\t\t\t.getResult(db)\n\t}\n}\n"],"names":[],"mappings":";AAgBO,MAAM,qCAAqC,cAA2C;AAAA,EAC5F,YACkB,UAChB;AACD,UAAA;AAFiB,SAAA,WAAA;AAAA,EAGlB;AAAA,EAEA,MAAM,MAAM,EAAE,MAA+D;AAC5E,WAAO,MAAM,cAAc,SACzB,OAAO,CAAC,4BAA4B,IAAI,CAAC,EACzC,OAAO,CAAC,4BAA4B,YAAY,GAAG,WAAW,EAC9D,OAAO,CAAC,4BAA4B,qBAAqB,GAAG,oBAAoB,EAChF,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,aAAa,GAAG,4BAA4B,EACzE,KAAK,0BAA0B,EAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAA,SAAQ,KAAK,UAAU,CAAC,qBAAqB,IAAI,GAAG,CAAC,4BAA4B,sBAAsB,CAAC;AAAA,IAAA,EAExG,MAAM,EAAE,WAAW,KAAK,SAAA,CAAU,EAClC,QAAQ,CAAC,4BAA4B,YAAY,CAAC,EAClD,QAAQ,CAAC,4BAA4B,IAAI,CAAC,EAC1C,UAAU,EAAE;AAAA,EACf;AACD;"}
1
+ {"version":3,"file":"PersonIdentityProvidersQuery.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/PersonIdentityProvidersQuery.ts"],"sourcesContent":["import { DatabaseQuery, DatabaseQueryable, SelectBuilder } from '@contember/database'\n\nexport interface PersonIdentityProviderRow {\n\treadonly id: string\n\treadonly createdAt: Date\n\treadonly externalIdentifier: string\n\treadonly identityProviderSlug: string\n\treadonly identityProviderType: string\n\treadonly identityProviderDisabledAt: Date | null\n\treadonly identityProviderDisableLocalAuthentication: boolean\n}\n\n/**\n * Lists the external IdP connections of a single person, joined with the\n * identity provider they belong to. Used by the `Person.identityProviders`\n * field and by the disconnect flow to enforce ownership and lock-out protection.\n */\nexport class PersonIdentityProvidersQuery extends DatabaseQuery<PersonIdentityProviderRow[]> {\n\tconstructor(\n\t\tprivate readonly personId: string,\n\t) {\n\t\tsuper()\n\t}\n\n\tasync fetch({ db }: DatabaseQueryable): Promise<PersonIdentityProviderRow[]> {\n\t\treturn await SelectBuilder.create<PersonIdentityProviderRow>()\n\t\t\t.select(['person_identity_provider', 'id'])\n\t\t\t.select(['person_identity_provider', 'created_at'], 'createdAt')\n\t\t\t.select(['person_identity_provider', 'external_identifier'], 'externalIdentifier')\n\t\t\t.select(['identity_provider', 'slug'], 'identityProviderSlug')\n\t\t\t.select(['identity_provider', 'type'], 'identityProviderType')\n\t\t\t.select(['identity_provider', 'disabled_at'], 'identityProviderDisabledAt')\n\t\t\t.select(['identity_provider', 'disable_local_authentication'], 'identityProviderDisableLocalAuthentication')\n\t\t\t.from('person_identity_provider')\n\t\t\t.join(\n\t\t\t\t'identity_provider',\n\t\t\t\t'identity_provider',\n\t\t\t\texpr => expr.columnsEq(['identity_provider', 'id'], ['person_identity_provider', 'identity_provider_id']),\n\t\t\t)\n\t\t\t.where({ person_id: this.personId })\n\t\t\t.orderBy(['person_identity_provider', 'created_at'])\n\t\t\t.orderBy(['person_identity_provider', 'id'])\n\t\t\t.getResult(db)\n\t}\n}\n"],"names":[],"mappings":";AAiBO,MAAM,qCAAqC,cAA2C;AAAA,EAC5F,YACkB,UAChB;AACD,UAAA;AAFiB,SAAA,WAAA;AAAA,EAGlB;AAAA,EAEA,MAAM,MAAM,EAAE,MAA+D;AAC5E,WAAO,MAAM,cAAc,OAAA,EACzB,OAAO,CAAC,4BAA4B,IAAI,CAAC,EACzC,OAAO,CAAC,4BAA4B,YAAY,GAAG,WAAW,EAC9D,OAAO,CAAC,4BAA4B,qBAAqB,GAAG,oBAAoB,EAChF,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,MAAM,GAAG,sBAAsB,EAC5D,OAAO,CAAC,qBAAqB,aAAa,GAAG,4BAA4B,EACzE,OAAO,CAAC,qBAAqB,8BAA8B,GAAG,4CAA4C,EAC1G,KAAK,0BAA0B,EAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAA,SAAQ,KAAK,UAAU,CAAC,qBAAqB,IAAI,GAAG,CAAC,4BAA4B,sBAAsB,CAAC;AAAA,IAAA,EAExG,MAAM,EAAE,WAAW,KAAK,SAAA,CAAU,EAClC,QAAQ,CAAC,4BAA4B,YAAY,CAAC,EAClD,QAAQ,CAAC,4BAA4B,IAAI,CAAC,EAC1C,UAAU,EAAE;AAAA,EACf;AACD;"}
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const Database = require("@contember/database");
4
- const createBaseIdpQuery = () => Database.SelectBuilder.create().select("id").select("slug").select("type").select("configuration").select("disabled_at", "disabledAt").select("auto_sign_up", "autoSignUp").select("exclusive").select("init_returns_config", "initReturnsConfig").select("require_verified_email", "requireVerifiedEmail").select("assume_email_verified", "assumeEmailVerified").from("identity_provider");
5
- const createIdpDto = ({ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, ...row }) => {
4
+ const createBaseIdpQuery = () => Database.SelectBuilder.create().select("id").select("slug").select("type").select("configuration").select("disabled_at", "disabledAt").select("auto_sign_up", "autoSignUp").select("exclusive").select("init_returns_config", "initReturnsConfig").select("require_verified_email", "requireVerifiedEmail").select("assume_email_verified", "assumeEmailVerified").select("disable_local_authentication", "disableLocalAuthentication").from("identity_provider");
5
+ const createIdpDto = ({ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication, ...row }) => {
6
6
  return {
7
7
  ...row,
8
- options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified }
8
+ options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication }
9
9
  };
10
10
  };
11
11
  exports.createBaseIdpQuery = createBaseIdpQuery;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/helpers.ts"],"sourcesContent":["import { SelectBuilder } from '@contember/database'\nimport { IdentityProviderDto, IdentityProviderRow } from './types.js'\n\nexport const createBaseIdpQuery = () =>\n\tSelectBuilder.create<IdentityProviderRow>()\n\t\t.select('id')\n\t\t.select('slug')\n\t\t.select('type')\n\t\t.select('configuration')\n\t\t.select('disabled_at', 'disabledAt')\n\t\t.select('auto_sign_up', 'autoSignUp')\n\t\t.select('exclusive')\n\t\t.select('init_returns_config', 'initReturnsConfig')\n\t\t.select('require_verified_email', 'requireVerifiedEmail')\n\t\t.select('assume_email_verified', 'assumeEmailVerified')\n\t\t.from('identity_provider')\n\nexport const createIdpDto = (\n\t{ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, ...row }: IdentityProviderRow,\n): IdentityProviderDto => {\n\treturn {\n\t\t...row,\n\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified },\n\t}\n}\n"],"names":["SelectBuilder"],"mappings":";;;AAGO,MAAM,qBAAqB,MACjCA,SAAAA,cAAc,SACZ,OAAO,IAAI,EACX,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,eAAe,EACtB,OAAO,eAAe,YAAY,EAClC,OAAO,gBAAgB,YAAY,EACnC,OAAO,WAAW,EAClB,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,0BAA0B,sBAAsB,EACvD,OAAO,yBAAyB,qBAAqB,EACrD,KAAK,mBAAmB;AAEpB,MAAM,eAAe,CAC3B,EAAE,WAAW,YAAY,mBAAmB,sBAAsB,qBAAqB,GAAG,UACjE;AACzB,SAAO;AAAA,IACN,GAAG;AAAA,IACH,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,oBAAA;AAAA,EAAoB;AAEjG;;;"}
1
+ {"version":3,"file":"helpers.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/helpers.ts"],"sourcesContent":["import { SelectBuilder } from '@contember/database'\nimport { IdentityProviderDto, IdentityProviderRow } from './types.js'\n\nexport const createBaseIdpQuery = () =>\n\tSelectBuilder.create<IdentityProviderRow>()\n\t\t.select('id')\n\t\t.select('slug')\n\t\t.select('type')\n\t\t.select('configuration')\n\t\t.select('disabled_at', 'disabledAt')\n\t\t.select('auto_sign_up', 'autoSignUp')\n\t\t.select('exclusive')\n\t\t.select('init_returns_config', 'initReturnsConfig')\n\t\t.select('require_verified_email', 'requireVerifiedEmail')\n\t\t.select('assume_email_verified', 'assumeEmailVerified')\n\t\t.select('disable_local_authentication', 'disableLocalAuthentication')\n\t\t.from('identity_provider')\n\nexport const createIdpDto = (\n\t{ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication, ...row }: IdentityProviderRow,\n): IdentityProviderDto => {\n\treturn {\n\t\t...row,\n\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication },\n\t}\n}\n"],"names":["SelectBuilder"],"mappings":";;;AAGO,MAAM,qBAAqB,MACjCA,SAAAA,cAAc,OAAA,EACZ,OAAO,IAAI,EACX,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,eAAe,EACtB,OAAO,eAAe,YAAY,EAClC,OAAO,gBAAgB,YAAY,EACnC,OAAO,WAAW,EAClB,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,0BAA0B,sBAAsB,EACvD,OAAO,yBAAyB,qBAAqB,EACrD,OAAO,gCAAgC,4BAA4B,EACnE,KAAK,mBAAmB;AAEpB,MAAM,eAAe,CAC3B,EAAE,WAAW,YAAY,mBAAmB,sBAAsB,qBAAqB,4BAA4B,GAAG,UAC7F;AACzB,SAAO;AAAA,IACN,GAAG;AAAA,IACH,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,qBAAqB,2BAAA;AAAA,EAA2B;AAE7H;;;"}
@@ -1,9 +1,9 @@
1
1
  import { SelectBuilder } from "@contember/database";
2
- const createBaseIdpQuery = () => SelectBuilder.create().select("id").select("slug").select("type").select("configuration").select("disabled_at", "disabledAt").select("auto_sign_up", "autoSignUp").select("exclusive").select("init_returns_config", "initReturnsConfig").select("require_verified_email", "requireVerifiedEmail").select("assume_email_verified", "assumeEmailVerified").from("identity_provider");
3
- const createIdpDto = ({ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, ...row }) => {
2
+ const createBaseIdpQuery = () => SelectBuilder.create().select("id").select("slug").select("type").select("configuration").select("disabled_at", "disabledAt").select("auto_sign_up", "autoSignUp").select("exclusive").select("init_returns_config", "initReturnsConfig").select("require_verified_email", "requireVerifiedEmail").select("assume_email_verified", "assumeEmailVerified").select("disable_local_authentication", "disableLocalAuthentication").from("identity_provider");
3
+ const createIdpDto = ({ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication, ...row }) => {
4
4
  return {
5
5
  ...row,
6
- options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified }
6
+ options: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication }
7
7
  };
8
8
  };
9
9
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/helpers.ts"],"sourcesContent":["import { SelectBuilder } from '@contember/database'\nimport { IdentityProviderDto, IdentityProviderRow } from './types.js'\n\nexport const createBaseIdpQuery = () =>\n\tSelectBuilder.create<IdentityProviderRow>()\n\t\t.select('id')\n\t\t.select('slug')\n\t\t.select('type')\n\t\t.select('configuration')\n\t\t.select('disabled_at', 'disabledAt')\n\t\t.select('auto_sign_up', 'autoSignUp')\n\t\t.select('exclusive')\n\t\t.select('init_returns_config', 'initReturnsConfig')\n\t\t.select('require_verified_email', 'requireVerifiedEmail')\n\t\t.select('assume_email_verified', 'assumeEmailVerified')\n\t\t.from('identity_provider')\n\nexport const createIdpDto = (\n\t{ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, ...row }: IdentityProviderRow,\n): IdentityProviderDto => {\n\treturn {\n\t\t...row,\n\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified },\n\t}\n}\n"],"names":[],"mappings":";AAGO,MAAM,qBAAqB,MACjC,cAAc,SACZ,OAAO,IAAI,EACX,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,eAAe,EACtB,OAAO,eAAe,YAAY,EAClC,OAAO,gBAAgB,YAAY,EACnC,OAAO,WAAW,EAClB,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,0BAA0B,sBAAsB,EACvD,OAAO,yBAAyB,qBAAqB,EACrD,KAAK,mBAAmB;AAEpB,MAAM,eAAe,CAC3B,EAAE,WAAW,YAAY,mBAAmB,sBAAsB,qBAAqB,GAAG,UACjE;AACzB,SAAO;AAAA,IACN,GAAG;AAAA,IACH,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,oBAAA;AAAA,EAAoB;AAEjG;"}
1
+ {"version":3,"file":"helpers.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/queries/idp/helpers.ts"],"sourcesContent":["import { SelectBuilder } from '@contember/database'\nimport { IdentityProviderDto, IdentityProviderRow } from './types.js'\n\nexport const createBaseIdpQuery = () =>\n\tSelectBuilder.create<IdentityProviderRow>()\n\t\t.select('id')\n\t\t.select('slug')\n\t\t.select('type')\n\t\t.select('configuration')\n\t\t.select('disabled_at', 'disabledAt')\n\t\t.select('auto_sign_up', 'autoSignUp')\n\t\t.select('exclusive')\n\t\t.select('init_returns_config', 'initReturnsConfig')\n\t\t.select('require_verified_email', 'requireVerifiedEmail')\n\t\t.select('assume_email_verified', 'assumeEmailVerified')\n\t\t.select('disable_local_authentication', 'disableLocalAuthentication')\n\t\t.from('identity_provider')\n\nexport const createIdpDto = (\n\t{ exclusive, autoSignUp, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication, ...row }: IdentityProviderRow,\n): IdentityProviderDto => {\n\treturn {\n\t\t...row,\n\t\toptions: { autoSignUp, exclusive, initReturnsConfig, requireVerifiedEmail, assumeEmailVerified, disableLocalAuthentication },\n\t}\n}\n"],"names":[],"mappings":";AAGO,MAAM,qBAAqB,MACjC,cAAc,OAAA,EACZ,OAAO,IAAI,EACX,OAAO,MAAM,EACb,OAAO,MAAM,EACb,OAAO,eAAe,EACtB,OAAO,eAAe,YAAY,EAClC,OAAO,gBAAgB,YAAY,EACnC,OAAO,WAAW,EAClB,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,0BAA0B,sBAAsB,EACvD,OAAO,yBAAyB,qBAAqB,EACrD,OAAO,gCAAgC,4BAA4B,EACnE,KAAK,mBAAmB;AAEpB,MAAM,eAAe,CAC3B,EAAE,WAAW,YAAY,mBAAmB,sBAAsB,qBAAqB,4BAA4B,GAAG,UAC7F;AACzB,SAAO;AAAA,IACN,GAAG;AAAA,IACH,SAAS,EAAE,YAAY,WAAW,mBAAmB,sBAAsB,qBAAqB,2BAAA;AAAA,EAA2B;AAE7H;"}
@@ -6,6 +6,7 @@ require("@contember/database");
6
6
  require("../type/ApiKey.cjs");
7
7
  const ConfigurationQuery = require("../queries/configuration/ConfigurationQuery.cjs");
8
8
  const exceptions = require("../../exceptions.cjs");
9
+ const LocalAuthDisablingIdpsQuery = require("../queries/idp/LocalAuthDisablingIdpsQuery.cjs");
9
10
  require("../authorization/PermissionActions.cjs");
10
11
  require("@contember/authorization");
11
12
  require("../authorization/PermissionContext.cjs");
@@ -28,6 +29,10 @@ class PasswordResetManager {
28
29
  if (!person.email) {
29
30
  throw new exceptions.ImplementationException();
30
31
  }
32
+ const exclusiveIdps = await dbContext.queryHandler.fetch(new LocalAuthDisablingIdpsQuery.LocalAuthDisablingIdpsQuery(person.id));
33
+ if (exclusiveIdps.length > 0) {
34
+ return;
35
+ }
31
36
  const nextAllowed = await dbContext.queryHandler.fetch(
32
37
  new NextMailAttemptQuery.NextMailAttemptQuery(person.email, "password_reset_init", "password_reset")
33
38
  );
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordResetManager.cjs","sources":["../../../../../../packages/engine-tenant-api/src/model/service/PasswordResetManager.ts"],"sourcesContent":["import { Response, ResponseError, ResponseOk } from '../utils/Response.js'\nimport { UserMailer } from '../mailing/index.js'\nimport { ConfigurationQuery, PersonRow } from '../queries/index.js'\nimport { PermissionContext } from '../authorization/index.js'\nimport { ProjectManager } from './ProjectManager.js'\nimport { DatabaseContext } from '../utils/index.js'\nimport { ImplementationException } from '../../exceptions.js'\nimport { getPreferredProject } from './helpers/getPreferredProject.js'\nimport { CreatePersonTokenCommand, ResetPasswordCommand } from '../commands/personToken/index.js'\nimport { PasswordStrengthValidator } from './PasswordStrengthValidator.js'\nimport { ResetPasswordErrorCode, WeakPasswordReason } from '../../schema/index.js'\nimport { PersonTokenQuery } from '../queries/personToken/PersonTokenQuery.js'\nimport { AuthLogService } from './AuthLogService.js'\nimport { NextMailAttemptQuery } from '../queries/authLog/NextMailAttemptQuery.js'\n\ninterface MailOptions {\n\tproject?: string\n\tmailVariant?: string\n}\n\nexport class PasswordResetManager {\n\tconstructor(\n\t\tprivate readonly mailer: UserMailer,\n\t\tprivate readonly projectManager: ProjectManager,\n\t\tprivate readonly passwordStrengthValidator: PasswordStrengthValidator,\n\t) {}\n\n\tpublic async createPasswordResetRequest(\n\t\tdbContext: DatabaseContext,\n\t\tpermissionContext: PermissionContext,\n\t\tperson: PersonRow,\n\t\tmailOptions: MailOptions = {},\n\t): Promise<void> {\n\t\tif (!person.email) {\n\t\t\tthrow new ImplementationException()\n\t\t}\n\n\t\t// Per-email exponential backoff on outbound mails — don't spam a real\n\t\t// user with reset mails just because attackers keep poking the\n\t\t// endpoint. Reuses login_* backoff config against person_auth_log.\n\t\tconst nextAllowed = await dbContext.queryHandler.fetch(\n\t\t\tnew NextMailAttemptQuery(person.email, 'password_reset_init', 'password_reset'),\n\t\t)\n\t\tif (nextAllowed > new Date()) {\n\t\t\treturn\n\t\t}\n\n\t\tconst result = await dbContext.commandBus.execute(CreatePersonTokenCommand.createPasswordResetRequest(person.id))\n\t\tconst projects = await this.projectManager.getProjectsByIdentity(dbContext, person.identity_id, permissionContext)\n\t\tconst project = getPreferredProject(projects, mailOptions.project ?? null)\n\n\t\tawait this.mailer.sendPasswordResetEmail(\n\t\t\tdbContext,\n\t\t\t{\n\t\t\t\temail: person.email,\n\t\t\t\ttoken: result.token,\n\t\t\t\tproject: project?.name,\n\t\t\t\tprojectSlug: project?.slug,\n\t\t\t},\n\t\t\t{\n\t\t\t\tvariant: mailOptions.mailVariant || '',\n\t\t\t\tprojectId: project?.id ?? null,\n\t\t\t},\n\t\t)\n\t}\n\n\tpublic async resetPassword(dbContext: DatabaseContext, token: string, password: string): Promise<ResetPasswordResponse> {\n\t\tconst config = await dbContext.queryHandler.fetch(new ConfigurationQuery(dbContext.providers))\n\t\tconst tokenRow = await dbContext.queryHandler.fetch(PersonTokenQuery.byToken(token, 'password_reset'))\n\t\tif (!tokenRow) {\n\t\t\treturn new ResponseError('TOKEN_NOT_FOUND', 'Token not found', {\n\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({}),\n\t\t\t})\n\t\t}\n\n\t\tconst authLogData = new AuthLogService.Bag({\n\t\t\tpersonId: tokenRow.person_id,\n\t\t\ttokenId: tokenRow.id,\n\t\t})\n\t\tconst weakPassword = await this.passwordStrengthValidator.verify(password, config.password, 'PASSWORD_TOO_WEAK')\n\t\tif (!weakPassword.ok) {\n\t\t\treturn new ResponseError(weakPassword.error, weakPassword.errorMessage, {\n\t\t\t\t...weakPassword.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\tconst resetPasswordResult = await dbContext.commandBus.execute(new ResetPasswordCommand(token, password))\n\t\tif (!resetPasswordResult.ok) {\n\t\t\treturn new ResponseError(resetPasswordResult.error, resetPasswordResult.errorMessage, {\n\t\t\t\t...resetPasswordResult.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\treturn new ResponseOk({\n\t\t\t[AuthLogService.Key]: authLogData,\n\t\t})\n\t}\n}\n\nexport type ResetPasswordResponse = Response<\n\t{\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t},\n\tResetPasswordErrorCode,\n\t{\n\t\tweakPasswordReasons?: WeakPasswordReason[]\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}\n>\n"],"names":["ImplementationException","NextMailAttemptQuery","CreatePersonTokenCommand","getPreferredProject","ConfigurationQuery","PersonTokenQuery","ResponseError","AuthLogService","ResetPasswordCommand","ResponseOk"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBO,MAAM,qBAAqB;AAAA,EACjC,YACkB,QACA,gBACA,2BAChB;AAHgB,SAAA,SAAA;AACA,SAAA,iBAAA;AACA,SAAA,4BAAA;AAAA,EACf;AAAA,EAEH,MAAa,2BACZ,WACA,mBACA,QACA,cAA2B,CAAA,GACX;AAChB,QAAI,CAAC,OAAO,OAAO;AAClB,YAAM,IAAIA,WAAAA,wBAAA;AAAA,IACX;AAKA,UAAM,cAAc,MAAM,UAAU,aAAa;AAAA,MAChD,IAAIC,0CAAqB,OAAO,OAAO,uBAAuB,gBAAgB;AAAA,IAAA;AAE/E,QAAI,cAAc,oBAAI,QAAQ;AAC7B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM,UAAU,WAAW,QAAQC,yBAAAA,yBAAyB,2BAA2B,OAAO,EAAE,CAAC;AAChH,UAAM,WAAW,MAAM,KAAK,eAAe,sBAAsB,WAAW,OAAO,aAAa,iBAAiB;AACjH,UAAM,UAAUC,oBAAAA,oBAAoB,UAAU,YAAY,WAAW,IAAI;AAEzE,UAAM,KAAK,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,QACC,OAAO,OAAO;AAAA,QACd,OAAO,OAAO;AAAA,QACd,SAAS,SAAS;AAAA,QAClB,aAAa,SAAS;AAAA,MAAA;AAAA,MAEvB;AAAA,QACC,SAAS,YAAY,eAAe;AAAA,QACpC,WAAW,SAAS,MAAM;AAAA,MAAA;AAAA,IAC3B;AAAA,EAEF;AAAA,EAEA,MAAa,cAAc,WAA4B,OAAe,UAAkD;AACvH,UAAM,SAAS,MAAM,UAAU,aAAa,MAAM,IAAIC,mBAAAA,mBAAmB,UAAU,SAAS,CAAC;AAC7F,UAAM,WAAW,MAAM,UAAU,aAAa,MAAMC,iBAAAA,iBAAiB,QAAQ,OAAO,gBAAgB,CAAC;AACrG,QAAI,CAAC,UAAU;AACd,aAAO,IAAIC,SAAAA,cAAc,mBAAmB,mBAAmB;AAAA,QAC9D,CAACC,eAAAA,eAAe,GAAG,GAAG,IAAIA,eAAAA,eAAe,IAAI,CAAA,CAAE;AAAA,MAAA,CAC/C;AAAA,IACF;AAEA,UAAM,cAAc,IAAIA,eAAAA,eAAe,IAAI;AAAA,MAC1C,UAAU,SAAS;AAAA,MACnB,SAAS,SAAS;AAAA,IAAA,CAClB;AACD,UAAM,eAAe,MAAM,KAAK,0BAA0B,OAAO,UAAU,OAAO,UAAU,mBAAmB;AAC/G,QAAI,CAAC,aAAa,IAAI;AACrB,aAAO,IAAID,SAAAA,cAAc,aAAa,OAAO,aAAa,cAAc;AAAA,QACvE,GAAG,aAAa,YAAY,CAAA;AAAA,QAC5B,CAACC,eAAAA,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,UAAM,sBAAsB,MAAM,UAAU,WAAW,QAAQ,IAAIC,qBAAAA,qBAAqB,OAAO,QAAQ,CAAC;AACxG,QAAI,CAAC,oBAAoB,IAAI;AAC5B,aAAO,IAAIF,SAAAA,cAAc,oBAAoB,OAAO,oBAAoB,cAAc;AAAA,QACrF,GAAG,oBAAoB,YAAY,CAAA;AAAA,QACnC,CAACC,eAAAA,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,WAAO,IAAIE,SAAAA,WAAW;AAAA,MACrB,CAACF,eAAAA,eAAe,GAAG,GAAG;AAAA,IAAA,CACtB;AAAA,EACF;AACD;;"}
1
+ {"version":3,"file":"PasswordResetManager.cjs","sources":["../../../../../../packages/engine-tenant-api/src/model/service/PasswordResetManager.ts"],"sourcesContent":["import { Response, ResponseError, ResponseOk } from '../utils/Response.js'\nimport { UserMailer } from '../mailing/index.js'\nimport { ConfigurationQuery, LocalAuthDisablingIdpsQuery, PersonRow } from '../queries/index.js'\nimport { PermissionContext } from '../authorization/index.js'\nimport { ProjectManager } from './ProjectManager.js'\nimport { DatabaseContext } from '../utils/index.js'\nimport { ImplementationException } from '../../exceptions.js'\nimport { getPreferredProject } from './helpers/getPreferredProject.js'\nimport { CreatePersonTokenCommand, ResetPasswordCommand } from '../commands/personToken/index.js'\nimport { PasswordStrengthValidator } from './PasswordStrengthValidator.js'\nimport { ResetPasswordErrorCode, WeakPasswordReason } from '../../schema/index.js'\nimport { PersonTokenQuery } from '../queries/personToken/PersonTokenQuery.js'\nimport { AuthLogService } from './AuthLogService.js'\nimport { NextMailAttemptQuery } from '../queries/authLog/NextMailAttemptQuery.js'\n\ninterface MailOptions {\n\tproject?: string\n\tmailVariant?: string\n}\n\nexport class PasswordResetManager {\n\tconstructor(\n\t\tprivate readonly mailer: UserMailer,\n\t\tprivate readonly projectManager: ProjectManager,\n\t\tprivate readonly passwordStrengthValidator: PasswordStrengthValidator,\n\t) {}\n\n\tpublic async createPasswordResetRequest(\n\t\tdbContext: DatabaseContext,\n\t\tpermissionContext: PermissionContext,\n\t\tperson: PersonRow,\n\t\tmailOptions: MailOptions = {},\n\t): Promise<void> {\n\t\tif (!person.email) {\n\t\t\tthrow new ImplementationException()\n\t\t}\n\n\t\t// A person federated through a provider with `disableLocalAuthentication`\n\t\t// cannot sign in with a password, so a reset mail would only offer them a\n\t\t// credential the tenant refuses — and one more link worth phishing.\n\t\tconst exclusiveIdps = await dbContext.queryHandler.fetch(new LocalAuthDisablingIdpsQuery(person.id))\n\t\tif (exclusiveIdps.length > 0) {\n\t\t\treturn\n\t\t}\n\n\t\t// Per-email exponential backoff on outbound mails — don't spam a real\n\t\t// user with reset mails just because attackers keep poking the\n\t\t// endpoint. Reuses login_* backoff config against person_auth_log.\n\t\tconst nextAllowed = await dbContext.queryHandler.fetch(\n\t\t\tnew NextMailAttemptQuery(person.email, 'password_reset_init', 'password_reset'),\n\t\t)\n\t\tif (nextAllowed > new Date()) {\n\t\t\treturn\n\t\t}\n\n\t\tconst result = await dbContext.commandBus.execute(CreatePersonTokenCommand.createPasswordResetRequest(person.id))\n\t\tconst projects = await this.projectManager.getProjectsByIdentity(dbContext, person.identity_id, permissionContext)\n\t\tconst project = getPreferredProject(projects, mailOptions.project ?? null)\n\n\t\tawait this.mailer.sendPasswordResetEmail(\n\t\t\tdbContext,\n\t\t\t{\n\t\t\t\temail: person.email,\n\t\t\t\ttoken: result.token,\n\t\t\t\tproject: project?.name,\n\t\t\t\tprojectSlug: project?.slug,\n\t\t\t},\n\t\t\t{\n\t\t\t\tvariant: mailOptions.mailVariant || '',\n\t\t\t\tprojectId: project?.id ?? null,\n\t\t\t},\n\t\t)\n\t}\n\n\tpublic async resetPassword(dbContext: DatabaseContext, token: string, password: string): Promise<ResetPasswordResponse> {\n\t\tconst config = await dbContext.queryHandler.fetch(new ConfigurationQuery(dbContext.providers))\n\t\tconst tokenRow = await dbContext.queryHandler.fetch(PersonTokenQuery.byToken(token, 'password_reset'))\n\t\tif (!tokenRow) {\n\t\t\treturn new ResponseError('TOKEN_NOT_FOUND', 'Token not found', {\n\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({}),\n\t\t\t})\n\t\t}\n\n\t\tconst authLogData = new AuthLogService.Bag({\n\t\t\tpersonId: tokenRow.person_id,\n\t\t\ttokenId: tokenRow.id,\n\t\t})\n\t\tconst weakPassword = await this.passwordStrengthValidator.verify(password, config.password, 'PASSWORD_TOO_WEAK')\n\t\tif (!weakPassword.ok) {\n\t\t\treturn new ResponseError(weakPassword.error, weakPassword.errorMessage, {\n\t\t\t\t...weakPassword.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\tconst resetPasswordResult = await dbContext.commandBus.execute(new ResetPasswordCommand(token, password))\n\t\tif (!resetPasswordResult.ok) {\n\t\t\treturn new ResponseError(resetPasswordResult.error, resetPasswordResult.errorMessage, {\n\t\t\t\t...resetPasswordResult.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\treturn new ResponseOk({\n\t\t\t[AuthLogService.Key]: authLogData,\n\t\t})\n\t}\n}\n\nexport type ResetPasswordResponse = Response<\n\t{\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t},\n\tResetPasswordErrorCode,\n\t{\n\t\tweakPasswordReasons?: WeakPasswordReason[]\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}\n>\n"],"names":["ImplementationException","LocalAuthDisablingIdpsQuery","NextMailAttemptQuery","CreatePersonTokenCommand","getPreferredProject","ConfigurationQuery","PersonTokenQuery","ResponseError","AuthLogService","ResetPasswordCommand","ResponseOk"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBO,MAAM,qBAAqB;AAAA,EACjC,YACkB,QACA,gBACA,2BAChB;AAHgB,SAAA,SAAA;AACA,SAAA,iBAAA;AACA,SAAA,4BAAA;AAAA,EACf;AAAA,EAEH,MAAa,2BACZ,WACA,mBACA,QACA,cAA2B,CAAA,GACX;AAChB,QAAI,CAAC,OAAO,OAAO;AAClB,YAAM,IAAIA,WAAAA,wBAAA;AAAA,IACX;AAKA,UAAM,gBAAgB,MAAM,UAAU,aAAa,MAAM,IAAIC,4BAAAA,4BAA4B,OAAO,EAAE,CAAC;AACnG,QAAI,cAAc,SAAS,GAAG;AAC7B;AAAA,IACD;AAKA,UAAM,cAAc,MAAM,UAAU,aAAa;AAAA,MAChD,IAAIC,0CAAqB,OAAO,OAAO,uBAAuB,gBAAgB;AAAA,IAAA;AAE/E,QAAI,cAAc,oBAAI,QAAQ;AAC7B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM,UAAU,WAAW,QAAQC,yBAAAA,yBAAyB,2BAA2B,OAAO,EAAE,CAAC;AAChH,UAAM,WAAW,MAAM,KAAK,eAAe,sBAAsB,WAAW,OAAO,aAAa,iBAAiB;AACjH,UAAM,UAAUC,oBAAAA,oBAAoB,UAAU,YAAY,WAAW,IAAI;AAEzE,UAAM,KAAK,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,QACC,OAAO,OAAO;AAAA,QACd,OAAO,OAAO;AAAA,QACd,SAAS,SAAS;AAAA,QAClB,aAAa,SAAS;AAAA,MAAA;AAAA,MAEvB;AAAA,QACC,SAAS,YAAY,eAAe;AAAA,QACpC,WAAW,SAAS,MAAM;AAAA,MAAA;AAAA,IAC3B;AAAA,EAEF;AAAA,EAEA,MAAa,cAAc,WAA4B,OAAe,UAAkD;AACvH,UAAM,SAAS,MAAM,UAAU,aAAa,MAAM,IAAIC,mBAAAA,mBAAmB,UAAU,SAAS,CAAC;AAC7F,UAAM,WAAW,MAAM,UAAU,aAAa,MAAMC,iBAAAA,iBAAiB,QAAQ,OAAO,gBAAgB,CAAC;AACrG,QAAI,CAAC,UAAU;AACd,aAAO,IAAIC,SAAAA,cAAc,mBAAmB,mBAAmB;AAAA,QAC9D,CAACC,eAAAA,eAAe,GAAG,GAAG,IAAIA,eAAAA,eAAe,IAAI,CAAA,CAAE;AAAA,MAAA,CAC/C;AAAA,IACF;AAEA,UAAM,cAAc,IAAIA,eAAAA,eAAe,IAAI;AAAA,MAC1C,UAAU,SAAS;AAAA,MACnB,SAAS,SAAS;AAAA,IAAA,CAClB;AACD,UAAM,eAAe,MAAM,KAAK,0BAA0B,OAAO,UAAU,OAAO,UAAU,mBAAmB;AAC/G,QAAI,CAAC,aAAa,IAAI;AACrB,aAAO,IAAID,SAAAA,cAAc,aAAa,OAAO,aAAa,cAAc;AAAA,QACvE,GAAG,aAAa,YAAY,CAAA;AAAA,QAC5B,CAACC,eAAAA,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,UAAM,sBAAsB,MAAM,UAAU,WAAW,QAAQ,IAAIC,qBAAAA,qBAAqB,OAAO,QAAQ,CAAC;AACxG,QAAI,CAAC,oBAAoB,IAAI;AAC5B,aAAO,IAAIF,SAAAA,cAAc,oBAAoB,OAAO,oBAAoB,cAAc;AAAA,QACrF,GAAG,oBAAoB,YAAY,CAAA;AAAA,QACnC,CAACC,eAAAA,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,WAAO,IAAIE,SAAAA,WAAW;AAAA,MACrB,CAACF,eAAAA,eAAe,GAAG,GAAG;AAAA,IAAA,CACtB;AAAA,EACF;AACD;;"}
@@ -4,6 +4,7 @@ import "@contember/database";
4
4
  import "../type/ApiKey.js";
5
5
  import { ConfigurationQuery } from "../queries/configuration/ConfigurationQuery.js";
6
6
  import { ImplementationException } from "../../exceptions.js";
7
+ import { LocalAuthDisablingIdpsQuery } from "../queries/idp/LocalAuthDisablingIdpsQuery.js";
7
8
  import "../authorization/PermissionActions.js";
8
9
  import "@contember/authorization";
9
10
  import "../authorization/PermissionContext.js";
@@ -26,6 +27,10 @@ class PasswordResetManager {
26
27
  if (!person.email) {
27
28
  throw new ImplementationException();
28
29
  }
30
+ const exclusiveIdps = await dbContext.queryHandler.fetch(new LocalAuthDisablingIdpsQuery(person.id));
31
+ if (exclusiveIdps.length > 0) {
32
+ return;
33
+ }
29
34
  const nextAllowed = await dbContext.queryHandler.fetch(
30
35
  new NextMailAttemptQuery(person.email, "password_reset_init", "password_reset")
31
36
  );
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordResetManager.js","sources":["../../../../../../packages/engine-tenant-api/src/model/service/PasswordResetManager.ts"],"sourcesContent":["import { Response, ResponseError, ResponseOk } from '../utils/Response.js'\nimport { UserMailer } from '../mailing/index.js'\nimport { ConfigurationQuery, PersonRow } from '../queries/index.js'\nimport { PermissionContext } from '../authorization/index.js'\nimport { ProjectManager } from './ProjectManager.js'\nimport { DatabaseContext } from '../utils/index.js'\nimport { ImplementationException } from '../../exceptions.js'\nimport { getPreferredProject } from './helpers/getPreferredProject.js'\nimport { CreatePersonTokenCommand, ResetPasswordCommand } from '../commands/personToken/index.js'\nimport { PasswordStrengthValidator } from './PasswordStrengthValidator.js'\nimport { ResetPasswordErrorCode, WeakPasswordReason } from '../../schema/index.js'\nimport { PersonTokenQuery } from '../queries/personToken/PersonTokenQuery.js'\nimport { AuthLogService } from './AuthLogService.js'\nimport { NextMailAttemptQuery } from '../queries/authLog/NextMailAttemptQuery.js'\n\ninterface MailOptions {\n\tproject?: string\n\tmailVariant?: string\n}\n\nexport class PasswordResetManager {\n\tconstructor(\n\t\tprivate readonly mailer: UserMailer,\n\t\tprivate readonly projectManager: ProjectManager,\n\t\tprivate readonly passwordStrengthValidator: PasswordStrengthValidator,\n\t) {}\n\n\tpublic async createPasswordResetRequest(\n\t\tdbContext: DatabaseContext,\n\t\tpermissionContext: PermissionContext,\n\t\tperson: PersonRow,\n\t\tmailOptions: MailOptions = {},\n\t): Promise<void> {\n\t\tif (!person.email) {\n\t\t\tthrow new ImplementationException()\n\t\t}\n\n\t\t// Per-email exponential backoff on outbound mails — don't spam a real\n\t\t// user with reset mails just because attackers keep poking the\n\t\t// endpoint. Reuses login_* backoff config against person_auth_log.\n\t\tconst nextAllowed = await dbContext.queryHandler.fetch(\n\t\t\tnew NextMailAttemptQuery(person.email, 'password_reset_init', 'password_reset'),\n\t\t)\n\t\tif (nextAllowed > new Date()) {\n\t\t\treturn\n\t\t}\n\n\t\tconst result = await dbContext.commandBus.execute(CreatePersonTokenCommand.createPasswordResetRequest(person.id))\n\t\tconst projects = await this.projectManager.getProjectsByIdentity(dbContext, person.identity_id, permissionContext)\n\t\tconst project = getPreferredProject(projects, mailOptions.project ?? null)\n\n\t\tawait this.mailer.sendPasswordResetEmail(\n\t\t\tdbContext,\n\t\t\t{\n\t\t\t\temail: person.email,\n\t\t\t\ttoken: result.token,\n\t\t\t\tproject: project?.name,\n\t\t\t\tprojectSlug: project?.slug,\n\t\t\t},\n\t\t\t{\n\t\t\t\tvariant: mailOptions.mailVariant || '',\n\t\t\t\tprojectId: project?.id ?? null,\n\t\t\t},\n\t\t)\n\t}\n\n\tpublic async resetPassword(dbContext: DatabaseContext, token: string, password: string): Promise<ResetPasswordResponse> {\n\t\tconst config = await dbContext.queryHandler.fetch(new ConfigurationQuery(dbContext.providers))\n\t\tconst tokenRow = await dbContext.queryHandler.fetch(PersonTokenQuery.byToken(token, 'password_reset'))\n\t\tif (!tokenRow) {\n\t\t\treturn new ResponseError('TOKEN_NOT_FOUND', 'Token not found', {\n\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({}),\n\t\t\t})\n\t\t}\n\n\t\tconst authLogData = new AuthLogService.Bag({\n\t\t\tpersonId: tokenRow.person_id,\n\t\t\ttokenId: tokenRow.id,\n\t\t})\n\t\tconst weakPassword = await this.passwordStrengthValidator.verify(password, config.password, 'PASSWORD_TOO_WEAK')\n\t\tif (!weakPassword.ok) {\n\t\t\treturn new ResponseError(weakPassword.error, weakPassword.errorMessage, {\n\t\t\t\t...weakPassword.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\tconst resetPasswordResult = await dbContext.commandBus.execute(new ResetPasswordCommand(token, password))\n\t\tif (!resetPasswordResult.ok) {\n\t\t\treturn new ResponseError(resetPasswordResult.error, resetPasswordResult.errorMessage, {\n\t\t\t\t...resetPasswordResult.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\treturn new ResponseOk({\n\t\t\t[AuthLogService.Key]: authLogData,\n\t\t})\n\t}\n}\n\nexport type ResetPasswordResponse = Response<\n\t{\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t},\n\tResetPasswordErrorCode,\n\t{\n\t\tweakPasswordReasons?: WeakPasswordReason[]\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}\n>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAoBO,MAAM,qBAAqB;AAAA,EACjC,YACkB,QACA,gBACA,2BAChB;AAHgB,SAAA,SAAA;AACA,SAAA,iBAAA;AACA,SAAA,4BAAA;AAAA,EACf;AAAA,EAEH,MAAa,2BACZ,WACA,mBACA,QACA,cAA2B,CAAA,GACX;AAChB,QAAI,CAAC,OAAO,OAAO;AAClB,YAAM,IAAI,wBAAA;AAAA,IACX;AAKA,UAAM,cAAc,MAAM,UAAU,aAAa;AAAA,MAChD,IAAI,qBAAqB,OAAO,OAAO,uBAAuB,gBAAgB;AAAA,IAAA;AAE/E,QAAI,cAAc,oBAAI,QAAQ;AAC7B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM,UAAU,WAAW,QAAQ,yBAAyB,2BAA2B,OAAO,EAAE,CAAC;AAChH,UAAM,WAAW,MAAM,KAAK,eAAe,sBAAsB,WAAW,OAAO,aAAa,iBAAiB;AACjH,UAAM,UAAU,oBAAoB,UAAU,YAAY,WAAW,IAAI;AAEzE,UAAM,KAAK,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,QACC,OAAO,OAAO;AAAA,QACd,OAAO,OAAO;AAAA,QACd,SAAS,SAAS;AAAA,QAClB,aAAa,SAAS;AAAA,MAAA;AAAA,MAEvB;AAAA,QACC,SAAS,YAAY,eAAe;AAAA,QACpC,WAAW,SAAS,MAAM;AAAA,MAAA;AAAA,IAC3B;AAAA,EAEF;AAAA,EAEA,MAAa,cAAc,WAA4B,OAAe,UAAkD;AACvH,UAAM,SAAS,MAAM,UAAU,aAAa,MAAM,IAAI,mBAAmB,UAAU,SAAS,CAAC;AAC7F,UAAM,WAAW,MAAM,UAAU,aAAa,MAAM,iBAAiB,QAAQ,OAAO,gBAAgB,CAAC;AACrG,QAAI,CAAC,UAAU;AACd,aAAO,IAAI,cAAc,mBAAmB,mBAAmB;AAAA,QAC9D,CAAC,eAAe,GAAG,GAAG,IAAI,eAAe,IAAI,CAAA,CAAE;AAAA,MAAA,CAC/C;AAAA,IACF;AAEA,UAAM,cAAc,IAAI,eAAe,IAAI;AAAA,MAC1C,UAAU,SAAS;AAAA,MACnB,SAAS,SAAS;AAAA,IAAA,CAClB;AACD,UAAM,eAAe,MAAM,KAAK,0BAA0B,OAAO,UAAU,OAAO,UAAU,mBAAmB;AAC/G,QAAI,CAAC,aAAa,IAAI;AACrB,aAAO,IAAI,cAAc,aAAa,OAAO,aAAa,cAAc;AAAA,QACvE,GAAG,aAAa,YAAY,CAAA;AAAA,QAC5B,CAAC,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,UAAM,sBAAsB,MAAM,UAAU,WAAW,QAAQ,IAAI,qBAAqB,OAAO,QAAQ,CAAC;AACxG,QAAI,CAAC,oBAAoB,IAAI;AAC5B,aAAO,IAAI,cAAc,oBAAoB,OAAO,oBAAoB,cAAc;AAAA,QACrF,GAAG,oBAAoB,YAAY,CAAA;AAAA,QACnC,CAAC,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,WAAO,IAAI,WAAW;AAAA,MACrB,CAAC,eAAe,GAAG,GAAG;AAAA,IAAA,CACtB;AAAA,EACF;AACD;"}
1
+ {"version":3,"file":"PasswordResetManager.js","sources":["../../../../../../packages/engine-tenant-api/src/model/service/PasswordResetManager.ts"],"sourcesContent":["import { Response, ResponseError, ResponseOk } from '../utils/Response.js'\nimport { UserMailer } from '../mailing/index.js'\nimport { ConfigurationQuery, LocalAuthDisablingIdpsQuery, PersonRow } from '../queries/index.js'\nimport { PermissionContext } from '../authorization/index.js'\nimport { ProjectManager } from './ProjectManager.js'\nimport { DatabaseContext } from '../utils/index.js'\nimport { ImplementationException } from '../../exceptions.js'\nimport { getPreferredProject } from './helpers/getPreferredProject.js'\nimport { CreatePersonTokenCommand, ResetPasswordCommand } from '../commands/personToken/index.js'\nimport { PasswordStrengthValidator } from './PasswordStrengthValidator.js'\nimport { ResetPasswordErrorCode, WeakPasswordReason } from '../../schema/index.js'\nimport { PersonTokenQuery } from '../queries/personToken/PersonTokenQuery.js'\nimport { AuthLogService } from './AuthLogService.js'\nimport { NextMailAttemptQuery } from '../queries/authLog/NextMailAttemptQuery.js'\n\ninterface MailOptions {\n\tproject?: string\n\tmailVariant?: string\n}\n\nexport class PasswordResetManager {\n\tconstructor(\n\t\tprivate readonly mailer: UserMailer,\n\t\tprivate readonly projectManager: ProjectManager,\n\t\tprivate readonly passwordStrengthValidator: PasswordStrengthValidator,\n\t) {}\n\n\tpublic async createPasswordResetRequest(\n\t\tdbContext: DatabaseContext,\n\t\tpermissionContext: PermissionContext,\n\t\tperson: PersonRow,\n\t\tmailOptions: MailOptions = {},\n\t): Promise<void> {\n\t\tif (!person.email) {\n\t\t\tthrow new ImplementationException()\n\t\t}\n\n\t\t// A person federated through a provider with `disableLocalAuthentication`\n\t\t// cannot sign in with a password, so a reset mail would only offer them a\n\t\t// credential the tenant refuses — and one more link worth phishing.\n\t\tconst exclusiveIdps = await dbContext.queryHandler.fetch(new LocalAuthDisablingIdpsQuery(person.id))\n\t\tif (exclusiveIdps.length > 0) {\n\t\t\treturn\n\t\t}\n\n\t\t// Per-email exponential backoff on outbound mails — don't spam a real\n\t\t// user with reset mails just because attackers keep poking the\n\t\t// endpoint. Reuses login_* backoff config against person_auth_log.\n\t\tconst nextAllowed = await dbContext.queryHandler.fetch(\n\t\t\tnew NextMailAttemptQuery(person.email, 'password_reset_init', 'password_reset'),\n\t\t)\n\t\tif (nextAllowed > new Date()) {\n\t\t\treturn\n\t\t}\n\n\t\tconst result = await dbContext.commandBus.execute(CreatePersonTokenCommand.createPasswordResetRequest(person.id))\n\t\tconst projects = await this.projectManager.getProjectsByIdentity(dbContext, person.identity_id, permissionContext)\n\t\tconst project = getPreferredProject(projects, mailOptions.project ?? null)\n\n\t\tawait this.mailer.sendPasswordResetEmail(\n\t\t\tdbContext,\n\t\t\t{\n\t\t\t\temail: person.email,\n\t\t\t\ttoken: result.token,\n\t\t\t\tproject: project?.name,\n\t\t\t\tprojectSlug: project?.slug,\n\t\t\t},\n\t\t\t{\n\t\t\t\tvariant: mailOptions.mailVariant || '',\n\t\t\t\tprojectId: project?.id ?? null,\n\t\t\t},\n\t\t)\n\t}\n\n\tpublic async resetPassword(dbContext: DatabaseContext, token: string, password: string): Promise<ResetPasswordResponse> {\n\t\tconst config = await dbContext.queryHandler.fetch(new ConfigurationQuery(dbContext.providers))\n\t\tconst tokenRow = await dbContext.queryHandler.fetch(PersonTokenQuery.byToken(token, 'password_reset'))\n\t\tif (!tokenRow) {\n\t\t\treturn new ResponseError('TOKEN_NOT_FOUND', 'Token not found', {\n\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({}),\n\t\t\t})\n\t\t}\n\n\t\tconst authLogData = new AuthLogService.Bag({\n\t\t\tpersonId: tokenRow.person_id,\n\t\t\ttokenId: tokenRow.id,\n\t\t})\n\t\tconst weakPassword = await this.passwordStrengthValidator.verify(password, config.password, 'PASSWORD_TOO_WEAK')\n\t\tif (!weakPassword.ok) {\n\t\t\treturn new ResponseError(weakPassword.error, weakPassword.errorMessage, {\n\t\t\t\t...weakPassword.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\tconst resetPasswordResult = await dbContext.commandBus.execute(new ResetPasswordCommand(token, password))\n\t\tif (!resetPasswordResult.ok) {\n\t\t\treturn new ResponseError(resetPasswordResult.error, resetPasswordResult.errorMessage, {\n\t\t\t\t...resetPasswordResult.metadata ?? {},\n\t\t\t\t[AuthLogService.Key]: authLogData,\n\t\t\t})\n\t\t}\n\t\treturn new ResponseOk({\n\t\t\t[AuthLogService.Key]: authLogData,\n\t\t})\n\t}\n}\n\nexport type ResetPasswordResponse = Response<\n\t{\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t},\n\tResetPasswordErrorCode,\n\t{\n\t\tweakPasswordReasons?: WeakPasswordReason[]\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}\n>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAoBO,MAAM,qBAAqB;AAAA,EACjC,YACkB,QACA,gBACA,2BAChB;AAHgB,SAAA,SAAA;AACA,SAAA,iBAAA;AACA,SAAA,4BAAA;AAAA,EACf;AAAA,EAEH,MAAa,2BACZ,WACA,mBACA,QACA,cAA2B,CAAA,GACX;AAChB,QAAI,CAAC,OAAO,OAAO;AAClB,YAAM,IAAI,wBAAA;AAAA,IACX;AAKA,UAAM,gBAAgB,MAAM,UAAU,aAAa,MAAM,IAAI,4BAA4B,OAAO,EAAE,CAAC;AACnG,QAAI,cAAc,SAAS,GAAG;AAC7B;AAAA,IACD;AAKA,UAAM,cAAc,MAAM,UAAU,aAAa;AAAA,MAChD,IAAI,qBAAqB,OAAO,OAAO,uBAAuB,gBAAgB;AAAA,IAAA;AAE/E,QAAI,cAAc,oBAAI,QAAQ;AAC7B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM,UAAU,WAAW,QAAQ,yBAAyB,2BAA2B,OAAO,EAAE,CAAC;AAChH,UAAM,WAAW,MAAM,KAAK,eAAe,sBAAsB,WAAW,OAAO,aAAa,iBAAiB;AACjH,UAAM,UAAU,oBAAoB,UAAU,YAAY,WAAW,IAAI;AAEzE,UAAM,KAAK,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,QACC,OAAO,OAAO;AAAA,QACd,OAAO,OAAO;AAAA,QACd,SAAS,SAAS;AAAA,QAClB,aAAa,SAAS;AAAA,MAAA;AAAA,MAEvB;AAAA,QACC,SAAS,YAAY,eAAe;AAAA,QACpC,WAAW,SAAS,MAAM;AAAA,MAAA;AAAA,IAC3B;AAAA,EAEF;AAAA,EAEA,MAAa,cAAc,WAA4B,OAAe,UAAkD;AACvH,UAAM,SAAS,MAAM,UAAU,aAAa,MAAM,IAAI,mBAAmB,UAAU,SAAS,CAAC;AAC7F,UAAM,WAAW,MAAM,UAAU,aAAa,MAAM,iBAAiB,QAAQ,OAAO,gBAAgB,CAAC;AACrG,QAAI,CAAC,UAAU;AACd,aAAO,IAAI,cAAc,mBAAmB,mBAAmB;AAAA,QAC9D,CAAC,eAAe,GAAG,GAAG,IAAI,eAAe,IAAI,CAAA,CAAE;AAAA,MAAA,CAC/C;AAAA,IACF;AAEA,UAAM,cAAc,IAAI,eAAe,IAAI;AAAA,MAC1C,UAAU,SAAS;AAAA,MACnB,SAAS,SAAS;AAAA,IAAA,CAClB;AACD,UAAM,eAAe,MAAM,KAAK,0BAA0B,OAAO,UAAU,OAAO,UAAU,mBAAmB;AAC/G,QAAI,CAAC,aAAa,IAAI;AACrB,aAAO,IAAI,cAAc,aAAa,OAAO,aAAa,cAAc;AAAA,QACvE,GAAG,aAAa,YAAY,CAAA;AAAA,QAC5B,CAAC,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,UAAM,sBAAsB,MAAM,UAAU,WAAW,QAAQ,IAAI,qBAAqB,OAAO,QAAQ,CAAC;AACxG,QAAI,CAAC,oBAAoB,IAAI;AAC5B,aAAO,IAAI,cAAc,oBAAoB,OAAO,oBAAoB,cAAc;AAAA,QACrF,GAAG,oBAAoB,YAAY,CAAA;AAAA,QACnC,CAAC,eAAe,GAAG,GAAG;AAAA,MAAA,CACtB;AAAA,IACF;AACA,WAAO,IAAI,WAAW;AAAA,MACrB,CAAC,eAAe,GAAG,GAAG;AAAA,IAAA,CACtB;AAAA,EACF;AACD;"}