@adonis-agora/authkit-server 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/build/assets/grafana/authkit-dashboard.json +118 -0
  4. package/build/commands/clients_create.d.ts +27 -0
  5. package/build/commands/clients_create.js +121 -0
  6. package/build/commands/commands.json +292 -0
  7. package/build/commands/configure.d.ts +2 -0
  8. package/build/commands/configure.js +45 -0
  9. package/build/commands/doctor.d.ts +10 -0
  10. package/build/commands/doctor.js +113 -0
  11. package/build/commands/eject.d.ts +11 -0
  12. package/build/commands/eject.js +96 -0
  13. package/build/commands/expire_scan.d.ts +28 -0
  14. package/build/commands/expire_scan.js +92 -0
  15. package/build/commands/import_users.d.ts +17 -0
  16. package/build/commands/import_users.js +80 -0
  17. package/build/commands/keys_rotate.d.ts +21 -0
  18. package/build/commands/keys_rotate.js +126 -0
  19. package/build/commands/main.d.ts +12 -0
  20. package/build/commands/main.js +38 -0
  21. package/build/commands/settings_get.d.ts +18 -0
  22. package/build/commands/settings_get.js +43 -0
  23. package/build/commands/settings_list.d.ts +17 -0
  24. package/build/commands/settings_list.js +39 -0
  25. package/build/commands/settings_set.d.ts +20 -0
  26. package/build/commands/settings_set.js +55 -0
  27. package/build/commands/settings_unset.d.ts +18 -0
  28. package/build/commands/settings_unset.js +46 -0
  29. package/build/commands/ui_preset.d.ts +4 -0
  30. package/build/commands/ui_preset.js +32 -0
  31. package/build/database/migrations/make_authkit_oidc_table.d.ts +6 -0
  32. package/build/database/migrations/make_authkit_oidc_table.js +19 -0
  33. package/build/host/ui/admin.html +29 -0
  34. package/build/host/views/account/apps.edge +59 -0
  35. package/build/host/views/account/confirm.edge +70 -0
  36. package/build/host/views/account/email-confirmed.edge +16 -0
  37. package/build/host/views/account/login.edge +33 -0
  38. package/build/host/views/account/mfa.edge +152 -0
  39. package/build/host/views/account/orgs.edge +58 -0
  40. package/build/host/views/account/security.edge +215 -0
  41. package/build/host/views/account/tokens.edge +75 -0
  42. package/build/host/views/consent.edge +20 -0
  43. package/build/host/views/forgot.edge +43 -0
  44. package/build/host/views/login.edge +251 -0
  45. package/build/host/views/maintenance.edge +32 -0
  46. package/build/host/views/mfa-challenge.edge +107 -0
  47. package/build/host/views/otp-unlock.edge +40 -0
  48. package/build/host/views/partials/styles.edge +2 -0
  49. package/build/host/views/reset.edge +30 -0
  50. package/build/host/views/signup.edge +62 -0
  51. package/build/host/views/verify-email.edge +17 -0
  52. package/build/index.d.ts +115 -0
  53. package/build/index.js +76 -0
  54. package/build/password/common_passwords.txt +10000 -0
  55. package/build/providers/authkit_server_provider.d.ts +27 -0
  56. package/build/providers/authkit_server_provider.js +242 -0
  57. package/build/src/accounts/account_store.d.ts +578 -0
  58. package/build/src/accounts/account_store.js +60 -0
  59. package/build/src/accounts/lucid_account_store.d.ts +156 -0
  60. package/build/src/accounts/lucid_account_store.js +294 -0
  61. package/build/src/accounts/lucid_store/core.d.ts +9 -0
  62. package/build/src/accounts/lucid_store/core.js +306 -0
  63. package/build/src/accounts/lucid_store/mfa.d.ts +15 -0
  64. package/build/src/accounts/lucid_store/mfa.js +108 -0
  65. package/build/src/accounts/lucid_store/organizations.d.ts +13 -0
  66. package/build/src/accounts/lucid_store/organizations.js +294 -0
  67. package/build/src/accounts/lucid_store/password_hygiene.d.ts +20 -0
  68. package/build/src/accounts/lucid_store/password_hygiene.js +130 -0
  69. package/build/src/accounts/lucid_store/provider_identity.d.ts +8 -0
  70. package/build/src/accounts/lucid_store/provider_identity.js +59 -0
  71. package/build/src/accounts/lucid_store/shared.d.ts +113 -0
  72. package/build/src/accounts/lucid_store/shared.js +130 -0
  73. package/build/src/accounts/lucid_store/status_profile.d.ts +34 -0
  74. package/build/src/accounts/lucid_store/status_profile.js +100 -0
  75. package/build/src/accounts/lucid_store/webauthn.d.ts +8 -0
  76. package/build/src/accounts/lucid_store/webauthn.js +140 -0
  77. package/build/src/accounts/lucid_stores.d.ts +45 -0
  78. package/build/src/accounts/lucid_stores.js +30 -0
  79. package/build/src/adapters/adapter_contract.d.ts +37 -0
  80. package/build/src/adapters/adapter_contract.js +1 -0
  81. package/build/src/adapters/database_adapter.d.ts +21 -0
  82. package/build/src/adapters/database_adapter.js +79 -0
  83. package/build/src/adapters/factory.d.ts +30 -0
  84. package/build/src/adapters/factory.js +43 -0
  85. package/build/src/adapters/redis_adapter.d.ts +24 -0
  86. package/build/src/adapters/redis_adapter.js +122 -0
  87. package/build/src/audit/audit_sink.d.ts +63 -0
  88. package/build/src/audit/audit_sink.js +1 -0
  89. package/build/src/audit/lucid_audit_sink.d.ts +10 -0
  90. package/build/src/audit/lucid_audit_sink.js +99 -0
  91. package/build/src/commands/expire_scan_command.d.ts +60 -0
  92. package/build/src/commands/expire_scan_command.js +229 -0
  93. package/build/src/commands/import_clients.d.ts +40 -0
  94. package/build/src/commands/import_clients.js +79 -0
  95. package/build/src/commands/import_users.d.ts +51 -0
  96. package/build/src/commands/import_users.js +94 -0
  97. package/build/src/commands/resolve_config.d.ts +13 -0
  98. package/build/src/commands/resolve_config.js +18 -0
  99. package/build/src/commands/settings_commands.d.ts +47 -0
  100. package/build/src/commands/settings_commands.js +270 -0
  101. package/build/src/controllers/oidc_callback_controller.d.ts +22 -0
  102. package/build/src/controllers/oidc_callback_controller.js +33 -0
  103. package/build/src/define_config.d.ts +772 -0
  104. package/build/src/define_config.js +351 -0
  105. package/build/src/doctor/checks.d.ts +197 -0
  106. package/build/src/doctor/checks.js +858 -0
  107. package/build/src/events/dispatcher.d.ts +45 -0
  108. package/build/src/events/dispatcher.js +117 -0
  109. package/build/src/host/account_api/account_api_controller.d.ts +245 -0
  110. package/build/src/host/account_api/account_api_controller.js +827 -0
  111. package/build/src/host/account_deletion_ops.d.ts +80 -0
  112. package/build/src/host/account_deletion_ops.js +118 -0
  113. package/build/src/host/account_deletion_service.d.ts +63 -0
  114. package/build/src/host/account_deletion_service.js +133 -0
  115. package/build/src/host/account_export_service.d.ts +76 -0
  116. package/build/src/host/account_export_service.js +140 -0
  117. package/build/src/host/account_home.d.ts +11 -0
  118. package/build/src/host/account_home.js +11 -0
  119. package/build/src/host/account_lockout.d.ts +86 -0
  120. package/build/src/host/account_lockout.js +185 -0
  121. package/build/src/host/active_org_cookie.d.ts +28 -0
  122. package/build/src/host/active_org_cookie.js +47 -0
  123. package/build/src/host/admin_api/admin_api_guard.d.ts +16 -0
  124. package/build/src/host/admin_api/admin_api_guard.js +59 -0
  125. package/build/src/host/admin_api/admin_orgs_service.d.ts +125 -0
  126. package/build/src/host/admin_api/admin_orgs_service.js +324 -0
  127. package/build/src/host/admin_api/admin_users_service.d.ts +163 -0
  128. package/build/src/host/admin_api/admin_users_service.js +308 -0
  129. package/build/src/host/admin_api/api_clients_controller.d.ts +54 -0
  130. package/build/src/host/admin_api/api_clients_controller.js +89 -0
  131. package/build/src/host/admin_api/api_keys_controller.d.ts +19 -0
  132. package/build/src/host/admin_api/api_keys_controller.js +36 -0
  133. package/build/src/host/admin_api/api_misc_controller.d.ts +19 -0
  134. package/build/src/host/admin_api/api_misc_controller.js +44 -0
  135. package/build/src/host/admin_api/api_orgs_controller.d.ts +108 -0
  136. package/build/src/host/admin_api/api_orgs_controller.js +189 -0
  137. package/build/src/host/admin_api/api_settings_controller.d.ts +55 -0
  138. package/build/src/host/admin_api/api_settings_controller.js +134 -0
  139. package/build/src/host/admin_api/api_users_controller.d.ts +108 -0
  140. package/build/src/host/admin_api/api_users_controller.js +187 -0
  141. package/build/src/host/admin_api/dto.d.ts +131 -0
  142. package/build/src/host/admin_api/dto.js +122 -0
  143. package/build/src/host/admin_api/token_verify_service.d.ts +34 -0
  144. package/build/src/host/admin_api/token_verify_service.js +74 -0
  145. package/build/src/host/admin_clients_service.d.ts +88 -0
  146. package/build/src/host/admin_clients_service.js +181 -0
  147. package/build/src/host/admin_console/admin_shell_controller.d.ts +27 -0
  148. package/build/src/host/admin_console/admin_shell_controller.js +167 -0
  149. package/build/src/host/admin_console/console_audit_controller.d.ts +17 -0
  150. package/build/src/host/admin_console/console_audit_controller.js +25 -0
  151. package/build/src/host/admin_console/console_clients_controller.d.ts +53 -0
  152. package/build/src/host/admin_console/console_clients_controller.js +102 -0
  153. package/build/src/host/admin_console/console_impersonation_controller.d.ts +23 -0
  154. package/build/src/host/admin_console/console_impersonation_controller.js +45 -0
  155. package/build/src/host/admin_console/console_keys_controller.d.ts +24 -0
  156. package/build/src/host/admin_console/console_keys_controller.js +41 -0
  157. package/build/src/host/admin_console/console_orgs_controller.d.ts +96 -0
  158. package/build/src/host/admin_console/console_orgs_controller.js +238 -0
  159. package/build/src/host/admin_console/console_overview_controller.d.ts +27 -0
  160. package/build/src/host/admin_console/console_overview_controller.js +44 -0
  161. package/build/src/host/admin_console/console_roles_controller.d.ts +31 -0
  162. package/build/src/host/admin_console/console_roles_controller.js +108 -0
  163. package/build/src/host/admin_console/console_sessions_controller.d.ts +91 -0
  164. package/build/src/host/admin_console/console_sessions_controller.js +125 -0
  165. package/build/src/host/admin_console/console_settings_controller.d.ts +47 -0
  166. package/build/src/host/admin_console/console_settings_controller.js +115 -0
  167. package/build/src/host/admin_console/console_users_controller.d.ts +110 -0
  168. package/build/src/host/admin_console/console_users_controller.js +212 -0
  169. package/build/src/host/admin_prefix.d.ts +50 -0
  170. package/build/src/host/admin_prefix.js +77 -0
  171. package/build/src/host/admin_sessions_service.d.ts +119 -0
  172. package/build/src/host/admin_sessions_service.js +284 -0
  173. package/build/src/host/admin_stats_service.d.ts +44 -0
  174. package/build/src/host/admin_stats_service.js +130 -0
  175. package/build/src/host/admin_validators.d.ts +247 -0
  176. package/build/src/host/admin_validators.js +197 -0
  177. package/build/src/host/augmentations.d.ts +12 -0
  178. package/build/src/host/augmentations.js +1 -0
  179. package/build/src/host/auth_host_config.d.ts +22 -0
  180. package/build/src/host/auth_host_config.js +13 -0
  181. package/build/src/host/avatar_storage.d.ts +68 -0
  182. package/build/src/host/avatar_storage.js +166 -0
  183. package/build/src/host/bot_protection.d.ts +187 -0
  184. package/build/src/host/bot_protection.js +132 -0
  185. package/build/src/host/branding.d.ts +19 -0
  186. package/build/src/host/branding.js +8 -0
  187. package/build/src/host/config_locks.d.ts +38 -0
  188. package/build/src/host/config_locks.js +70 -0
  189. package/build/src/host/console_session.d.ts +27 -0
  190. package/build/src/host/console_session.js +36 -0
  191. package/build/src/host/controllers/account_apps_controller.d.ts +15 -0
  192. package/build/src/host/controllers/account_apps_controller.js +61 -0
  193. package/build/src/host/controllers/account_confirm_controller.d.ts +24 -0
  194. package/build/src/host/controllers/account_confirm_controller.js +144 -0
  195. package/build/src/host/controllers/account_mfa_controller.d.ts +28 -0
  196. package/build/src/host/controllers/account_mfa_controller.js +208 -0
  197. package/build/src/host/controllers/account_orgs_controller.d.ts +80 -0
  198. package/build/src/host/controllers/account_orgs_controller.js +401 -0
  199. package/build/src/host/controllers/account_security_controller.d.ts +43 -0
  200. package/build/src/host/controllers/account_security_controller.js +546 -0
  201. package/build/src/host/controllers/account_session_controller.d.ts +21 -0
  202. package/build/src/host/controllers/account_session_controller.js +113 -0
  203. package/build/src/host/controllers/account_tokens_controller.d.ts +7 -0
  204. package/build/src/host/controllers/account_tokens_controller.js +67 -0
  205. package/build/src/host/controllers/interaction_controller.d.ts +125 -0
  206. package/build/src/host/controllers/interaction_controller.js +981 -0
  207. package/build/src/host/controllers/pat_introspection_controller.d.ts +22 -0
  208. package/build/src/host/controllers/pat_introspection_controller.js +46 -0
  209. package/build/src/host/controllers/registration_controller.d.ts +18 -0
  210. package/build/src/host/controllers/registration_controller.js +382 -0
  211. package/build/src/host/controllers/social_controller.d.ts +8 -0
  212. package/build/src/host/controllers/social_controller.js +89 -0
  213. package/build/src/host/csrf.d.ts +29 -0
  214. package/build/src/host/csrf.js +14 -0
  215. package/build/src/host/default_mailer.d.ts +112 -0
  216. package/build/src/host/default_mailer.js +417 -0
  217. package/build/src/host/durable/account_deletion_workflow.d.ts +48 -0
  218. package/build/src/host/durable/account_deletion_workflow.js +86 -0
  219. package/build/src/host/durable/account_export_workflow.d.ts +68 -0
  220. package/build/src/host/durable/account_export_workflow.js +93 -0
  221. package/build/src/host/durable/index.d.ts +68 -0
  222. package/build/src/host/durable/index.js +77 -0
  223. package/build/src/host/email_templates.d.ts +39 -0
  224. package/build/src/host/email_templates.js +69 -0
  225. package/build/src/host/geo.d.ts +22 -0
  226. package/build/src/host/geo.js +39 -0
  227. package/build/src/host/i18n.d.ts +1416 -0
  228. package/build/src/host/i18n.js +1583 -0
  229. package/build/src/host/impersonation.d.ts +25 -0
  230. package/build/src/host/impersonation.js +31 -0
  231. package/build/src/host/key_rotation.d.ts +14 -0
  232. package/build/src/host/key_rotation.js +27 -0
  233. package/build/src/host/key_rotation_actions.d.ts +42 -0
  234. package/build/src/host/key_rotation_actions.js +27 -0
  235. package/build/src/host/login_attempt.d.ts +98 -0
  236. package/build/src/host/login_attempt.js +211 -0
  237. package/build/src/host/login_notify.d.ts +27 -0
  238. package/build/src/host/login_notify.js +142 -0
  239. package/build/src/host/middleware/account_auth.d.ts +7 -0
  240. package/build/src/host/middleware/account_auth.js +11 -0
  241. package/build/src/host/otp_lockout.d.ts +103 -0
  242. package/build/src/host/otp_lockout.js +221 -0
  243. package/build/src/host/rate_limit.d.ts +39 -0
  244. package/build/src/host/rate_limit.js +94 -0
  245. package/build/src/host/register_auth_host.d.ts +97 -0
  246. package/build/src/host/register_auth_host.js +466 -0
  247. package/build/src/host/renderers/edge_renderer.d.ts +12 -0
  248. package/build/src/host/renderers/edge_renderer.js +38 -0
  249. package/build/src/host/renderers/inertia_renderer.d.ts +70 -0
  250. package/build/src/host/renderers/inertia_renderer.js +54 -0
  251. package/build/src/host/runtime_settings.d.ts +181 -0
  252. package/build/src/host/runtime_settings.js +307 -0
  253. package/build/src/host/runtime_toggles.d.ts +807 -0
  254. package/build/src/host/runtime_toggles.js +784 -0
  255. package/build/src/host/security_notice_service.d.ts +36 -0
  256. package/build/src/host/security_notice_service.js +87 -0
  257. package/build/src/host/session_context.d.ts +23 -0
  258. package/build/src/host/session_context.js +89 -0
  259. package/build/src/host/sudo_mode.d.ts +56 -0
  260. package/build/src/host/sudo_mode.js +99 -0
  261. package/build/src/host/svg_chart.d.ts +15 -0
  262. package/build/src/host/svg_chart.js +45 -0
  263. package/build/src/host/trusted_device.d.ts +61 -0
  264. package/build/src/host/trusted_device.js +65 -0
  265. package/build/src/host/ui-dist/assets/index-CRWcmsex.js +137 -0
  266. package/build/src/host/ui-dist/assets/index-DTSmD4RU.css +1 -0
  267. package/build/src/host/ui-dist/index.html +17 -0
  268. package/build/src/host/user_agent.d.ts +18 -0
  269. package/build/src/host/user_agent.js +50 -0
  270. package/build/src/host/validators.d.ts +127 -0
  271. package/build/src/host/validators.js +53 -0
  272. package/build/src/keys/jwks_manager.d.ts +6 -0
  273. package/build/src/keys/jwks_manager.js +11 -0
  274. package/build/src/keys/keystore.d.ts +52 -0
  275. package/build/src/keys/keystore.js +68 -0
  276. package/build/src/keys/keystore_codec.d.ts +20 -0
  277. package/build/src/keys/keystore_codec.js +42 -0
  278. package/build/src/keys/keystore_crypto.d.ts +9 -0
  279. package/build/src/keys/keystore_crypto.js +27 -0
  280. package/build/src/keys/keystore_manager.d.ts +43 -0
  281. package/build/src/keys/keystore_manager.js +104 -0
  282. package/build/src/keys/keystore_vault.d.ts +113 -0
  283. package/build/src/keys/keystore_vault.js +265 -0
  284. package/build/src/mixins/json_column.d.ts +33 -0
  285. package/build/src/mixins/json_column.js +38 -0
  286. package/build/src/mixins/with_audit_log.d.ts +19 -0
  287. package/build/src/mixins/with_audit_log.js +39 -0
  288. package/build/src/mixins/with_auth_user.d.ts +24 -0
  289. package/build/src/mixins/with_auth_user.js +46 -0
  290. package/build/src/mixins/with_credentials.d.ts +20 -0
  291. package/build/src/mixins/with_credentials.js +29 -0
  292. package/build/src/mixins/with_mfa.d.ts +35 -0
  293. package/build/src/mixins/with_mfa.js +21 -0
  294. package/build/src/mixins/with_personal_access_token.d.ts +19 -0
  295. package/build/src/mixins/with_personal_access_token.js +42 -0
  296. package/build/src/mixins/with_provider_identity.d.ts +20 -0
  297. package/build/src/mixins/with_provider_identity.js +32 -0
  298. package/build/src/mixins/with_webauthn_credential.d.ts +37 -0
  299. package/build/src/mixins/with_webauthn_credential.js +46 -0
  300. package/build/src/observability/diagnostics_bridge.d.ts +6 -0
  301. package/build/src/observability/diagnostics_bridge.js +27 -0
  302. package/build/src/observability/metrics_controller.d.ts +5 -0
  303. package/build/src/observability/metrics_controller.js +24 -0
  304. package/build/src/observability/metrics_service.d.ts +2 -0
  305. package/build/src/observability/metrics_service.js +7 -0
  306. package/build/src/observability/otel_recorder.d.ts +10 -0
  307. package/build/src/observability/otel_recorder.js +59 -0
  308. package/build/src/observability/telescope/data_providers.d.ts +24 -0
  309. package/build/src/observability/telescope/data_providers.js +235 -0
  310. package/build/src/observability/telescope/extension.d.ts +29 -0
  311. package/build/src/observability/telescope/extension.js +167 -0
  312. package/build/src/observability/telescope/index.d.ts +8 -0
  313. package/build/src/observability/telescope/index.js +8 -0
  314. package/build/src/observability/wire_provider_events.d.ts +12 -0
  315. package/build/src/observability/wire_provider_events.js +30 -0
  316. package/build/src/password/common_passwords.d.ts +31 -0
  317. package/build/src/password/common_passwords.js +73 -0
  318. package/build/src/password/password_manager.d.ts +163 -0
  319. package/build/src/password/password_manager.js +191 -0
  320. package/build/src/password/policy.d.ts +71 -0
  321. package/build/src/password/policy.js +55 -0
  322. package/build/src/password/pwned.d.ts +36 -0
  323. package/build/src/password/pwned.js +52 -0
  324. package/build/src/pat/lucid_pat_store.d.ts +6 -0
  325. package/build/src/pat/lucid_pat_store.js +62 -0
  326. package/build/src/pat/pat_store.d.ts +31 -0
  327. package/build/src/pat/pat_store.js +1 -0
  328. package/build/src/pat/pat_tokens.d.ts +4 -0
  329. package/build/src/pat/pat_tokens.js +9 -0
  330. package/build/src/provider/build_provider.d.ts +45 -0
  331. package/build/src/provider/build_provider.js +219 -0
  332. package/build/src/provider/device_sources.d.ts +6 -0
  333. package/build/src/provider/device_sources.js +65 -0
  334. package/build/src/provider/interaction_actions.d.ts +36 -0
  335. package/build/src/provider/interaction_actions.js +55 -0
  336. package/build/src/provider/key_rotation_scheduler.d.ts +28 -0
  337. package/build/src/provider/key_rotation_scheduler.js +40 -0
  338. package/build/src/provider/keystore_reload.d.ts +21 -0
  339. package/build/src/provider/keystore_reload.js +39 -0
  340. package/build/src/provider/logout_sources.d.ts +13 -0
  341. package/build/src/provider/logout_sources.js +64 -0
  342. package/build/src/provider/oidc_service.d.ts +81 -0
  343. package/build/src/provider/oidc_service.js +254 -0
  344. package/build/src/provider/single_flight_lock.d.ts +18 -0
  345. package/build/src/provider/single_flight_lock.js +31 -0
  346. package/build/src/provider/token_exchange.d.ts +21 -0
  347. package/build/src/provider/token_exchange.js +124 -0
  348. package/build/src/register_routes.d.ts +16 -0
  349. package/build/src/register_routes.js +21 -0
  350. package/build/src/schema/ensure.d.ts +41 -0
  351. package/build/src/schema/ensure.js +262 -0
  352. package/build/stubs/config/authkit.stub +20 -0
  353. package/build/stubs/config/authkit_react.stub +52 -0
  354. package/build/stubs/main.d.ts +1 -0
  355. package/build/stubs/main.js +2 -0
  356. package/build/stubs/models/auth_user.stub +22 -0
  357. package/build/stubs/ui/edge/views/consent.edge +13 -0
  358. package/build/stubs/ui/edge/views/login.edge +19 -0
  359. package/build/stubs/ui/react/components/auth_shell.tsx +67 -0
  360. package/build/stubs/ui/react/pages/account/login.tsx +56 -0
  361. package/build/stubs/ui/react/pages/account/mfa.tsx +132 -0
  362. package/build/stubs/ui/react/pages/account/tokens.tsx +88 -0
  363. package/build/stubs/ui/react/pages/consent.tsx +39 -0
  364. package/build/stubs/ui/react/pages/forgot.tsx +44 -0
  365. package/build/stubs/ui/react/pages/login.tsx +171 -0
  366. package/build/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
  367. package/build/stubs/ui/react/pages/reset.tsx +58 -0
  368. package/build/stubs/ui/react/pages/signup.tsx +78 -0
  369. package/build/stubs/ui/react/pages/verify-email.tsx +24 -0
  370. package/build/types.d.ts +7 -0
  371. package/build/types.js +1 -0
  372. package/package.json +147 -0
  373. package/stubs/config/authkit.stub +20 -0
  374. package/stubs/config/authkit_react.stub +52 -0
  375. package/stubs/main.ts +2 -0
  376. package/stubs/models/auth_user.stub +22 -0
  377. package/stubs/ui/edge/views/consent.edge +13 -0
  378. package/stubs/ui/edge/views/login.edge +19 -0
  379. package/stubs/ui/react/components/auth_shell.tsx +67 -0
  380. package/stubs/ui/react/pages/account/login.tsx +56 -0
  381. package/stubs/ui/react/pages/account/mfa.tsx +132 -0
  382. package/stubs/ui/react/pages/account/tokens.tsx +88 -0
  383. package/stubs/ui/react/pages/consent.tsx +39 -0
  384. package/stubs/ui/react/pages/forgot.tsx +44 -0
  385. package/stubs/ui/react/pages/login.tsx +171 -0
  386. package/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
  387. package/stubs/ui/react/pages/reset.tsx +58 -0
  388. package/stubs/ui/react/pages/signup.tsx +78 -0
  389. package/stubs/ui/react/pages/verify-email.tsx +24 -0
