hazo_auth 1.4.2 → 1.6.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 (320) hide show
  1. package/SETUP_CHECKLIST.md +708 -0
  2. package/dist/app/api/hazo_auth/change_password/route.d.ts +8 -0
  3. package/dist/app/api/hazo_auth/change_password/route.d.ts.map +1 -0
  4. package/dist/app/api/hazo_auth/change_password/route.js +98 -0
  5. package/dist/app/api/hazo_auth/forgot_password/route.d.ts +8 -0
  6. package/dist/app/api/hazo_auth/forgot_password/route.d.ts.map +1 -0
  7. package/dist/app/api/hazo_auth/forgot_password/route.js +78 -0
  8. package/dist/app/api/hazo_auth/get_auth/route.d.ts +10 -0
  9. package/dist/app/api/hazo_auth/get_auth/route.d.ts.map +1 -0
  10. package/dist/app/api/hazo_auth/get_auth/route.js +63 -0
  11. package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts +14 -0
  12. package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts.map +1 -0
  13. package/dist/app/api/hazo_auth/invalidate_cache/route.js +96 -0
  14. package/dist/app/api/hazo_auth/library_photos/route.d.ts +13 -0
  15. package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +1 -0
  16. package/dist/app/api/hazo_auth/library_photos/route.js +55 -0
  17. package/dist/app/api/hazo_auth/login/route.d.ts +12 -0
  18. package/dist/app/api/hazo_auth/login/route.d.ts.map +1 -0
  19. package/dist/app/api/hazo_auth/login/route.js +140 -0
  20. package/dist/app/api/hazo_auth/logout/route.d.ts +8 -0
  21. package/dist/app/api/hazo_auth/logout/route.d.ts.map +1 -0
  22. package/dist/app/api/hazo_auth/logout/route.js +71 -0
  23. package/dist/app/api/hazo_auth/me/route.d.ts +3 -0
  24. package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -0
  25. package/dist/app/api/hazo_auth/me/route.js +34 -0
  26. package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts +7 -0
  27. package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts.map +1 -0
  28. package/dist/app/api/hazo_auth/profile_picture/[filename]/route.js +43 -0
  29. package/dist/app/api/hazo_auth/register/route.d.ts +9 -0
  30. package/dist/app/api/hazo_auth/register/route.d.ts.map +1 -0
  31. package/dist/app/api/hazo_auth/register/route.js +80 -0
  32. package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts +8 -0
  33. package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts.map +1 -0
  34. package/dist/app/api/hazo_auth/remove_profile_picture/route.js +64 -0
  35. package/dist/app/api/hazo_auth/resend_verification/route.d.ts +8 -0
  36. package/dist/app/api/hazo_auth/resend_verification/route.d.ts.map +1 -0
  37. package/dist/app/api/hazo_auth/resend_verification/route.js +79 -0
  38. package/dist/app/api/hazo_auth/reset_password/route.d.ts +8 -0
  39. package/dist/app/api/hazo_auth/reset_password/route.d.ts.map +1 -0
  40. package/dist/app/api/hazo_auth/reset_password/route.js +76 -0
  41. package/dist/app/api/hazo_auth/update_user/route.d.ts +9 -0
  42. package/dist/app/api/hazo_auth/update_user/route.d.ts.map +1 -0
  43. package/dist/app/api/hazo_auth/update_user/route.js +95 -0
  44. package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts +9 -0
  45. package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts.map +1 -0
  46. package/dist/app/api/hazo_auth/upload_profile_picture/route.js +204 -0
  47. package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts +6 -0
  48. package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts.map +1 -0
  49. package/dist/app/api/hazo_auth/validate_reset_token/route.js +58 -0
  50. package/dist/app/api/hazo_auth/verify_email/route.d.ts +11 -0
  51. package/dist/app/api/hazo_auth/verify_email/route.d.ts.map +1 -0
  52. package/dist/app/api/hazo_auth/verify_email/route.js +63 -0
  53. package/dist/cli/generate.d.ts +2 -0
  54. package/dist/cli/generate.d.ts.map +1 -0
  55. package/dist/cli/generate.js +117 -0
  56. package/dist/cli/index.d.ts +3 -0
  57. package/dist/cli/index.d.ts.map +1 -0
  58. package/dist/cli/index.js +120 -0
  59. package/dist/cli/validate.d.ts +15 -0
  60. package/dist/cli/validate.d.ts.map +1 -0
  61. package/dist/cli/validate.js +509 -0
  62. package/dist/components/ui/card.d.ts +9 -0
  63. package/dist/components/ui/card.d.ts.map +1 -0
  64. package/dist/components/ui/card.js +45 -0
  65. package/dist/hooks/use-mobile.d.ts.map +1 -1
  66. package/dist/hooks/use-mobile.js +17 -3
  67. package/dist/server/routes/change_password.d.ts +2 -0
  68. package/dist/server/routes/change_password.d.ts.map +1 -0
  69. package/dist/server/routes/change_password.js +2 -0
  70. package/dist/server/routes/forgot_password.d.ts +2 -0
  71. package/dist/server/routes/forgot_password.d.ts.map +1 -0
  72. package/dist/server/routes/forgot_password.js +2 -0
  73. package/dist/server/routes/get_auth.d.ts +2 -0
  74. package/dist/server/routes/get_auth.d.ts.map +1 -0
  75. package/dist/server/routes/get_auth.js +2 -0
  76. package/dist/server/routes/index.d.ts +18 -0
  77. package/dist/server/routes/index.d.ts.map +1 -0
  78. package/dist/server/routes/index.js +24 -0
  79. package/dist/server/routes/invalidate_cache.d.ts +2 -0
  80. package/dist/server/routes/invalidate_cache.d.ts.map +1 -0
  81. package/dist/server/routes/invalidate_cache.js +2 -0
  82. package/dist/server/routes/library_photos.d.ts +2 -0
  83. package/dist/server/routes/library_photos.d.ts.map +1 -0
  84. package/dist/server/routes/library_photos.js +2 -0
  85. package/dist/server/routes/login.d.ts +2 -0
  86. package/dist/server/routes/login.d.ts.map +1 -0
  87. package/dist/server/routes/login.js +2 -0
  88. package/dist/server/routes/logout.d.ts +2 -0
  89. package/dist/server/routes/logout.d.ts.map +1 -0
  90. package/dist/server/routes/logout.js +2 -0
  91. package/dist/server/routes/me.d.ts +2 -0
  92. package/dist/server/routes/me.d.ts.map +1 -0
  93. package/dist/server/routes/me.js +2 -0
  94. package/dist/server/routes/profile_picture_filename.d.ts +2 -0
  95. package/dist/server/routes/profile_picture_filename.d.ts.map +1 -0
  96. package/dist/server/routes/profile_picture_filename.js +3 -0
  97. package/dist/server/routes/register.d.ts +2 -0
  98. package/dist/server/routes/register.d.ts.map +1 -0
  99. package/dist/server/routes/register.js +2 -0
  100. package/dist/server/routes/remove_profile_picture.d.ts +2 -0
  101. package/dist/server/routes/remove_profile_picture.d.ts.map +1 -0
  102. package/dist/server/routes/remove_profile_picture.js +2 -0
  103. package/dist/server/routes/resend_verification.d.ts +2 -0
  104. package/dist/server/routes/resend_verification.d.ts.map +1 -0
  105. package/dist/server/routes/resend_verification.js +2 -0
  106. package/dist/server/routes/reset_password.d.ts +2 -0
  107. package/dist/server/routes/reset_password.d.ts.map +1 -0
  108. package/dist/server/routes/reset_password.js +2 -0
  109. package/dist/server/routes/update_user.d.ts +2 -0
  110. package/dist/server/routes/update_user.d.ts.map +1 -0
  111. package/dist/server/routes/update_user.js +2 -0
  112. package/dist/server/routes/upload_profile_picture.d.ts +2 -0
  113. package/dist/server/routes/upload_profile_picture.d.ts.map +1 -0
  114. package/dist/server/routes/upload_profile_picture.js +2 -0
  115. package/dist/server/routes/validate_reset_token.d.ts +2 -0
  116. package/dist/server/routes/validate_reset_token.d.ts.map +1 -0
  117. package/dist/server/routes/validate_reset_token.js +2 -0
  118. package/dist/server/routes/verify_email.d.ts +2 -0
  119. package/dist/server/routes/verify_email.d.ts.map +1 -0
  120. package/dist/server/routes/verify_email.js +2 -0
  121. package/package.json +12 -17
  122. package/components.json +0 -22
  123. package/instrumentation.ts +0 -32
  124. package/migrations/001_add_token_type_to_refresh_tokens.sql +0 -14
  125. package/migrations/002_add_name_to_hazo_users.sql +0 -7
  126. package/migrations/003_add_url_on_logon_to_hazo_users.sql +0 -8
  127. package/next.config.mjs +0 -67
  128. package/postcss.config.mjs +0 -8
  129. package/public/file.svg +0 -1
  130. package/public/globe.svg +0 -1
  131. package/public/next.svg +0 -1
  132. package/public/vercel.svg +0 -1
  133. package/public/window.svg +0 -1
  134. package/scripts/apply_migration.ts +0 -118
  135. package/scripts/init_users.ts +0 -378
  136. package/src/app/api/hazo_auth/auth/upload_profile_picture/route.ts +0 -268
  137. package/src/app/api/hazo_auth/change_password/route.ts +0 -132
  138. package/src/app/api/hazo_auth/forgot_password/route.ts +0 -107
  139. package/src/app/api/hazo_auth/get_auth/route.ts +0 -89
  140. package/src/app/api/hazo_auth/invalidate_cache/route.ts +0 -139
  141. package/src/app/api/hazo_auth/library_photos/route.ts +0 -73
  142. package/src/app/api/hazo_auth/login/route.ts +0 -181
  143. package/src/app/api/hazo_auth/logout/route.ts +0 -89
  144. package/src/app/api/hazo_auth/me/route.ts +0 -47
  145. package/src/app/api/hazo_auth/profile_picture/[filename]/route.ts +0 -67
  146. package/src/app/api/hazo_auth/register/route.ts +0 -109
  147. package/src/app/api/hazo_auth/remove_profile_picture/route.ts +0 -86
  148. package/src/app/api/hazo_auth/resend_verification/route.ts +0 -108
  149. package/src/app/api/hazo_auth/reset_password/route.ts +0 -107
  150. package/src/app/api/hazo_auth/update_user/route.ts +0 -126
  151. package/src/app/api/hazo_auth/upload_profile_picture/route.ts +0 -268
  152. package/src/app/api/hazo_auth/user_management/permissions/route.ts +0 -367
  153. package/src/app/api/hazo_auth/user_management/roles/route.ts +0 -442
  154. package/src/app/api/hazo_auth/user_management/users/roles/route.ts +0 -367
  155. package/src/app/api/hazo_auth/user_management/users/route.ts +0 -239
  156. package/src/app/api/hazo_auth/validate_reset_token/route.ts +0 -83
  157. package/src/app/api/hazo_auth/verify_email/route.ts +0 -88
  158. package/src/app/api/migrations/apply/route.ts +0 -91
  159. package/src/app/favicon.ico +0 -0
  160. package/src/app/fonts/GeistMonoVF.woff +0 -0
  161. package/src/app/fonts/GeistVF.woff +0 -0
  162. package/src/app/globals.css +0 -89
  163. package/src/app/hazo_auth/forgot_password/forgot_password_page_client.tsx +0 -60
  164. package/src/app/hazo_auth/forgot_password/page.tsx +0 -24
  165. package/src/app/hazo_auth/login/login_page_client.tsx +0 -86
  166. package/src/app/hazo_auth/login/page.tsx +0 -38
  167. package/src/app/hazo_auth/my_settings/my_settings_page_client.tsx +0 -120
  168. package/src/app/hazo_auth/my_settings/page.tsx +0 -40
  169. package/src/app/hazo_auth/register/page.tsx +0 -36
  170. package/src/app/hazo_auth/register/register_page_client.tsx +0 -81
  171. package/src/app/hazo_auth/reset_password/page.tsx +0 -29
  172. package/src/app/hazo_auth/reset_password/reset_password_page_client.tsx +0 -81
  173. package/src/app/hazo_auth/user_management/page.tsx +0 -14
  174. package/src/app/hazo_auth/user_management/user_management_page_client.tsx +0 -16
  175. package/src/app/hazo_auth/verify_email/page.tsx +0 -24
  176. package/src/app/hazo_auth/verify_email/verify_email_page_client.tsx +0 -60
  177. package/src/app/hazo_connect/api/sqlite/data/route.ts +0 -203
  178. package/src/app/hazo_connect/api/sqlite/schema/route.ts +0 -45
  179. package/src/app/hazo_connect/api/sqlite/tables/route.ts +0 -36
  180. package/src/app/hazo_connect/sqlite_admin/page.tsx +0 -51
  181. package/src/app/hazo_connect/sqlite_admin/sqlite-admin-client.tsx +0 -984
  182. package/src/app/layout.tsx +0 -43
  183. package/src/app/page.tsx +0 -170
  184. package/src/components/index.ts +0 -7
  185. package/src/components/layouts/email_verification/config/email_verification_field_config.ts +0 -86
  186. package/src/components/layouts/email_verification/hooks/use_email_verification.ts +0 -297
  187. package/src/components/layouts/email_verification/index.tsx +0 -297
  188. package/src/components/layouts/forgot_password/config/forgot_password_field_config.ts +0 -58
  189. package/src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts +0 -179
  190. package/src/components/layouts/forgot_password/index.tsx +0 -168
  191. package/src/components/layouts/index.ts +0 -26
  192. package/src/components/layouts/login/config/login_field_config.ts +0 -67
  193. package/src/components/layouts/login/hooks/use_login_form.ts +0 -286
  194. package/src/components/layouts/login/index.tsx +0 -252
  195. package/src/components/layouts/my_settings/components/editable_field.tsx +0 -177
  196. package/src/components/layouts/my_settings/components/password_change_dialog.tsx +0 -301
  197. package/src/components/layouts/my_settings/components/profile_picture_dialog.tsx +0 -385
  198. package/src/components/layouts/my_settings/components/profile_picture_display.tsx +0 -66
  199. package/src/components/layouts/my_settings/components/profile_picture_gravatar_tab.tsx +0 -143
  200. package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +0 -311
  201. package/src/components/layouts/my_settings/components/profile_picture_upload_tab.tsx +0 -341
  202. package/src/components/layouts/my_settings/config/my_settings_field_config.ts +0 -61
  203. package/src/components/layouts/my_settings/hooks/use_my_settings.ts +0 -458
  204. package/src/components/layouts/my_settings/index.tsx +0 -351
  205. package/src/components/layouts/register/config/register_field_config.ts +0 -101
  206. package/src/components/layouts/register/hooks/use_register_form.ts +0 -275
  207. package/src/components/layouts/register/index.tsx +0 -226
  208. package/src/components/layouts/reset_password/config/reset_password_field_config.ts +0 -86
  209. package/src/components/layouts/reset_password/hooks/use_reset_password_form.ts +0 -276
  210. package/src/components/layouts/reset_password/index.tsx +0 -294
  211. package/src/components/layouts/shared/components/already_logged_in_guard.tsx +0 -95
  212. package/src/components/layouts/shared/components/auth_page_shell.tsx +0 -36
  213. package/src/components/layouts/shared/components/field_error_message.tsx +0 -29
  214. package/src/components/layouts/shared/components/form_action_buttons.tsx +0 -64
  215. package/src/components/layouts/shared/components/form_field_wrapper.tsx +0 -44
  216. package/src/components/layouts/shared/components/form_header.tsx +0 -36
  217. package/src/components/layouts/shared/components/logout_button.tsx +0 -76
  218. package/src/components/layouts/shared/components/password_field.tsx +0 -72
  219. package/src/components/layouts/shared/components/profile_pic_menu.tsx +0 -321
  220. package/src/components/layouts/shared/components/profile_pic_menu_wrapper.tsx +0 -40
  221. package/src/components/layouts/shared/components/sidebar_layout_wrapper.tsx +0 -214
  222. package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +0 -53
  223. package/src/components/layouts/shared/components/two_column_auth_layout.tsx +0 -44
  224. package/src/components/layouts/shared/components/unauthorized_guard.tsx +0 -78
  225. package/src/components/layouts/shared/components/visual_panel.tsx +0 -41
  226. package/src/components/layouts/shared/config/layout_customization.ts +0 -95
  227. package/src/components/layouts/shared/data/layout_data_client.ts +0 -19
  228. package/src/components/layouts/shared/hooks/use_auth_status.ts +0 -103
  229. package/src/components/layouts/shared/hooks/use_hazo_auth.ts +0 -158
  230. package/src/components/layouts/shared/index.ts +0 -34
  231. package/src/components/layouts/shared/utils/ip_address.ts +0 -37
  232. package/src/components/layouts/shared/utils/validation.ts +0 -66
  233. package/src/components/layouts/user_management/components/roles_matrix.tsx +0 -607
  234. package/src/components/layouts/user_management/index.tsx +0 -1295
  235. package/src/components/ui/alert-dialog.tsx +0 -141
  236. package/src/components/ui/avatar.tsx +0 -50
  237. package/src/components/ui/button.tsx +0 -57
  238. package/src/components/ui/checkbox.tsx +0 -30
  239. package/src/components/ui/dialog.tsx +0 -122
  240. package/src/components/ui/dropdown-menu.tsx +0 -201
  241. package/src/components/ui/hazo_ui_tooltip.tsx +0 -67
  242. package/src/components/ui/index.ts +0 -22
  243. package/src/components/ui/input.tsx +0 -22
  244. package/src/components/ui/label.tsx +0 -26
  245. package/src/components/ui/separator.tsx +0 -31
  246. package/src/components/ui/sheet.tsx +0 -139
  247. package/src/components/ui/sidebar.tsx +0 -773
  248. package/src/components/ui/skeleton.tsx +0 -15
  249. package/src/components/ui/sonner.tsx +0 -31
  250. package/src/components/ui/switch.tsx +0 -29
  251. package/src/components/ui/table.tsx +0 -120
  252. package/src/components/ui/tabs.tsx +0 -55
  253. package/src/components/ui/tooltip.tsx +0 -32
  254. package/src/components/ui/vertical-tabs.tsx +0 -59
  255. package/src/hooks/use-mobile.tsx +0 -19
  256. package/src/index.ts +0 -7
  257. package/src/lib/already_logged_in_config.server.ts +0 -46
  258. package/src/lib/app_logger.ts +0 -24
  259. package/src/lib/auth/auth_cache.ts +0 -220
  260. package/src/lib/auth/auth_rate_limiter.ts +0 -121
  261. package/src/lib/auth/auth_types.ts +0 -65
  262. package/src/lib/auth/auth_utils.server.ts +0 -196
  263. package/src/lib/auth/hazo_get_auth.server.ts +0 -333
  264. package/src/lib/auth/index.ts +0 -23
  265. package/src/lib/auth/server_auth.ts +0 -88
  266. package/src/lib/auth_utility_config.server.ts +0 -136
  267. package/src/lib/config/config_loader.server.ts +0 -164
  268. package/src/lib/email_verification_config.server.ts +0 -32
  269. package/src/lib/file_types_config.server.ts +0 -25
  270. package/src/lib/forgot_password_config.server.ts +0 -32
  271. package/src/lib/hazo_connect_instance.server.ts +0 -101
  272. package/src/lib/hazo_connect_setup.server.ts +0 -194
  273. package/src/lib/hazo_connect_setup.ts +0 -54
  274. package/src/lib/index.ts +0 -44
  275. package/src/lib/login_config.server.ts +0 -71
  276. package/src/lib/messages_config.server.ts +0 -45
  277. package/src/lib/migrations/apply_migration.ts +0 -105
  278. package/src/lib/my_settings_config.server.ts +0 -135
  279. package/src/lib/password_requirements_config.server.ts +0 -39
  280. package/src/lib/profile_pic_menu_config.server.ts +0 -138
  281. package/src/lib/profile_picture_config.server.ts +0 -56
  282. package/src/lib/register_config.server.ts +0 -73
  283. package/src/lib/reset_password_config.server.ts +0 -75
  284. package/src/lib/services/email_service.ts +0 -581
  285. package/src/lib/services/email_verification_service.ts +0 -270
  286. package/src/lib/services/index.ts +0 -15
  287. package/src/lib/services/login_service.ts +0 -134
  288. package/src/lib/services/password_change_service.ts +0 -154
  289. package/src/lib/services/password_reset_service.ts +0 -405
  290. package/src/lib/services/profile_picture_remove_service.ts +0 -120
  291. package/src/lib/services/profile_picture_service.ts +0 -215
  292. package/src/lib/services/profile_picture_source_mapper.ts +0 -62
  293. package/src/lib/services/registration_service.ts +0 -184
  294. package/src/lib/services/token_service.ts +0 -240
  295. package/src/lib/services/user_profiles_service.ts +0 -143
  296. package/src/lib/services/user_update_service.ts +0 -141
  297. package/src/lib/ui_shell_config.server.ts +0 -73
  298. package/src/lib/ui_sizes_config.server.ts +0 -37
  299. package/src/lib/user_fields_config.server.ts +0 -31
  300. package/src/lib/user_management_config.server.ts +0 -39
  301. package/src/lib/utils/api_route_helpers.ts +0 -60
  302. package/src/lib/utils/error_sanitizer.ts +0 -75
  303. package/src/lib/utils.ts +0 -11
  304. package/src/middleware.ts +0 -94
  305. package/src/routes/index.ts +0 -34
  306. package/src/server/config/config_loader.ts +0 -496
  307. package/src/server/index.ts +0 -38
  308. package/src/server/logging/logger_service.ts +0 -56
  309. package/src/server/routes/root_router.ts +0 -16
  310. package/src/server/server.ts +0 -28
  311. package/src/server/types/app_types.ts +0 -74
  312. package/src/server/types/express.d.ts +0 -16
  313. package/src/stories/email_verification_layout.stories.tsx +0 -137
  314. package/src/stories/forgot_password_layout.stories.tsx +0 -85
  315. package/src/stories/login_layout.stories.tsx +0 -85
  316. package/src/stories/project_overview.stories.tsx +0 -33
  317. package/src/stories/register_layout.stories.tsx +0 -107
  318. package/tailwind.config.ts +0 -77
  319. package/tsconfig.build.json +0 -36
  320. package/tsconfig.json +0 -28
