@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,215 @@
1
+ <!doctype html>
2
+ <html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('account.security.page_title') }}</title>
3
+ @include('authkit::partials/styles')
4
+ </head>
5
+ <body class="min-h-screen bg-gray-100 p-4">
6
+ <div class="mx-auto max-w-2xl">
7
+ <div class="flex items-center justify-between py-6">
8
+ <div>
9
+ <div class="text-xs font-semibold uppercase tracking-widest text-gray-400">{{ t('common.brand_eyebrow') }}</div>
10
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('account.security.title') }}</h1>
11
+ @if(email)
12
+ <p class="mt-1 text-sm text-gray-500">{{ t('account.security.current_email', { email: email }) }}</p>
13
+ @end
14
+ </div>
15
+ <form method="POST" action="/account/logout">
16
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
17
+ <button type="submit" class="text-sm text-gray-500 hover:underline">{{ t('account.security.logout') }}</button>
18
+ </form>
19
+ </div>
20
+
21
+ <nav class="mb-6 flex gap-4 text-sm font-medium">
22
+ <a href="/account/tokens" class="text-gray-500 hover:underline">{{ t('account.tokens.title') }}</a>
23
+ <a href="/account/security" class="text-gray-900 underline">{{ t('account.security.title') }}</a>
24
+ <a href="/account/apps" class="text-gray-500 hover:underline">{{ t('account.apps.title') }}</a>
25
+ </nav>
26
+
27
+ @if(profileUpdated)
28
+ <div class="mb-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
29
+ <p class="text-sm font-medium text-emerald-900">{{ profileUpdated }}</p>
30
+ </div>
31
+ @end
32
+
33
+ @if(profileSupported)
34
+ <div class="mb-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
35
+ <h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.profile.section') }}</h2>
36
+ <p class="mb-4 text-xs text-gray-500">{{ t('account.profile.intro') }}</p>
37
+ <form method="POST" action="/account/security/profile" enctype="multipart/form-data" class="space-y-4">
38
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
39
+ @if(avatarUrl)
40
+ <div>
41
+ <img src="{{ avatarUrl }}" alt="avatar" class="h-16 w-16 rounded-full object-cover ring-1 ring-black/5" />
42
+ </div>
43
+ @end
44
+ <div>
45
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.profile.name_label') }}</label>
46
+ <input name="name" type="text" value="{{ name }}" maxlength="255"
47
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
48
+ </div>
49
+ @if(avatarUploadSupported)
50
+ <div>
51
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.profile.avatar_upload_label') }}</label>
52
+ <input name="avatar" type="file" accept="image/jpeg,image/png,image/webp"
53
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
54
+ <p class="mt-1 text-xs text-gray-500">{{ t('account.profile.avatar_upload_hint') }}</p>
55
+ </div>
56
+ @end
57
+ <div>
58
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.profile.avatar_label') }}</label>
59
+ <input name="avatarUrl" type="url" value="{{ avatarUrl }}"
60
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
61
+ </div>
62
+ <button type="submit" class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white">
63
+ {{ t('account.profile.submit') }}
64
+ </button>
65
+ </form>
66
+ </div>
67
+ @end
68
+
69
+ @if(!supported)
70
+ <div class="rounded-xl bg-white p-6 text-sm text-gray-500 shadow-sm ring-1 ring-black/5">
71
+ {{ t('account.security.not_supported') }}
72
+ </div>
73
+ @else
74
+ @if(error)
75
+ <div class="mb-6 rounded-lg border border-red-300 bg-red-50 p-4">
76
+ <p class="text-sm font-medium text-red-900">{{ error }}</p>
77
+ </div>
78
+ @end
79
+ @if(passwordChanged)
80
+ <div class="mb-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
81
+ <p class="text-sm font-medium text-emerald-900">{{ passwordChanged }}</p>
82
+ </div>
83
+ @end
84
+ @if(emailChangeRequested)
85
+ <div class="mb-6 rounded-lg border border-blue-300 bg-blue-50 p-4">
86
+ <p class="text-sm font-medium text-blue-900">{{ emailChangeRequested }}</p>
87
+ </div>
88
+ @end
89
+
90
+ <div class="mb-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
91
+ <h2 class="mb-4 text-sm font-semibold text-gray-900">{{ t('account.security.password_section') }}</h2>
92
+ <form method="POST" action="/account/security/password" class="space-y-4">
93
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
94
+ <div>
95
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.current_password_label') }}</label>
96
+ <input name="currentPassword" type="password" required
97
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
98
+ </div>
99
+ <div>
100
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.new_password_label') }}</label>
101
+ <input name="newPassword" type="password" required minlength="8"
102
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
103
+ </div>
104
+ <button type="submit" class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white">
105
+ {{ t('account.security.change_password_submit') }}
106
+ </button>
107
+ </form>
108
+ </div>
109
+
110
+ <div class="rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
111
+ <h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.security.email_section') }}</h2>
112
+ <p class="mb-4 text-xs text-gray-500">{{ t('account.security.email_intro') }}</p>
113
+ <form method="POST" action="/account/security/email" class="space-y-4">
114
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
115
+ <div>
116
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.new_email_label') }}</label>
117
+ <input name="newEmail" type="email" required
118
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
119
+ </div>
120
+ <div>
121
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.security.email_password_label') }}</label>
122
+ <input name="currentPassword" type="password" required
123
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
124
+ </div>
125
+ <button type="submit" class="rounded-lg bg-gray-900 px-4 py-2 text-sm font-semibold text-white">
126
+ {{ t('account.security.change_email_submit') }}
127
+ </button>
128
+ </form>
129
+ </div>
130
+ @end
131
+
132
+ @if(sessionsSupported)
133
+ <div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
134
+ <h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.security.sessions_section') }}</h2>
135
+ <p class="mb-4 text-xs text-gray-500">{{ t('account.security.sessions_intro') }}</p>
136
+ @if(sessions.length === 0)
137
+ <p class="text-sm text-gray-500">{{ t('account.security.sessions_empty') }}</p>
138
+ @else
139
+ <ul class="divide-y divide-gray-100">
140
+ @each(session in sessions)
141
+ <li class="py-3">
142
+ @if(session.browser || session.os)
143
+ <p class="text-sm font-medium text-gray-900">{{ t('admin.sessions.session_device', { browser: session.browser || '—', os: session.os || '—' }) }}</p>
144
+ @end
145
+ @if(session.ip)
146
+ <p class="text-xs text-gray-500">{{ session.location ? t('admin.sessions.session_ip_geo', { ip: session.ip, location: session.location }) : t('admin.sessions.session_ip', { ip: session.ip }) }}</p>
147
+ @end
148
+ @if(session.loginTs)
149
+ <p class="text-xs text-gray-400">{{ t('admin.sessions.session_login_ts', { date: session.loginTs }) }}</p>
150
+ @end
151
+ </li>
152
+ @end
153
+ </ul>
154
+ @end
155
+ </div>
156
+ @end
157
+
158
+ @if(trustedDevicesEnabled)
159
+ @if(trustedDevicesRevoked)
160
+ <div class="mt-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
161
+ <p class="text-sm font-medium text-emerald-900">{{ trustedDevicesRevoked }}</p>
162
+ </div>
163
+ @end
164
+ <div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
165
+ <h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.security.trusted_devices_section') }}</h2>
166
+ <p class="mb-4 text-xs text-gray-500">{{ t('account.security.trusted_devices_intro') }}</p>
167
+ <form method="POST" action="/account/security/trusted-devices/revoke">
168
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
169
+ <button type="submit" class="rounded-lg border border-gray-300 px-4 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-50">
170
+ {{ t('account.security.trusted_devices_revoke') }}
171
+ </button>
172
+ </form>
173
+ </div>
174
+ @end
175
+
176
+ @if(exportSupported)
177
+ <div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-black/5">
178
+ <h2 class="mb-1 text-sm font-semibold text-gray-900">{{ t('account.export.section') }}</h2>
179
+ <p class="mb-4 text-xs text-gray-500">{{ t('account.export.intro') }}</p>
180
+ <a href="/account/security/export"
181
+ class="inline-block rounded-lg border border-gray-300 px-4 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-50">
182
+ {{ t('account.export.submit') }}
183
+ </a>
184
+ </div>
185
+ @end
186
+
187
+ @if(deletionSupported)
188
+ @if(deleteError)
189
+ <div class="mt-6 rounded-lg border border-red-300 bg-red-50 p-4">
190
+ <p class="text-sm font-medium text-red-900">{{ deleteError }}</p>
191
+ </div>
192
+ @end
193
+ <div class="mt-6 rounded-xl bg-white p-6 shadow-sm ring-1 ring-red-200">
194
+ <h2 class="mb-1 text-sm font-semibold text-red-700">{{ t('account.delete.section') }}</h2>
195
+ <p class="mb-4 text-xs text-gray-500">{{ t('account.delete.intro') }}</p>
196
+ <form method="POST" action="/account/security/delete" class="space-y-4">
197
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
198
+ <div>
199
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.delete.confirm_password_label') }}</label>
200
+ <input name="currentPassword" type="password"
201
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-red-600" />
202
+ </div>
203
+ <div>
204
+ <label class="mb-1 block text-sm font-medium text-gray-700">{{ t('account.delete.confirm_email_label') }}</label>
205
+ <input name="confirmEmail" type="email" placeholder="{{ email }}"
206
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-red-600" />
207
+ </div>
208
+ <button type="submit" class="rounded-lg bg-red-600 px-4 py-2 text-sm font-semibold text-white hover:bg-red-700">
209
+ {{ t('account.delete.submit') }}
210
+ </button>
211
+ </form>
212
+ </div>
213
+ @end
214
+ </div>
215
+ </body></html>
@@ -0,0 +1,75 @@
1
+ <!doctype html>
2
+ <html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('account.tokens.page_title') }}</title>
3
+ @include('authkit::partials/styles')
4
+ </head>
5
+ <body class="min-h-screen bg-gray-100 p-4">
6
+ <div class="mx-auto max-w-2xl">
7
+ <div class="flex items-center justify-between py-6">
8
+ <div>
9
+ <div class="text-xs font-semibold uppercase tracking-widest text-gray-400">{{ t('common.brand_eyebrow') }}</div>
10
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('account.tokens.title') }}</h1>
11
+ </div>
12
+ <div class="flex items-center gap-4">
13
+ <a href="/account/security" class="text-sm text-gray-500 hover:underline">{{ t('account.tokens.security') }}</a>
14
+ <a href="/account/apps" class="text-sm text-gray-500 hover:underline">{{ t('account.apps.title') }}</a>
15
+ <form method="POST" action="/account/logout">
16
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
17
+ <button type="submit" class="text-sm text-gray-500 hover:underline">{{ t('account.tokens.logout') }}</button>
18
+ </form>
19
+ </div>
20
+ </div>
21
+
22
+ @if(createdToken)
23
+ <div class="mb-6 rounded-lg border border-emerald-300 bg-emerald-50 p-4">
24
+ <p class="text-sm font-medium text-emerald-900">
25
+ {{ t('account.tokens.created_notice') }}
26
+ </p>
27
+ <code class="mt-2 block break-all rounded bg-white px-3 py-2 text-sm text-emerald-800 ring-1 ring-emerald-200">
28
+ {{ createdToken }}
29
+ </code>
30
+ </div>
31
+ @end
32
+
33
+ <form method="POST" action="/account/tokens"
34
+ class="mb-6 flex gap-2 rounded-xl bg-white p-4 shadow-sm ring-1 ring-black/5">
35
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
36
+ <input name="name" placeholder="{{ t('account.tokens.name_placeholder') }}"
37
+ class="flex-1 rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
38
+ <button type="submit" class="rounded-lg bg-gray-900 px-4 text-sm font-semibold text-white">
39
+ {{ t('account.tokens.create') }}
40
+ </button>
41
+ </form>
42
+
43
+ <div class="overflow-hidden rounded-xl bg-white shadow-sm ring-1 ring-black/5">
44
+ @if(tokens.length === 0)
45
+ <p class="p-6 text-sm text-gray-500">{{ t('account.tokens.empty') }}</p>
46
+ @else
47
+ @each(token in tokens)
48
+ <div class="flex items-center justify-between border-b border-gray-100 p-4 last:border-0">
49
+ <div>
50
+ <p class="text-sm font-medium text-gray-900">{{ token.name }}</p>
51
+ <p class="text-xs text-gray-500">
52
+ {{ t('account.tokens.created_at', { date: token.createdAt }) }}
53
+ @if(token.lastUsedAt)
54
+ {{ t('account.tokens.last_used', { date: token.lastUsedAt }) }}
55
+ @else
56
+ {{ t('account.tokens.never_used') }}
57
+ @end
58
+ </p>
59
+ @if(token.scopes && token.scopes.length > 0)
60
+ <p class="text-xs text-gray-400">{{ t('account.tokens.scopes', { scopes: token.scopes.join(', ') }) }}</p>
61
+ @end
62
+ @if(token.audience)
63
+ <p class="text-xs text-gray-400">{{ t('account.tokens.audience', { audience: token.audience }) }}</p>
64
+ @end
65
+ </div>
66
+ <form method="POST" action="/account/tokens/{{ token.id }}/revoke">
67
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
68
+ <button type="submit" class="text-sm text-red-600 hover:underline">{{ t('account.tokens.revoke') }}</button>
69
+ </form>
70
+ </div>
71
+ @end
72
+ @end
73
+ </div>
74
+ </div>
75
+ </body></html>
@@ -0,0 +1,20 @@
1
+ <!doctype html>
2
+ <html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('consent.page_title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
3
+ @include('authkit::partials/styles')
4
+ </head>
5
+ <body class="min-h-screen flex items-center justify-center bg-gray-50">
6
+ <div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
7
+ <form method="POST" action="/auth/interaction/{{ uid }}/consent">
8
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
9
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('consent.title') }}</h1>
10
+ <p class="mt-2 text-sm text-gray-600">
11
+ {{{ t('consent.body', { app: brand && brand.appName ? brand.appName : params.client_id }) }}}
12
+ </p>
13
+
14
+ <button type="submit"
15
+ class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
16
+ {{ t('consent.submit') }}
17
+ </button>
18
+ </form>
19
+ </div>
20
+ </body></html>
@@ -0,0 +1,43 @@
1
+ <!doctype html>
2
+ <html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('forgot.page_title') }}</title>
3
+ @include('authkit::partials/styles')
4
+ @if(botProtection && botProtection.scriptUrl)
5
+ <script src="{{ botProtection.scriptUrl }}" async defer></script>
6
+ @end
7
+ </head>
8
+ <body class="min-h-screen flex items-center justify-center bg-gray-50">
9
+ <div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
10
+ @if(sent)
11
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('forgot.sent_title') }}</h1>
12
+ <p class="mt-2 text-sm text-gray-600">
13
+ {{ t('forgot.sent_body') }}
14
+ </p>
15
+ @else
16
+ <form method="POST" action="/auth/forgot-password">
17
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
18
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('forgot.title') }}</h1>
19
+ <p class="mt-1 text-sm text-gray-500">{{ t('forgot.intro') }}</p>
20
+
21
+ @if(error)
22
+ <p class="mt-4 text-sm text-red-600">{{ error }}</p>
23
+ @end
24
+
25
+ <div class="mt-6">
26
+ <label for="email" class="mb-1 block text-sm font-medium text-gray-700">{{ t('forgot.email_label') }}</label>
27
+ <input id="email" name="email" type="email" required autofocus
28
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
29
+ </div>
30
+
31
+ {{-- Bot protection: container do widget (config-trusted; HTML do host renderizado raw). --}}
32
+ @if(botProtection && botProtection.html)
33
+ <div class="mt-4">{{{ botProtection.html }}}</div>
34
+ @end
35
+
36
+ <button type="submit"
37
+ class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
38
+ {{ t('forgot.submit') }}
39
+ </button>
40
+ </form>
41
+ @end
42
+ </div>
43
+ </body></html>
@@ -0,0 +1,251 @@
1
+ <!doctype html>
2
+ <html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('login.page_title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
3
+ @include('authkit::partials/styles')
4
+ @if(botProtection && botProtection.scriptUrl)
5
+ <script src="{{ botProtection.scriptUrl }}" async defer></script>
6
+ @end
7
+ </head>
8
+ <body class="min-h-screen flex items-center justify-center bg-gray-50">
9
+ @if(step === 'identifier')
10
+ <div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
11
+ <form method="POST" action="/auth/interaction/{{ uid }}/identifier">
12
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
13
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('login.title') }}</h1>
14
+ <p class="mt-1 text-sm text-gray-500">{{ t('login.identifier_intro') }}</p>
15
+
16
+ @if(error)
17
+ <p class="mt-4 text-sm text-red-600">{{ error }}</p>
18
+ @end
19
+
20
+ <div class="mt-6">
21
+ <label for="email" class="mb-1 block text-sm font-medium text-gray-700">{{ t('login.email_label') }}</label>
22
+ <input id="email" name="email" type="email" required autofocus
23
+ autocomplete="{{ authMethods && authMethods.passkeyAutofill ? 'username webauthn' : 'username' }}"
24
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
25
+ </div>
26
+
27
+ <button type="submit"
28
+ class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
29
+ {{ t('login.identifier_submit') }}
30
+ </button>
31
+
32
+ <div class="mt-4 flex justify-between text-sm text-gray-600">
33
+ @if(registrationEnabled !== false)
34
+ <a href="/auth/interaction/{{ uid }}/signup" class="hover:underline">{{ t('login.create_account') }}</a>
35
+ @end
36
+ @if(!authMethods || authMethods.forgotPassword !== false)
37
+ <a href="/auth/forgot-password" class="hover:underline">{{ t('login.forgot_password') }}</a>
38
+ @end
39
+ </div>
40
+ </form>
41
+
42
+ @if(!authMethods || authMethods.social === undefined || authMethods.social.length > 0)
43
+ <div class="my-6 flex items-center gap-3 text-xs text-gray-400">
44
+ <span class="h-px flex-1 bg-gray-200"></span>
45
+ {{ t('login.divider_or') }}
46
+ <span class="h-px flex-1 bg-gray-200"></span>
47
+ </div>
48
+
49
+ @each(provider in (authMethods && authMethods.social ? authMethods.social : []))
50
+ <a href="/auth/{{ provider }}/redirect/{{ uid }}"
51
+ class="flex w-full items-center justify-center gap-2 rounded-lg border border-gray-300 bg-white py-2.5 text-sm font-medium text-gray-700 transition hover:bg-gray-50 mb-2">
52
+ @if(provider === 'google')
53
+ <svg class="h-4 w-4" viewBox="0 0 24 24" aria-hidden="true">
54
+ <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.27-4.74 3.27-8.1Z"/>
55
+ <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84A11 11 0 0 0 12 23Z"/>
56
+ <path fill="#FBBC05" d="M5.84 14.1a6.6 6.6 0 0 1 0-4.2V7.06H2.18a11 11 0 0 0 0 9.88l3.66-2.84Z"/>
57
+ <path fill="#EA4335" d="M12 4.75c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 1.46 14.97.5 12 .5A11 11 0 0 0 2.18 7.06l3.66 2.84C6.71 7.3 9.14 4.75 12 4.75Z"/>
58
+ </svg>
59
+ {{ t('login.google') }}
60
+ @else
61
+ {{ t('login.social_provider', { provider: provider }) }}
62
+ @end
63
+ </a>
64
+ @end
65
+ @end
66
+
67
+ {{-- WebAuthn autofill (conditional mediation): quando passkey + passkeyAutofill estão on
68
+ e o browser suporta, o input de e-mail mostra sugestões de passkeys diretamente.
69
+ Sucesso → submete o verify e completa o login sem precisar da senha.
70
+ Fail-safe total: browser sem suporte, abort ou erro = silêncio, login normal segue. --}}
71
+ @if(authMethods && authMethods.passkeyAutofill && authMethods.passkey)
72
+ <form id="autofill-passkey-form" method="POST" action="/auth/interaction/{{ uid }}/passkey/verify" class="hidden">
73
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
74
+ <input type="hidden" name="response" id="autofill-passkey-response">
75
+ </form>
76
+ <script type="module">
77
+ (async () => {
78
+ try {
79
+ // SSR-safe: só roda no browser.
80
+ if (typeof window === 'undefined' || typeof navigator === 'undefined') return
81
+ if (!window.PublicKeyCredential) return
82
+ // Detecta suporte a conditional mediation.
83
+ const supported = await PublicKeyCredential.isConditionalMediationAvailable?.()
84
+ if (!supported) return
85
+
86
+ const { startAuthentication } = await import(
87
+ 'https://cdn.jsdelivr.net/npm/@simplewebauthn/browser@13/dist/bundle/index.js'
88
+ )
89
+ const csrf = document.querySelector('input[name="_csrf"]')?.value ?? ''
90
+ const optRes = await fetch('/auth/interaction/{{ uid }}/passkey/options', {
91
+ method: 'POST',
92
+ headers: { 'content-type': 'application/json', 'x-csrf-token': csrf },
93
+ body: JSON.stringify({}),
94
+ })
95
+ if (!optRes.ok) return
96
+ const optionsJSON = await optRes.json()
97
+ // Remove flag interna antes de passar ao browser.
98
+ delete optionsJSON._discoverable
99
+
100
+ // AbortController: cancela ao navegar/desmontar.
101
+ const ac = new AbortController()
102
+ window.addEventListener('beforeunload', () => ac.abort(), { once: true })
103
+
104
+ const assertion = await startAuthentication({
105
+ optionsJSON,
106
+ useBrowserAutofill: true,
107
+ verifyBrowserAutofillInput: true,
108
+ }, ac.signal)
109
+
110
+ document.getElementById('autofill-passkey-response').value = JSON.stringify(assertion)
111
+ document.getElementById('autofill-passkey-form').submit()
112
+ } catch {
113
+ // Fail-safe: abort, suporte ausente ou qualquer erro = login normal.
114
+ }
115
+ })()
116
+ </script>
117
+ @end
118
+ </div>
119
+ @else
120
+ <div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
121
+ @if(!authMethods || authMethods.password !== false)
122
+ <form method="POST" action="/auth/interaction/{{ uid }}/login">
123
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
124
+
125
+ @if(account && account.fullName)
126
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('login.greeting', { name: account.fullName }) }}</h1>
127
+ @else
128
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('login.title') }}</h1>
129
+ @end
130
+
131
+ <div class="mt-1 flex items-center gap-2">
132
+ @if(email)
133
+ <span class="text-sm text-gray-500">{{ email }}</span>
134
+ @end
135
+ <a href="/auth/interaction/{{ uid }}/switch" class="text-xs font-medium text-gray-900 hover:underline">
136
+ {{ t('login.switch_account') }}
137
+ </a>
138
+ </div>
139
+
140
+ @if(error)
141
+ <p class="mt-4 text-sm text-red-600">{{ error }}</p>
142
+ @end
143
+
144
+ <div class="mt-6">
145
+ <label for="password" class="mb-1 block text-sm font-medium text-gray-700">{{ t('login.password_label') }}</label>
146
+ <input id="password" name="password" type="password" required autofocus
147
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
148
+ </div>
149
+
150
+ {{-- Bot protection: container do widget (config-trusted; HTML do host renderizado raw). --}}
151
+ @if(botProtection && botProtection.html)
152
+ <div class="mt-4">{{{ botProtection.html }}}</div>
153
+ @end
154
+
155
+ {{-- Remember-me checkbox: visível apenas quando rememberEnabled=true (session_policy). --}}
156
+ @if(rememberEnabled !== false)
157
+ <div class="mt-4 flex items-center gap-2">
158
+ <input id="remember" name="remember" type="checkbox" value="on"
159
+ class="h-4 w-4 rounded border-gray-300 text-gray-900 focus:ring-gray-900" />
160
+ <label for="remember" class="text-sm text-gray-700">{{ t('login.remember_me') }}</label>
161
+ </div>
162
+ @end
163
+
164
+ <button type="submit"
165
+ class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
166
+ {{ t('login.submit') }}
167
+ </button>
168
+
169
+ @if(!authMethods || authMethods.forgotPassword !== false)
170
+ <div class="mt-4 flex justify-end text-sm text-gray-600">
171
+ <a href="/auth/forgot-password" class="hover:underline">{{ t('login.forgot_password') }}</a>
172
+ </div>
173
+ @end
174
+ </form>
175
+ @else
176
+ {{-- Sem método senha: cabeçalho sem o formulário de senha --}}
177
+ @if(account && account.fullName)
178
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('login.greeting', { name: account.fullName }) }}</h1>
179
+ @else
180
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('login.title') }}</h1>
181
+ @end
182
+ <div class="mt-1 flex items-center gap-2">
183
+ @if(email)
184
+ <span class="text-sm text-gray-500">{{ email }}</span>
185
+ @end
186
+ <a href="/auth/interaction/{{ uid }}/switch" class="text-xs font-medium text-gray-900 hover:underline">
187
+ {{ t('login.switch_account') }}
188
+ </a>
189
+ </div>
190
+ @if(error)
191
+ <p class="mt-4 text-sm text-red-600">{{ error }}</p>
192
+ @end
193
+ @end
194
+
195
+ {{-- Passwordless: confirmação de magic link enviado (anti-enumeração). --}}
196
+ @if(magicLinkSent)
197
+ <p class="mt-4 rounded-lg bg-green-50 px-3 py-2 text-sm text-green-700">{{ t('login.magic_link_sent') }}</p>
198
+ @end
199
+
200
+ {{-- Passwordless: "me envie um link de login" (mesma sessão/e-mail; não pede senha). --}}
201
+ @if(magicLinkAvailable && !magicLinkSent)
202
+ <form method="POST" action="/auth/interaction/{{ uid }}/magic" class="mt-4">
203
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
204
+ <button type="submit"
205
+ class="w-full rounded-lg border border-gray-300 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50">
206
+ {{ t('login.magic_link_button') }}
207
+ </button>
208
+ </form>
209
+ @end
210
+
211
+ {{-- Passwordless: "entrar com passkey" ANTES da senha. Reusa as cerimônias
212
+ de passkey do MFA (begin/finish) liberadas no estágio de senha. --}}
213
+ @if(passkeyFirstAvailable)
214
+ <form id="passkey-form" method="POST" action="/auth/interaction/{{ uid }}/passkey/verify" class="mt-4">
215
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
216
+ <input type="hidden" name="response" id="passkey-response">
217
+ </form>
218
+ <button type="button" id="passkey-button"
219
+ class="mt-4 w-full rounded-lg border border-gray-300 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50">
220
+ {{ t('login.passkey_button') }}
221
+ </button>
222
+ <p id="passkey-error" class="mt-3 hidden text-sm text-red-600">{{ t('mfa_challenge.passkey_error') }}</p>
223
+ <script type="module">
224
+ import { startAuthentication } from 'https://cdn.jsdelivr.net/npm/@simplewebauthn/browser@13/dist/bundle/index.js'
225
+ const btn = document.getElementById('passkey-button')
226
+ const errEl = document.getElementById('passkey-error')
227
+ const csrf = document.querySelector('#passkey-form input[name="_csrf"]').value
228
+ btn?.addEventListener('click', async () => {
229
+ errEl.classList.add('hidden')
230
+ btn.disabled = true
231
+ try {
232
+ const res = await fetch('/auth/interaction/{{ uid }}/passkey/options', {
233
+ method: 'POST',
234
+ headers: { 'content-type': 'application/json', 'x-csrf-token': csrf },
235
+ body: JSON.stringify({}),
236
+ })
237
+ if (!res.ok) throw new Error('options')
238
+ const optionsJSON = await res.json()
239
+ const assertion = await startAuthentication({ optionsJSON })
240
+ document.getElementById('passkey-response').value = JSON.stringify(assertion)
241
+ document.getElementById('passkey-form').submit()
242
+ } catch (e) {
243
+ errEl.classList.remove('hidden')
244
+ btn.disabled = false
245
+ }
246
+ })
247
+ </script>
248
+ @end
249
+ </div>
250
+ @end
251
+ </body></html>
@@ -0,0 +1,32 @@
1
+ <!doctype html>
2
+ <html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('maintenance.title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
3
+ @include('authkit::partials/styles')
4
+ </head>
5
+ <body class="min-h-screen flex items-center justify-center bg-gray-50">
6
+ <div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5 text-center">
7
+ <h1 class="text-xl font-semibold text-gray-900">{{ t('maintenance.title') }}</h1>
8
+ <p class="mt-3 text-sm text-gray-600">{{ message }}</p>
9
+
10
+ {{-- Admins can still authenticate. The form POSTs to the interaction identifier
11
+ endpoint; from there the normal password step runs, and the POST /login
12
+ guard allows admins through even during maintenance. --}}
13
+ @if(adminLoginAllowed && uid)
14
+ <details class="mt-6 text-left">
15
+ <summary class="cursor-pointer text-xs text-gray-400 hover:text-gray-600 select-none">
16
+ {{ adminLoginNote }}
17
+ </summary>
18
+ <form method="POST" action="/auth/interaction/{{ uid }}/identifier" class="mt-3 space-y-3">
19
+ <input type="hidden" name="_csrf" value="{{ csrfToken }}">
20
+ <input name="email" type="email" required autofocus placeholder="{{ t('login.email_label') }}"
21
+ class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
22
+ <button type="submit"
23
+ class="w-full rounded-lg bg-gray-800 py-2 text-sm font-medium text-white transition hover:bg-gray-700">
24
+ {{ t('login.identifier_submit') }}
25
+ </button>
26
+ </form>
27
+ </details>
28
+ @elseif(adminLoginAllowed)
29
+ <p class="mt-4 text-xs text-gray-400">{{ adminLoginNote }}</p>
30
+ @end
31
+ </div>
32
+ </body></html>