@@ -0,0 +1,189 @@
1
+ import '../augmentations.js';
2
+ import { AdminOrgsService } from './admin_orgs_service.js';
3
+ import { orgDto, orgDetailDto, orgInvitationDto, apiError } from './dto.js';
4
+ import { resolveRuntimeSettings } from '../runtime_settings.js';
5
+ import { orgCreateValidator, orgUpdateValidator, orgAddMemberValidator, orgMemberRoleValidator, orgInvitationValidator, } from '../admin_validators.js';
6
+ /** Lê a config + monta o actor `admin-api` para auditoria. */
7
+ async function ctxBits(ctx) {
8
+ const service = await ctx.containerResolver.make('authkit.server');
9
+ const cfg = service.config;
10
+ const actor = { actorId: null, ip: ctx.request.ip?.() ?? null, source: 'admin-api' };
11
+ return { service, cfg, actor };
12
+ }
13
+ /** Helper: 404 JSON quando organizations não é suportado. */
14
+ function notSupported(ctx) {
15
+ return ctx.response.notFound(apiError('capability_unsupported', 'Organizations não é suportado nesta instalação.'));
16
+ }
17
+ /**
18
+ * CRUD de organizações da Admin REST API.
19
+ * Todas as rotas ficam sob `/api/authkit/v1/organizations`.
20
+ */
21
+ export default class ApiOrgsController {
22
+ /** GET /organizations — lista todas as orgs com contagem de membros. */
23
+ async index(ctx) {
24
+ const { cfg } = await ctxBits(ctx);
25
+ const svc = new AdminOrgsService(cfg);
26
+ const result = await svc.listOrgs();
27
+ if (!Array.isArray(result)) {
28
+ if (result.reason === 'not_supported')
29
+ return notSupported(ctx);
30
+ }
31
+ const orgs = result;
32
+ if (!Array.isArray(orgs))
33
+ return notSupported(ctx);
34
+ return { data: orgs.map(orgDto) };
35
+ }
36
+ /** POST /organizations — cria uma org. Body: { name, slug, ownerAccountId, logoUrl? } */
37
+ async store(ctx) {
38
+ const { cfg, actor } = await ctxBits(ctx);
39
+ const svc = new AdminOrgsService(cfg);
40
+ const { name, slug, ownerAccountId, logoUrl } = await ctx.request.validateUsing(orgCreateValidator);
41
+ const result = await svc.createOrg({ name, slug, logoUrl: logoUrl ?? null, ownerAccountId }, actor);
42
+ if ('ok' in result && result.ok === false) {
43
+ if (result.reason === 'not_supported')
44
+ return notSupported(ctx);
45
+ return ctx.response.conflict(apiError('slug_taken', 'Já existe uma org com este slug.'));
46
+ }
47
+ ctx.response.status(201);
48
+ return orgDto(result);
49
+ }
50
+ /** GET /organizations/:id — obtém uma org com membros e convites. */
51
+ async show(ctx) {
52
+ const { cfg } = await ctxBits(ctx);
53
+ const svc = new AdminOrgsService(cfg);
54
+ const id = ctx.request.param('id');
55
+ const result = await svc.getOrg(id);
56
+ if ('ok' in result && result.ok === false) {
57
+ if (result.reason === 'not_supported')
58
+ return notSupported(ctx);
59
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
60
+ }
61
+ return orgDetailDto(result);
62
+ }
63
+ /** PATCH /organizations/:id — atualiza nome e/ou logo. */
64
+ async update(ctx) {
65
+ const { cfg, actor } = await ctxBits(ctx);
66
+ const svc = new AdminOrgsService(cfg);
67
+ const id = ctx.request.param('id');
68
+ const { name, logoUrl } = await ctx.request.validateUsing(orgUpdateValidator);
69
+ const patch = {};
70
+ if (name !== undefined)
71
+ patch.name = name;
72
+ if (logoUrl !== undefined)
73
+ patch.logoUrl = logoUrl;
74
+ const result = await svc.updateOrg(id, patch, actor);
75
+ if ('ok' in result && result.ok === false) {
76
+ if (result.reason === 'not_supported')
77
+ return notSupported(ctx);
78
+ if (result.reason === 'not_found')
79
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
80
+ return ctx.response.conflict(apiError('slug_taken', 'Já existe uma org com este slug.'));
81
+ }
82
+ return orgDto(result);
83
+ }
84
+ /** DELETE /organizations/:id */
85
+ async destroy(ctx) {
86
+ const { cfg, actor } = await ctxBits(ctx);
87
+ const svc = new AdminOrgsService(cfg);
88
+ const id = ctx.request.param('id');
89
+ const result = await svc.deleteOrg(id, actor);
90
+ if (!result.ok) {
91
+ if (result.reason === 'not_supported')
92
+ return notSupported(ctx);
93
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
94
+ }
95
+ return { id, deleted: true };
96
+ }
97
+ /** POST /organizations/:id/members — adiciona membro. Body: { accountId, role } */
98
+ async addMember(ctx) {
99
+ const { cfg, actor } = await ctxBits(ctx);
100
+ const svc = new AdminOrgsService(cfg);
101
+ const orgId = ctx.request.param('id');
102
+ const { accountId, role } = await ctx.request.validateUsing(orgAddMemberValidator);
103
+ const result = await svc.addMember(orgId, { accountId, role: role ?? 'member' }, actor, await resolveRuntimeSettings(ctx));
104
+ if (!result.ok) {
105
+ if (result.reason === 'not_supported')
106
+ return notSupported(ctx);
107
+ if (result.reason === 'not_found')
108
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
109
+ if (result.reason === 'invalid_role')
110
+ return ctx.response.unprocessableEntity(apiError('invalid_role', 'Role inválida — fora do catálogo da organização.'));
111
+ return ctx.response.notFound(apiError('account_not_found', 'Conta não encontrada.'));
112
+ }
113
+ ctx.response.status(201);
114
+ return { orgId, accountId, role, added: true };
115
+ }
116
+ /** DELETE /organizations/:id/members/:accountId */
117
+ async removeMember(ctx) {
118
+ const { cfg, actor } = await ctxBits(ctx);
119
+ const svc = new AdminOrgsService(cfg);
120
+ const orgId = ctx.request.param('id');
121
+ const accountId = ctx.request.param('accountId');
122
+ const result = await svc.removeMember(orgId, accountId, actor);
123
+ if (!result.ok) {
124
+ if (result.reason === 'not_supported')
125
+ return notSupported(ctx);
126
+ if (result.reason === 'not_found')
127
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
128
+ if (result.reason === 'last_owner')
129
+ return ctx.response.conflict(apiError('last_owner', 'Não é possível remover o último owner.'));
130
+ return ctx.response.notFound(apiError('member_not_found', 'Membro não encontrado.'));
131
+ }
132
+ return { orgId, accountId, removed: true };
133
+ }
134
+ /** PATCH /organizations/:id/members/:accountId — troca o papel. Body: { role } */
135
+ async updateMemberRole(ctx) {
136
+ const { cfg, actor } = await ctxBits(ctx);
137
+ const svc = new AdminOrgsService(cfg);
138
+ const orgId = ctx.request.param('id');
139
+ const accountId = ctx.request.param('accountId');
140
+ const { role } = await ctx.request.validateUsing(orgMemberRoleValidator);
141
+ const result = await svc.updateMemberRole(orgId, accountId, role, actor, await resolveRuntimeSettings(ctx));
142
+ if (!result.ok) {
143
+ if (result.reason === 'not_supported')
144
+ return notSupported(ctx);
145
+ if (result.reason === 'not_found')
146
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
147
+ if (result.reason === 'invalid_role')
148
+ return ctx.response.unprocessableEntity(apiError('invalid_role', 'Role inválida — fora do catálogo da organização.'));
149
+ if (result.reason === 'last_owner')
150
+ return ctx.response.conflict(apiError('last_owner', 'Não é possível rebaixar o último owner.'));
151
+ return ctx.response.notFound(apiError('member_not_found', 'Membro não encontrado.'));
152
+ }
153
+ return { orgId, accountId, role, updated: true };
154
+ }
155
+ /** POST /organizations/:id/invitations — cria convite. Body: { email, role } */
156
+ async createInvitation(ctx) {
157
+ const { cfg, actor } = await ctxBits(ctx);
158
+ const svc = new AdminOrgsService(cfg);
159
+ const orgId = ctx.request.param('id');
160
+ const { email, role } = await ctx.request.validateUsing(orgInvitationValidator);
161
+ const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
162
+ const result = await svc.createInvitation(orgId, { email, role: role ?? 'member' }, actor, origin, await resolveRuntimeSettings(ctx));
163
+ if (!result.ok) {
164
+ if (result.reason === 'not_supported')
165
+ return notSupported(ctx);
166
+ if (result.reason === 'invalid_role')
167
+ return ctx.response.unprocessableEntity(apiError('invalid_role', 'Role inválida — fora do catálogo da organização.'));
168
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
169
+ }
170
+ ctx.response.status(201);
171
+ return orgInvitationDto(result.invitation);
172
+ }
173
+ /** DELETE /organizations/:id/invitations/:invitationId */
174
+ async revokeInvitation(ctx) {
175
+ const { cfg, actor } = await ctxBits(ctx);
176
+ const svc = new AdminOrgsService(cfg);
177
+ const orgId = ctx.request.param('id');
178
+ const invitationId = ctx.request.param('invitationId');
179
+ const result = await svc.revokeInvitation(orgId, invitationId, actor);
180
+ if (!result.ok) {
181
+ if (result.reason === 'not_supported')
182
+ return notSupported(ctx);
183
+ if (result.reason === 'not_found')
184
+ return ctx.response.notFound(apiError('not_found', 'Organização não encontrada.'));
185
+ return ctx.response.notFound(apiError('invitation_not_found', 'Convite não encontrado.'));
186
+ }
187
+ return { orgId, invitationId, revoked: true };
188
+ }
189
+ }
@@ -0,0 +1,55 @@
1
+ import '../augmentations.js';
2
+ import type { HttpContext } from '@adonisjs/core/http';
3
+ /**
4
+ * CRUD de runtime settings da Admin REST API.
5
+ * Todas as rotas ficam sob `/api/authkit/v1/settings`.
6
+ * Retorna 404 (`capability_unsupported`) quando a tabela `auth_settings` não existe.
7
+ *
8
+ * Suporte a escopo por org via query param `?organizationId=`:
9
+ * GET /settings?organizationId={id} → lista settings da org
10
+ * PUT /settings/:key?organizationId= → upsert no escopo da org
11
+ * DEL /settings/:key?organizationId= → remove no escopo da org
12
+ *
13
+ * Keys org-scopáveis: `organizations_policy`, `roles_catalog`.
14
+ */
15
+ export default class ApiSettingsController {
16
+ /** GET /settings — lista settings (global por padrão, ou da org via ?organizationId=). */
17
+ index(ctx: HttpContext): Promise<void | {
18
+ data: {
19
+ lockedBy?: "config" | undefined;
20
+ key: string;
21
+ organizationId: string | null;
22
+ value: unknown;
23
+ updatedAt: string | null;
24
+ updatedBy: string | null;
25
+ locked: boolean;
26
+ }[];
27
+ locked: string[];
28
+ }>;
29
+ /** GET /settings/:key — obtém uma setting por key (global ou org). */
30
+ show(ctx: HttpContext): Promise<void | {
31
+ lockedBy?: "config" | undefined;
32
+ key: string;
33
+ organizationId: string | null;
34
+ value: unknown;
35
+ updatedAt: string | null;
36
+ updatedBy: string | null;
37
+ locked: boolean;
38
+ }>;
39
+ /** PUT /settings/:key — cria ou atualiza uma setting. Body: { value: any } */
40
+ upsert(ctx: HttpContext): Promise<void | {
41
+ lockedBy?: "config" | undefined;
42
+ key: string;
43
+ organizationId: string | null;
44
+ value: unknown;
45
+ updatedAt: string | null;
46
+ updatedBy: string | null;
47
+ locked: boolean;
48
+ }>;
49
+ /** DELETE /settings/:key */
50
+ destroy(ctx: HttpContext): Promise<void | {
51
+ key: string;
52
+ organizationId: string | null;
53
+ deleted: boolean;
54
+ }>;
55
+ }
@@ -0,0 +1,134 @@
1
+ import '../augmentations.js';
2
+ import { resolveRuntimeSettings } from '../runtime_settings.js';
3
+ import { settingDto, apiError } from './dto.js';
4
+ import { isSettingLocked, lockedSettingKeys, SettingLockedError } from '../config_locks.js';
5
+ /** 423 Locked: a setting foi travada via defineConfig (não editável em runtime). */
6
+ function lockedResponse(ctx, err) {
7
+ return ctx.response
8
+ .status(423)
9
+ .send(apiError('setting_locked', err.message, { key: err.key, lockedBy: 'config' }));
10
+ }
11
+ /** Helper: 404 JSON when settings capability is not available (table absent). */
12
+ function notSupported(ctx) {
13
+ return ctx.response.notFound(apiError('capability_unsupported', 'Runtime settings não é suportado nesta instalação (tabela auth_settings ausente).'));
14
+ }
15
+ /** Extrai organizationId do query string. null = global. */
16
+ function resolveOrgId(ctx) {
17
+ const qs = ctx.request.qs();
18
+ if ('organizationId' in qs) {
19
+ const v = qs['organizationId'];
20
+ return v && v.trim() ? v.trim() : null;
21
+ }
22
+ return null;
23
+ }
24
+ /**
25
+ * CRUD de runtime settings da Admin REST API.
26
+ * Todas as rotas ficam sob `/api/authkit/v1/settings`.
27
+ * Retorna 404 (`capability_unsupported`) quando a tabela `auth_settings` não existe.
28
+ *
29
+ * Suporte a escopo por org via query param `?organizationId=`:
30
+ * GET /settings?organizationId={id} → lista settings da org
31
+ * PUT /settings/:key?organizationId= → upsert no escopo da org
32
+ * DEL /settings/:key?organizationId= → remove no escopo da org
33
+ *
34
+ * Keys org-scopáveis: `organizations_policy`, `roles_catalog`.
35
+ */
36
+ export default class ApiSettingsController {
37
+ /** GET /settings — lista settings (global por padrão, ou da org via ?organizationId=). */
38
+ async index(ctx) {
39
+ const svc = await resolveRuntimeSettings(ctx);
40
+ if (!svc)
41
+ return notSupported(ctx);
42
+ // Probe table presence before returning list.
43
+ const tablePresent = await svc.isTablePresent();
44
+ if (!tablePresent)
45
+ return notSupported(ctx);
46
+ const orgId = resolveOrgId(ctx);
47
+ const rows = await svc.listSettings(orgId);
48
+ // `locked` lista TODAS as keys travadas por config (mesmo as sem row em auth_settings,
49
+ // pois config-only não persiste row). A UI usa isto p/ desabilitar + avisar.
50
+ return { data: rows.map(settingDto), locked: lockedSettingKeys() };
51
+ }
52
+ /** GET /settings/:key — obtém uma setting por key (global ou org). */
53
+ async show(ctx) {
54
+ const key = ctx.request.param('key');
55
+ const svc = await resolveRuntimeSettings(ctx);
56
+ if (!svc)
57
+ return notSupported(ctx);
58
+ const tablePresent = await svc.isTablePresent();
59
+ if (!tablePresent)
60
+ return notSupported(ctx);
61
+ const orgId = resolveOrgId(ctx);
62
+ const value = await svc.getSetting(key, orgId);
63
+ if (value === null) {
64
+ return ctx.response.notFound(apiError('not_found', 'Setting não encontrada.'));
65
+ }
66
+ return settingDto({ key, organizationId: orgId, value, updatedAt: null, updatedBy: null });
67
+ }
68
+ /** PUT /settings/:key — cria ou atualiza uma setting. Body: { value: any } */
69
+ async upsert(ctx) {
70
+ const key = ctx.request.param('key');
71
+ const body = ctx.request.body();
72
+ if (!body || !('value' in body)) {
73
+ return ctx.response.badRequest(apiError('invalid_request', 'O campo `value` é obrigatório.'));
74
+ }
75
+ const svc = await resolveRuntimeSettings(ctx);
76
+ if (!svc)
77
+ return notSupported(ctx);
78
+ const tablePresent = await svc.isTablePresent();
79
+ if (!tablePresent)
80
+ return notSupported(ctx);
81
+ // Travada via defineConfig → 423 antes de qualquer escrita.
82
+ if (isSettingLocked(key))
83
+ return lockedResponse(ctx, new SettingLockedError(key));
84
+ const orgId = resolveOrgId(ctx);
85
+ const service = await ctx.containerResolver.make('authkit.server');
86
+ const cfg = service.config;
87
+ try {
88
+ await svc.setSetting(key, body.value, null, orgId);
89
+ }
90
+ catch (err) {
91
+ if (err instanceof SettingLockedError)
92
+ return lockedResponse(ctx, err);
93
+ throw err;
94
+ }
95
+ await cfg.audit?.record({
96
+ type: 'settings.updated',
97
+ actorId: null,
98
+ ip: ctx.request.ip?.() ?? null,
99
+ metadata: { key, value: body.value, organizationId: orgId },
100
+ });
101
+ const saved = await svc.getSetting(key, orgId);
102
+ return settingDto({ key, organizationId: orgId, value: saved, updatedAt: new Date(), updatedBy: null });
103
+ }
104
+ /** DELETE /settings/:key */
105
+ async destroy(ctx) {
106
+ const key = ctx.request.param('key');
107
+ const svc = await resolveRuntimeSettings(ctx);
108
+ if (!svc)
109
+ return notSupported(ctx);
110
+ const tablePresent = await svc.isTablePresent();
111
+ if (!tablePresent)
112
+ return notSupported(ctx);
113
+ if (isSettingLocked(key))
114
+ return lockedResponse(ctx, new SettingLockedError(key));
115
+ const orgId = resolveOrgId(ctx);
116
+ const service = await ctx.containerResolver.make('authkit.server');
117
+ const cfg = service.config;
118
+ try {
119
+ await svc.deleteSetting(key, orgId);
120
+ }
121
+ catch (err) {
122
+ if (err instanceof SettingLockedError)
123
+ return lockedResponse(ctx, err);
124
+ throw err;
125
+ }
126
+ await cfg.audit?.record({
127
+ type: 'settings.updated',
128
+ actorId: null,
129
+ ip: ctx.request.ip?.() ?? null,
130
+ metadata: { key, action: 'deleted', organizationId: orgId },
131
+ });
132
+ return { key, organizationId: orgId, deleted: true };
133
+ }
134
+ }
@@ -0,0 +1,108 @@
1
+ import "../augmentations.js";
2
+ import type { HttpContext } from "@adonisjs/core/http";
3
+ /**
4
+ * Recurso de usuários da Admin REST API (R6). JSON puro (camelCase), erros no
5
+ * envelope `{ error: { code, message } }`. Toda escrita audita com `actor: 'admin-api'`.
6
+ */
7
+ export default class ApiUsersController {
8
+ #private;
9
+ /** GET /users — listagem paginada com busca por e-mail. */
10
+ index(ctx: HttpContext): Promise<{
11
+ data: any[];
12
+ total: any;
13
+ page: number;
14
+ limit: number;
15
+ }>;
16
+ /** GET /users/:id */
17
+ show(ctx: HttpContext): Promise<void | {
18
+ id: string;
19
+ email: string;
20
+ name: string | null;
21
+ avatarUrl: string | null;
22
+ globalRoles: string[];
23
+ disabled: boolean;
24
+ }>;
25
+ /** POST /users — { email, name?, password? | invite?:true }. */
26
+ store(ctx: HttpContext): Promise<void | {
27
+ invited: boolean;
28
+ id: string;
29
+ email: string;
30
+ name: string | null;
31
+ avatarUrl: string | null;
32
+ globalRoles: string[];
33
+ disabled: boolean;
34
+ }>;
35
+ /** PATCH /users/:id — { globalRoles?, name?, avatarUrl? }. */
36
+ update(ctx: HttpContext): Promise<void | {
37
+ id: string;
38
+ email: string;
39
+ name: string | null;
40
+ avatarUrl: string | null;
41
+ globalRoles: string[];
42
+ disabled: boolean;
43
+ }>;
44
+ /** DELETE /users/:id — deleção completa (cascade) da conta. */
45
+ destroy(ctx: HttpContext): Promise<void | {
46
+ id: any;
47
+ deleted: boolean;
48
+ enqueued: boolean;
49
+ runId: string;
50
+ } | {
51
+ ok: boolean;
52
+ sessions: number;
53
+ grants: number;
54
+ accessTokens: number;
55
+ refreshTokens: number;
56
+ pats: number;
57
+ passkeys: number;
58
+ providerIdentities: number;
59
+ auditAnonymized: number;
60
+ avatarDeleted: boolean;
61
+ orgMemberships: number;
62
+ orgInvitations: number;
63
+ id: any;
64
+ deleted: boolean;
65
+ enqueued?: undefined;
66
+ runId?: undefined;
67
+ }>;
68
+ /** POST /users/:id/disable */
69
+ disable(ctx: HttpContext): Promise<void | {
70
+ id: any;
71
+ disabled: boolean;
72
+ }>;
73
+ /** POST /users/:id/enable */
74
+ enable(ctx: HttpContext): Promise<void | {
75
+ id: any;
76
+ disabled: boolean;
77
+ }>;
78
+ /** POST /users/:id/reset-password — envia o e-mail de reset. */
79
+ resetPassword(ctx: HttpContext): Promise<void | {
80
+ id: any;
81
+ sent: boolean;
82
+ }>;
83
+ /** GET /users/:id/sessions — sessões (enriquecidas com contexto) + grants ativos. */
84
+ sessions(ctx: HttpContext): Promise<{
85
+ canList: boolean;
86
+ sessions: {
87
+ id: string;
88
+ accountId: string;
89
+ email: string | null;
90
+ loginTs: number | null;
91
+ amr: string[];
92
+ userAgent: string | null;
93
+ browser: string | null;
94
+ os: string | null;
95
+ ip: string | null;
96
+ location: string | null;
97
+ }[];
98
+ grants: {
99
+ id: string;
100
+ accountId: string;
101
+ clientId: string | null;
102
+ accessTokens: number;
103
+ refreshTokens: number;
104
+ }[];
105
+ }>;
106
+ /** POST /users/:id/revoke-sessions — revoga todas as sessões/grants. */
107
+ revokeSessions(ctx: HttpContext): Promise<import("../admin_sessions_service.js").RevokeResult>;
108
+ }
@@ -0,0 +1,187 @@
1
+ import "../augmentations.js";
2
+ import { AdminUsersService } from "./admin_users_service.js";
3
+ import { AdminSessionsService } from "../admin_sessions_service.js";
4
+ import { enrichSessionsWithContext } from "../session_context.js";
5
+ import { resolveRuntimeSettings } from "../runtime_settings.js";
6
+ import { userDto, sessionDto, grantDto, apiError } from "./dto.js";
7
+ import { adminUserCreateValidator, adminUserUpdateValidator, } from "../admin_validators.js";
8
+ const PAGE_SIZE = 20;
9
+ /**
10
+ * Lê a config + monta o actor `admin-api` para auditoria. O `actorId` recebe o
11
+ * id NÃO-SENSÍVEL da API key que autenticou (anexado pelo `adminApiGuard` em
12
+ * `ctx.adminApiKeyId`) — assim a trilha REST registra QUAL key agiu (M9) sem
13
+ * vazar o segredo. `null` apenas se a guard não anexou (defensivo).
14
+ */
15
+ async function ctxBits(ctx) {
16
+ const service = await ctx.containerResolver.make("authkit.server");
17
+ const cfg = service.config;
18
+ const actor = {
19
+ actorId: ctx.adminApiKeyId ?? null,
20
+ ip: ctx.request.ip?.() ?? null,
21
+ source: "admin-api",
22
+ };
23
+ return { service, cfg, actor };
24
+ }
25
+ /**
26
+ * Recurso de usuários da Admin REST API (R6). JSON puro (camelCase), erros no
27
+ * envelope `{ error: { code, message } }`. Toda escrita audita com `actor: 'admin-api'`.
28
+ */
29
+ export default class ApiUsersController {
30
+ /** GET /users — listagem paginada com busca por e-mail. */
31
+ async index(ctx) {
32
+ const { cfg } = await ctxBits(ctx);
33
+ const search = ctx.request.input("search", "").trim();
34
+ const page = Math.max(1, Number.parseInt(ctx.request.input("page", "1"), 10) || 1);
35
+ const limit = Math.max(1, Math.min(100, Number.parseInt(ctx.request.input("limit", String(PAGE_SIZE)), 10) ||
36
+ PAGE_SIZE));
37
+ const result = await cfg.accountStore.listAccounts({ search, page, limit });
38
+ const users = new AdminUsersService(cfg);
39
+ const data = await Promise.all(result.data.map(async (u) => userDto(u, await users.isDisabled(u.id))));
40
+ return { data, total: result.total, page, limit };
41
+ }
42
+ /** GET /users/:id */
43
+ async show(ctx) {
44
+ const { cfg } = await ctxBits(ctx);
45
+ const id = ctx.request.param("id");
46
+ const account = await cfg.accountStore.findById(id);
47
+ if (!account)
48
+ return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
49
+ const disabled = await new AdminUsersService(cfg).isDisabled(id);
50
+ return userDto(account, disabled);
51
+ }
52
+ /** POST /users — { email, name?, password? | invite?:true }. */
53
+ async store(ctx) {
54
+ const { cfg, actor } = await ctxBits(ctx);
55
+ const { email, name, password, invite } = await ctx.request.validateUsing(adminUserCreateValidator);
56
+ const users = new AdminUsersService(cfg);
57
+ const result = await users.create(ctx, {
58
+ email,
59
+ name: name ?? null,
60
+ password: password ?? null,
61
+ invite: invite ?? false,
62
+ }, actor);
63
+ if (!result.ok) {
64
+ if (result.reason === "password_policy") {
65
+ return ctx.response.badRequest(apiError("password_policy", cfg.messages[result.messageKey] ?? result.messageKey));
66
+ }
67
+ return ctx.response.conflict(apiError("email_taken", "Já existe uma conta com este e-mail."));
68
+ }
69
+ ctx.response.status(201);
70
+ return { ...userDto(result.account), invited: result.invited };
71
+ }
72
+ /** PATCH /users/:id — { globalRoles?, name?, avatarUrl? }. */
73
+ async update(ctx) {
74
+ const { cfg, actor } = await ctxBits(ctx);
75
+ const id = ctx.request.param("id");
76
+ const account = await cfg.accountStore.findById(id);
77
+ if (!account)
78
+ return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
79
+ const users = new AdminUsersService(cfg);
80
+ const { globalRoles: roles, name, avatarUrl, } = await ctx.request.validateUsing(adminUserUpdateValidator);
81
+ if (Array.isArray(roles)) {
82
+ const normalized = Array.from(new Set(roles.map((r) => r.trim()).filter(Boolean)));
83
+ // Proteções de escalonamento/lockout: último admin + auto-rebaixamento.
84
+ // O actorId vem do id da API key (M9); self-demote só aplica se identificável.
85
+ const guard = await users.guardGlobalRolesChange(id, normalized, actor.actorId);
86
+ if (guard === "last_admin") {
87
+ return ctx.response.conflict(apiError("last_admin", "Não é possível remover a última conta com a role de administrador."));
88
+ }
89
+ if (guard === "cannot_self_demote") {
90
+ return ctx.response.conflict(apiError("cannot_self_demote", "Você não pode remover a sua própria role de administrador."));
91
+ }
92
+ // Valida contra o catálogo (mesmo caminho do console) — roles fora do
93
+ // catálogo (e que o usuário não tinha) → 422.
94
+ const settings = await resolveRuntimeSettings(ctx);
95
+ const errorKey = await users.setGlobalRolesValidated(id, normalized, settings);
96
+ if (errorKey) {
97
+ return ctx.response
98
+ .status(422)
99
+ .send(apiError("invalid_role", cfg.messages[errorKey] ?? errorKey));
100
+ }
101
+ }
102
+ if (name !== undefined || avatarUrl !== undefined) {
103
+ const patch = {};
104
+ if (name !== undefined)
105
+ patch.name = name;
106
+ if (avatarUrl !== undefined)
107
+ patch.avatarUrl = avatarUrl;
108
+ await users.updateProfile(id, patch);
109
+ }
110
+ const updated = await cfg.accountStore.findById(id);
111
+ return userDto(updated, await users.isDisabled(id));
112
+ }
113
+ /** DELETE /users/:id — deleção completa (cascade) da conta. */
114
+ async destroy(ctx) {
115
+ const { service, cfg, actor } = await ctxBits(ctx);
116
+ const id = ctx.request.param("id");
117
+ // OPT-IN durável: passa o enqueue (cascade async); senão delete() roda síncrono.
118
+ const enqueue = cfg.accountLifecycle?.durable
119
+ ? (await import("../durable/index.js")).enqueueDeletionVia(ctx.containerResolver)
120
+ : undefined;
121
+ const outcome = await new AdminUsersService(cfg).delete(service, id, actor, enqueue);
122
+ if (!outcome.ok) {
123
+ if (outcome.reason === "not_found") {
124
+ return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
125
+ }
126
+ return ctx.response.conflict(apiError("capability_unsupported", "O store de contas não suporta deletar usuários."));
127
+ }
128
+ // Modo durável: a deleção foi ENFILEIRADA (cascade async) — responde 202-style.
129
+ if ("enqueued" in outcome) {
130
+ return { id, deleted: true, enqueued: true, runId: outcome.runId };
131
+ }
132
+ return { id, deleted: true, ...outcome.result };
133
+ }
134
+ /** POST /users/:id/disable */
135
+ async disable(ctx) {
136
+ return this.#setStatus(ctx, true);
137
+ }
138
+ /** POST /users/:id/enable */
139
+ async enable(ctx) {
140
+ return this.#setStatus(ctx, false);
141
+ }
142
+ async #setStatus(ctx, disable) {
143
+ const { cfg, actor } = await ctxBits(ctx);
144
+ const id = ctx.request.param("id");
145
+ const applied = await new AdminUsersService(cfg).setStatus(id, disable, actor);
146
+ if (!applied) {
147
+ return ctx.response.conflict(apiError("capability_unsupported", "O store de contas não suporta habilitar/desabilitar."));
148
+ }
149
+ return { id, disabled: disable };
150
+ }
151
+ /** POST /users/:id/reset-password — envia o e-mail de reset. */
152
+ async resetPassword(ctx) {
153
+ const { cfg, actor } = await ctxBits(ctx);
154
+ const id = ctx.request.param("id");
155
+ const account = await new AdminUsersService(cfg).resetPassword(ctx, id, actor);
156
+ if (!account)
157
+ return ctx.response.notFound(apiError("not_found", "Usuário não encontrado."));
158
+ return { id, sent: true };
159
+ }
160
+ /** GET /users/:id/sessions — sessões (enriquecidas com contexto) + grants ativos. */
161
+ async sessions(ctx) {
162
+ const { service, cfg } = await ctxBits(ctx);
163
+ const id = ctx.request.param("id");
164
+ const admin = new AdminSessionsService(service);
165
+ const sessions = await enrichSessionsWithContext(cfg, id, await admin.listSessions(id));
166
+ const grants = await admin.listGrants(id);
167
+ return {
168
+ canList: admin.canList,
169
+ sessions: sessions.map(sessionDto),
170
+ grants: grants.map(grantDto),
171
+ };
172
+ }
173
+ /** POST /users/:id/revoke-sessions — revoga todas as sessões/grants. */
174
+ async revokeSessions(ctx) {
175
+ const { service, cfg, actor } = await ctxBits(ctx);
176
+ const id = ctx.request.param("id");
177
+ const result = await new AdminSessionsService(service).revokeAll(id);
178
+ await cfg.audit?.record({
179
+ type: "session.revoked_all",
180
+ accountId: id,
181
+ actorId: actor.actorId,
182
+ ip: actor.ip,
183
+ metadata: { actor: actor.source, ...result },
184
+ });
185
+ return result;
186
+ }
187
+ }