@@ -1,26 +0,0 @@
1
- // file_description: barrel export for all layout components
2
- // section: layout_exports
3
- export { default as LoginLayout } from "./login/index";
4
- export type { LoginLayoutProps } from "./login/index";
5
-
6
- export { default as RegisterLayout } from "./register/index";
7
- export type { RegisterLayoutProps } from "./register/index";
8
-
9
- export { default as ForgotPasswordLayout } from "./forgot_password/index";
10
- export type { ForgotPasswordLayoutProps } from "./forgot_password/index";
11
-
12
- export { default as ResetPasswordLayout } from "./reset_password/index";
13
- export type { ResetPasswordLayoutProps } from "./reset_password/index";
14
-
15
- export { default as EmailVerificationLayout } from "./email_verification/index";
16
- export type { EmailVerificationLayoutProps } from "./email_verification/index";
17
-
18
- export { default as MySettingsLayout } from "./my_settings/index";
19
- export type { MySettingsLayoutProps } from "./my_settings/index";
20
-
21
- export { UserManagementLayout } from "./user_management/index";
22
- export type { UserManagementLayoutProps } from "./user_management/index";
23
-
24
- // section: shared_exports
25
- export * from "./shared/index";
26
-
@@ -1,67 +0,0 @@
1
- // file_description: login layout specific configuration helpers
2
- // section: imports
3
- import type { LayoutFieldMap, LayoutFieldMapOverrides } from "../../shared/config/layout_customization";
4
- import {
5
- resolveButtonPalette,
6
- resolveFieldDefinitions,
7
- resolveLabels,
8
- type ButtonPaletteDefaults,
9
- type ButtonPaletteOverrides,
10
- type LayoutLabelDefaults,
11
- type LayoutLabelOverrides,
12
- } from "../../shared/config/layout_customization";
13
-
14
- // section: field_identifiers
15
- export const LOGIN_FIELD_IDS = {
16
- EMAIL: "email_address",
17
- PASSWORD: "password",
18
- } as const;
19
-
20
- export type LoginFieldId = (typeof LOGIN_FIELD_IDS)[keyof typeof LOGIN_FIELD_IDS];
21
-
22
- // section: field_definitions
23
- const LOGIN_FIELD_DEFINITIONS: LayoutFieldMap = {
24
- [LOGIN_FIELD_IDS.EMAIL]: {
25
- id: LOGIN_FIELD_IDS.EMAIL,
26
- label: "Email address",
27
- type: "email",
28
- autoComplete: "email",
29
- placeholder: "Enter your email address",
30
- ariaLabel: "Email address input field",
31
- },
32
- [LOGIN_FIELD_IDS.PASSWORD]: {
33
- id: LOGIN_FIELD_IDS.PASSWORD,
34
- label: "Password",
35
- type: "password",
36
- autoComplete: "current-password",
37
- placeholder: "Enter your password",
38
- ariaLabel: "Password input field",
39
- },
40
- };
41
-
42
- export const createLoginFieldDefinitions = (
43
- overrides?: LayoutFieldMapOverrides,
44
- ) => resolveFieldDefinitions(LOGIN_FIELD_DEFINITIONS, overrides);
45
-
46
- // section: label_defaults
47
- const LOGIN_LABEL_DEFAULTS: LayoutLabelDefaults = {
48
- heading: "Sign in to your account",
49
- subHeading: "Enter your credentials to access your secure workspace.",
50
- submitButton: "Login",
51
- cancelButton: "Cancel",
52
- };
53
-
54
- export const resolveLoginLabels = (overrides?: LayoutLabelOverrides) =>
55
- resolveLabels(LOGIN_LABEL_DEFAULTS, overrides);
56
-
57
- // section: button_palette_defaults
58
- const LOGIN_BUTTON_PALETTE_DEFAULTS: ButtonPaletteDefaults = {
59
- submitBackground: "#0f172a",
60
- submitText: "#ffffff",
61
- cancelBorder: "#cbd5f5",
62
- cancelText: "#0f172a",
63
- };
64
-
65
- export const resolveLoginButtonPalette = (overrides?: ButtonPaletteOverrides) =>
66
- resolveButtonPalette(LOGIN_BUTTON_PALETTE_DEFAULTS, overrides);
67
-
@@ -1,286 +0,0 @@
1
- // file_description: encapsulate login form state, validation, data interactions, IP collection, and login attempt logging
2
- // section: imports
3
- import { useCallback, useMemo, useState, useEffect } from "react";
4
- import { useRouter } from "next/navigation";
5
- import type { LayoutDataClient } from "../../shared/data/layout_data_client";
6
- import { LOGIN_FIELD_IDS, type LoginFieldId } from "../config/login_field_config";
7
- import { validateEmail } from "../../shared/utils/validation";
8
- import { get_client_ip } from "../../shared/utils/ip_address";
9
- import { trigger_auth_status_refresh } from "../../shared/hooks/use_auth_status";
10
-
11
- // section: types
12
- export type LoginFormValues = Record<LoginFieldId, string>;
13
- export type LoginFormErrors = Partial<Record<LoginFieldId, string>>;
14
- export type PasswordVisibilityState = {
15
- password: boolean;
16
- };
17
-
18
- export type UseLoginFormParams<TClient = unknown> = {
19
- dataClient: LayoutDataClient<TClient>;
20
- logger?: {
21
- info: (message: string, data?: Record<string, unknown>) => void;
22
- error: (message: string, data?: Record<string, unknown>) => void;
23
- warn: (message: string, data?: Record<string, unknown>) => void;
24
- debug: (message: string, data?: Record<string, unknown>) => void;
25
- };
26
- redirectRoute?: string;
27
- successMessage?: string;
28
- urlOnLogon?: string;
29
- };
30
-
31
- export type UseLoginFormResult = {
32
- values: LoginFormValues;
33
- errors: LoginFormErrors;
34
- passwordVisibility: PasswordVisibilityState;
35
- isSubmitDisabled: boolean;
36
- emailTouched: boolean;
37
- isSuccess: boolean;
38
- handleFieldChange: (fieldId: LoginFieldId, value: string) => void;
39
- handleEmailBlur: () => void;
40
- togglePasswordVisibility: () => void;
41
- handleSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
42
- handleCancel: () => void;
43
- };
44
-
45
- // section: helpers
46
- const buildInitialValues = (): LoginFormValues => ({
47
- [LOGIN_FIELD_IDS.EMAIL]: "",
48
- [LOGIN_FIELD_IDS.PASSWORD]: "",
49
- });
50
-
51
- const get_filename = (): string => {
52
- return "use_login_form.ts";
53
- };
54
-
55
- const get_line_number = (): number => {
56
- // This is a placeholder - in a real implementation, you might use Error stack trace
57
- return 0;
58
- };
59
-
60
- // section: hook
61
- export const use_login_form = <TClient,>({
62
- dataClient,
63
- logger,
64
- redirectRoute,
65
- successMessage = "Successfully logged in",
66
- urlOnLogon,
67
- }: UseLoginFormParams<TClient>): UseLoginFormResult => {
68
- const router = useRouter();
69
- const [values, setValues] = useState<LoginFormValues>(buildInitialValues);
70
- const [errors, setErrors] = useState<LoginFormErrors>({});
71
- const [passwordVisibility, setPasswordVisibility] = useState<PasswordVisibilityState>({
72
- password: false,
73
- });
74
- const [clientIp, setClientIp] = useState<string>("unknown");
75
- const [emailTouched, setEmailTouched] = useState<boolean>(false);
76
- const [isSuccess, setIsSuccess] = useState<boolean>(false);
77
-
78
- // section: ip_collection
79
- useEffect(() => {
80
- let isMounted = true;
81
- void get_client_ip().then((ip) => {
82
- if (isMounted) {
83
- setClientIp(ip);
84
- }
85
- });
86
- return () => {
87
- isMounted = false;
88
- };
89
- }, []);
90
-
91
- const isSubmitDisabled = useMemo(() => {
92
- const allFieldsEmpty = Object.values(values).every((fieldValue) => fieldValue.trim() === "");
93
- return allFieldsEmpty;
94
- }, [values]);
95
-
96
- const togglePasswordVisibility = useCallback(() => {
97
- setPasswordVisibility((previous) => ({
98
- password: !previous.password,
99
- }));
100
- }, []);
101
-
102
- const handleFieldChange = useCallback((fieldId: LoginFieldId, value: string) => {
103
- setValues((previousValues) => {
104
- const nextValues: LoginFormValues = {
105
- ...previousValues,
106
- [fieldId]: value,
107
- };
108
-
109
- setErrors((previousErrors) => {
110
- const updatedErrors: LoginFormErrors = { ...previousErrors };
111
-
112
- // Only validate email on change if it has been touched (blurred)
113
- if (fieldId === LOGIN_FIELD_IDS.EMAIL && emailTouched) {
114
- const emailError = validateEmail(value);
115
- if (emailError) {
116
- updatedErrors[LOGIN_FIELD_IDS.EMAIL] = emailError;
117
- } else {
118
- delete updatedErrors[LOGIN_FIELD_IDS.EMAIL];
119
- }
120
- }
121
-
122
- return updatedErrors;
123
- });
124
-
125
- return nextValues;
126
- });
127
- }, [emailTouched]);
128
-
129
- const handleEmailBlur = useCallback(() => {
130
- setEmailTouched(true);
131
- // Validate email on blur
132
- setErrors((previousErrors) => {
133
- const updatedErrors: LoginFormErrors = { ...previousErrors };
134
- const emailValue = values[LOGIN_FIELD_IDS.EMAIL];
135
- const emailError = validateEmail(emailValue);
136
- if (emailError) {
137
- updatedErrors[LOGIN_FIELD_IDS.EMAIL] = emailError;
138
- } else {
139
- delete updatedErrors[LOGIN_FIELD_IDS.EMAIL];
140
- }
141
- return updatedErrors;
142
- });
143
- }, [values]);
144
-
145
- // section: login_attempt_logging
146
- const log_login_attempt = useCallback(
147
- (success: boolean, errorMessage?: string) => {
148
- if (!logger) {
149
- return;
150
- }
151
-
152
- const timestamp = new Date().toISOString();
153
- const logData = {
154
- filename: get_filename(),
155
- line_number: get_line_number(),
156
- email: values[LOGIN_FIELD_IDS.EMAIL],
157
- ip_address: clientIp,
158
- timestamp,
159
- success,
160
- ...(errorMessage ? { error_message: errorMessage } : {}),
161
- };
162
-
163
- if (success) {
164
- logger.info("login_attempt_successful", logData);
165
- } else {
166
- logger.error("login_attempt_failed", logData);
167
- }
168
- },
169
- [logger, values, clientIp],
170
- );
171
-
172
- const handleSubmit = useCallback(
173
- async (event: React.FormEvent<HTMLFormElement>) => {
174
- event.preventDefault();
175
-
176
- const email = values[LOGIN_FIELD_IDS.EMAIL];
177
- const password = values[LOGIN_FIELD_IDS.PASSWORD];
178
-
179
- try {
180
- // Update IP address if still unknown
181
- const currentIp = clientIp === "unknown" ? await get_client_ip() : clientIp;
182
- setClientIp(currentIp);
183
-
184
- // Attempt login via API route
185
- const response = await fetch("/api/hazo_auth/login", {
186
- method: "POST",
187
- headers: {
188
- "Content-Type": "application/json",
189
- },
190
- body: JSON.stringify({
191
- email,
192
- password,
193
- url_on_logon: urlOnLogon,
194
- }),
195
- });
196
-
197
- const data = await response.json();
198
-
199
- if (!response.ok || !data.success) {
200
- // Check if email is not verified
201
- if (data.email_not_verified) {
202
- // Redirect to verify_email page with email and message
203
- const emailParam = encodeURIComponent(email);
204
- const messageParam = encodeURIComponent(
205
- "Your email address has not been verified. Please verify your email to continue."
206
- );
207
- router.push(`/hazo_auth/verify_email?email=${emailParam}&message=${messageParam}`);
208
- return;
209
- }
210
-
211
- // Login failed for other reasons
212
- const errorMessage = data.error || "Login failed. Please try again.";
213
-
214
- // Log failed login attempt
215
- log_login_attempt(false, errorMessage);
216
-
217
- // Set error state (remain on same page)
218
- setErrors({
219
- [LOGIN_FIELD_IDS.EMAIL]: errorMessage,
220
- });
221
- setIsSuccess(false);
222
- return;
223
- }
224
-
225
- // Login successful
226
- // Log successful login attempt
227
- log_login_attempt(true);
228
-
229
- // Trigger auth status refresh in all components (navbar, sidebar, etc.)
230
- trigger_auth_status_refresh();
231
-
232
- // Refresh the page to update authentication state (cookies are set server-side)
233
- router.refresh();
234
-
235
- // Use redirectUrl from server response if available, otherwise fall back to redirectRoute prop
236
- // The server logic already prioritizes: query param > stored DB value > config > default "/"
237
- const finalRedirectUrl = data.redirectUrl || redirectRoute;
238
-
239
- if (finalRedirectUrl) {
240
- router.push(finalRedirectUrl);
241
- } else {
242
- // Otherwise, show success message
243
- setIsSuccess(true);
244
- }
245
- } catch (error) {
246
- const errorMessage =
247
- error instanceof Error ? error.message : "Unknown error occurred";
248
-
249
- // Log failed login attempt
250
- log_login_attempt(false, errorMessage);
251
-
252
- // Set error state (remain on same page)
253
- setErrors({
254
- [LOGIN_FIELD_IDS.EMAIL]: errorMessage,
255
- });
256
- setIsSuccess(false);
257
- }
258
- },
259
- [values, clientIp, log_login_attempt, redirectRoute, router, urlOnLogon],
260
- );
261
-
262
- const handleCancel = useCallback(() => {
263
- setValues(buildInitialValues());
264
- setErrors({});
265
- setPasswordVisibility({
266
- password: false,
267
- });
268
- setEmailTouched(false);
269
- setIsSuccess(false);
270
- }, []);
271
-
272
- return {
273
- values,
274
- errors,
275
- passwordVisibility,
276
- isSubmitDisabled,
277
- emailTouched,
278
- isSuccess,
279
- handleFieldChange,
280
- handleEmailBlur,
281
- togglePasswordVisibility,
282
- handleSubmit,
283
- handleCancel,
284
- };
285
- };
286
-
@@ -1,252 +0,0 @@
1
- // file_description: login layout component built atop shared layout utilities
2
- // section: client_directive
3
- "use client";
4
-
5
- // section: imports
6
- import Link from "next/link";
7
- import { Input } from "../../ui/input";
8
- import { PasswordField } from "../shared/components/password_field";
9
- import { FormFieldWrapper } from "../shared/components/form_field_wrapper";
10
- import { FormHeader } from "../shared/components/form_header";
11
- import { FormActionButtons } from "../shared/components/form_action_buttons";
12
- import { TwoColumnAuthLayout } from "../shared/components/two_column_auth_layout";
13
- import { CheckCircle } from "lucide-react";
14
- import { AlreadyLoggedInGuard } from "../shared/components/already_logged_in_guard";
15
- import {
16
- type ButtonPaletteOverrides,
17
- type LayoutFieldMapOverrides,
18
- type LayoutLabelOverrides,
19
- } from "../shared/config/layout_customization";
20
- import {
21
- LOGIN_FIELD_IDS,
22
- createLoginFieldDefinitions,
23
- resolveLoginButtonPalette,
24
- resolveLoginLabels,
25
- } from "./config/login_field_config";
26
- import {
27
- use_login_form,
28
- type UseLoginFormResult,
29
- } from "./hooks/use_login_form";
30
- import { type LayoutDataClient } from "../shared/data/layout_data_client";
31
-
32
- // section: types
33
- export type LoginLayoutProps<TClient = unknown> = {
34
- image_src: string;
35
- image_alt: string;
36
- image_background_color?: string;
37
- field_overrides?: LayoutFieldMapOverrides;
38
- labels?: LayoutLabelOverrides;
39
- button_colors?: ButtonPaletteOverrides;
40
- data_client: LayoutDataClient<TClient>;
41
- logger?: {
42
- info: (message: string, data?: Record<string, unknown>) => void;
43
- error: (message: string, data?: Record<string, unknown>) => void;
44
- warn: (message: string, data?: Record<string, unknown>) => void;
45
- debug: (message: string, data?: Record<string, unknown>) => void;
46
- };
47
- redirectRoute?: string;
48
- successMessage?: string;
49
- alreadyLoggedInMessage?: string;
50
- showLogoutButton?: boolean;
51
- showReturnHomeButton?: boolean;
52
- returnHomeButtonLabel?: string;
53
- returnHomePath?: string;
54
- forgot_password_path?: string;
55
- forgot_password_label?: string;
56
- create_account_path?: string;
57
- create_account_label?: string;
58
- urlOnLogon?: string;
59
- };
60
-
61
- const ORDERED_FIELDS: LoginFieldId[] = [
62
- LOGIN_FIELD_IDS.EMAIL,
63
- LOGIN_FIELD_IDS.PASSWORD,
64
- ];
65
-
66
- type LoginFieldId = (typeof LOGIN_FIELD_IDS)[keyof typeof LOGIN_FIELD_IDS];
67
-
68
- // section: component
69
- export default function login_layout<TClient>({
70
- image_src,
71
- image_alt,
72
- image_background_color = "#f1f5f9",
73
- field_overrides,
74
- labels,
75
- button_colors,
76
- data_client,
77
- logger,
78
- redirectRoute,
79
- successMessage = "Successfully logged in",
80
- alreadyLoggedInMessage = "You are already logged in",
81
- showLogoutButton = true,
82
- showReturnHomeButton = false,
83
- returnHomeButtonLabel = "Return home",
84
- returnHomePath = "/",
85
- forgot_password_path = "/hazo_auth/forgot_password",
86
- forgot_password_label = "Forgot password?",
87
- create_account_path = "/hazo_auth/register",
88
- create_account_label = "Create account",
89
- urlOnLogon,
90
- }: LoginLayoutProps<TClient>) {
91
- const fieldDefinitions = createLoginFieldDefinitions(field_overrides);
92
- const resolvedLabels = resolveLoginLabels(labels);
93
- const resolvedButtonPalette = resolveLoginButtonPalette(button_colors);
94
-
95
- const form = use_login_form({
96
- dataClient: data_client,
97
- logger,
98
- redirectRoute,
99
- successMessage,
100
- urlOnLogon: urlOnLogon,
101
- });
102
-
103
- const renderFields = (formState: UseLoginFormResult) => {
104
- return ORDERED_FIELDS.map((fieldId) => {
105
- const fieldDefinition = fieldDefinitions[fieldId];
106
- const fieldValue = formState.values[fieldId];
107
- const fieldError = formState.errors[fieldId];
108
-
109
- const isPasswordField = fieldDefinition.type === "password";
110
-
111
- const inputElement = isPasswordField ? (
112
- <PasswordField
113
- inputId={fieldDefinition.id}
114
- ariaLabel={fieldDefinition.ariaLabel}
115
- value={fieldValue}
116
- placeholder={fieldDefinition.placeholder}
117
- autoComplete={fieldDefinition.autoComplete}
118
- isVisible={formState.passwordVisibility.password}
119
- onChange={(nextValue) => formState.handleFieldChange(fieldId, nextValue)}
120
- onToggleVisibility={formState.togglePasswordVisibility}
121
- errorMessage={fieldError}
122
- />
123
- ) : (
124
- <Input
125
- id={fieldDefinition.id}
126
- type={fieldDefinition.type}
127
- value={fieldValue}
128
- onChange={(event) =>
129
- formState.handleFieldChange(fieldId, event.target.value)
130
- }
131
- onBlur={
132
- fieldId === LOGIN_FIELD_IDS.EMAIL
133
- ? formState.handleEmailBlur
134
- : undefined
135
- }
136
- autoComplete={fieldDefinition.autoComplete}
137
- placeholder={fieldDefinition.placeholder}
138
- aria-label={fieldDefinition.ariaLabel}
139
- className="cls_login_layout_field_input"
140
- />
141
- );
142
-
143
- // Only show email error if field has been touched (blurred)
144
- const shouldShowError =
145
- isPasswordField
146
- ? undefined
147
- : fieldId === LOGIN_FIELD_IDS.EMAIL
148
- ? formState.emailTouched && fieldError
149
- ? fieldError
150
- : undefined
151
- : fieldError;
152
-
153
- return (
154
- <FormFieldWrapper
155
- key={fieldId}
156
- fieldId={fieldDefinition.id}
157
- label={fieldDefinition.label}
158
- input={inputElement}
159
- errorMessage={shouldShowError}
160
- />
161
- );
162
- });
163
- };
164
-
165
- // Show success message if login was successful and no redirect route is provided
166
- if (form.isSuccess) {
167
- return (
168
- <TwoColumnAuthLayout
169
- imageSrc={image_src}
170
- imageAlt={image_alt}
171
- imageBackgroundColor={image_background_color}
172
- formContent={
173
- <>
174
- <FormHeader
175
- heading={resolvedLabels.heading}
176
- subHeading={resolvedLabels.subHeading}
177
- />
178
- <div className="cls_login_layout_success flex flex-col items-center justify-center gap-4 p-8 text-center">
179
- <CheckCircle
180
- className="cls_login_layout_success_icon h-16 w-16 text-green-600"
181
- aria-hidden="true"
182
- />
183
- <p className="cls_login_layout_success_message text-lg font-medium text-slate-900">
184
- {successMessage}
185
- </p>
186
- </div>
187
- </>
188
- }
189
- />
190
- );
191
- }
192
-
193
- return (
194
- <AlreadyLoggedInGuard
195
- image_src={image_src}
196
- image_alt={image_alt}
197
- image_background_color={image_background_color}
198
- message={alreadyLoggedInMessage}
199
- showLogoutButton={showLogoutButton}
200
- showReturnHomeButton={showReturnHomeButton}
201
- returnHomeButtonLabel={returnHomeButtonLabel}
202
- returnHomePath={returnHomePath}
203
- >
204
- <TwoColumnAuthLayout
205
- imageSrc={image_src}
206
- imageAlt={image_alt}
207
- imageBackgroundColor={image_background_color}
208
- formContent={
209
- <>
210
- <FormHeader
211
- heading={resolvedLabels.heading}
212
- subHeading={resolvedLabels.subHeading}
213
- />
214
- <form
215
- className="cls_login_layout_form_fields flex flex-col gap-5"
216
- onSubmit={form.handleSubmit}
217
- aria-label="Login form"
218
- >
219
- {renderFields(form)}
220
- <FormActionButtons
221
- submitLabel={resolvedLabels.submitButton}
222
- cancelLabel={resolvedLabels.cancelButton}
223
- buttonPalette={resolvedButtonPalette}
224
- isSubmitDisabled={form.isSubmitDisabled}
225
- onCancel={form.handleCancel}
226
- submitAriaLabel="Submit login form"
227
- cancelAriaLabel="Cancel login form"
228
- />
229
- <div className="cls_login_layout_support_links flex flex-col gap-1 text-sm text-muted-foreground">
230
- <Link
231
- href={forgot_password_path}
232
- className="cls_login_layout_forgot_password_link text-primary underline-offset-4 hover:underline"
233
- aria-label="Go to forgot password page"
234
- >
235
- {forgot_password_label}
236
- </Link>
237
- <Link
238
- href={create_account_path}
239
- className="cls_login_layout_create_account_link text-primary underline-offset-4 hover:underline"
240
- aria-label="Go to create account page"
241
- >
242
- {create_account_label}
243
- </Link>
244
- </div>
245
- </form>
246
- </>
247
- }
248
- />
249
- </AlreadyLoggedInGuard>
250
- );
251
- }
252
-