hazo_auth 1.3.0 → 1.4.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.
- package/README.md +383 -774
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +5 -0
- package/dist/components/layouts/email_verification/config/email_verification_field_config.d.ts +23 -0
- package/dist/components/layouts/email_verification/config/email_verification_field_config.d.ts.map +1 -0
- package/dist/components/layouts/email_verification/config/email_verification_field_config.js +44 -0
- package/dist/components/layouts/email_verification/hooks/use_email_verification.d.ts +31 -0
- package/dist/components/layouts/email_verification/hooks/use_email_verification.d.ts.map +1 -0
- package/dist/components/layouts/email_verification/hooks/use_email_verification.js +222 -0
- package/dist/components/layouts/email_verification/index.d.ts +23 -0
- package/dist/components/layouts/email_verification/index.d.ts.map +1 -0
- package/dist/components/layouts/email_verification/index.js +61 -0
- package/dist/components/layouts/forgot_password/config/forgot_password_field_config.d.ts +10 -0
- package/dist/components/layouts/forgot_password/config/forgot_password_field_config.d.ts.map +1 -0
- package/dist/components/layouts/forgot_password/config/forgot_password_field_config.js +33 -0
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts +22 -0
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts.map +1 -0
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.js +127 -0
- package/dist/components/layouts/forgot_password/index.d.ts +18 -0
- package/dist/components/layouts/forgot_password/index.d.ts.map +1 -0
- package/dist/components/layouts/forgot_password/index.js +43 -0
- package/dist/components/layouts/index.d.ts +16 -0
- package/dist/components/layouts/index.d.ts.map +1 -0
- package/dist/components/layouts/index.js +11 -0
- package/dist/components/layouts/login/config/login_field_config.d.ts +11 -0
- package/dist/components/layouts/login/config/login_field_config.d.ts.map +1 -0
- package/dist/components/layouts/login/config/login_field_config.js +42 -0
- package/dist/components/layouts/login/hooks/use_login_form.d.ts +34 -0
- package/dist/components/layouts/login/hooks/use_login_form.d.ts.map +1 -0
- package/dist/components/layouts/login/hooks/use_login_form.js +196 -0
- package/dist/components/layouts/login/index.d.ts +31 -0
- package/dist/components/layouts/login/index.d.ts.map +1 -0
- package/dist/components/layouts/login/index.js +58 -0
- package/dist/components/layouts/my_settings/components/editable_field.d.ts +19 -0
- package/dist/components/layouts/my_settings/components/editable_field.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/editable_field.js +73 -0
- package/dist/components/layouts/my_settings/components/password_change_dialog.d.ts +28 -0
- package/dist/components/layouts/my_settings/components/password_change_dialog.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/password_change_dialog.js +138 -0
- package/dist/components/layouts/my_settings/components/profile_picture_dialog.d.ts +42 -0
- package/dist/components/layouts/my_settings/components/profile_picture_dialog.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/profile_picture_dialog.js +198 -0
- package/dist/components/layouts/my_settings/components/profile_picture_display.d.ts +16 -0
- package/dist/components/layouts/my_settings/components/profile_picture_display.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/profile_picture_display.js +33 -0
- package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.d.ts +17 -0
- package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.js +48 -0
- package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts +21 -0
- package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/profile_picture_library_tab.js +144 -0
- package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.d.ts +23 -0
- package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.js +169 -0
- package/dist/components/layouts/my_settings/config/my_settings_field_config.d.ts +19 -0
- package/dist/components/layouts/my_settings/config/my_settings_field_config.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/config/my_settings_field_config.js +26 -0
- package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts +46 -0
- package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/hooks/use_my_settings.js +354 -0
- package/dist/components/layouts/my_settings/index.d.ts +64 -0
- package/dist/components/layouts/my_settings/index.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/index.js +65 -0
- package/dist/components/layouts/register/config/register_field_config.d.ts +14 -0
- package/dist/components/layouts/register/config/register_field_config.d.ts.map +1 -0
- package/dist/components/layouts/register/config/register_field_config.js +69 -0
- package/dist/components/layouts/register/hooks/use_register_form.d.ts +30 -0
- package/dist/components/layouts/register/hooks/use_register_form.d.ts.map +1 -0
- package/dist/components/layouts/register/hooks/use_register_form.js +184 -0
- package/dist/components/layouts/register/index.d.ts +23 -0
- package/dist/components/layouts/register/index.d.ts.map +1 -0
- package/dist/components/layouts/register/index.js +58 -0
- package/dist/components/layouts/reset_password/config/reset_password_field_config.d.ts +13 -0
- package/dist/components/layouts/reset_password/config/reset_password_field_config.d.ts.map +1 -0
- package/dist/components/layouts/reset_password/config/reset_password_field_config.js +53 -0
- package/dist/components/layouts/reset_password/hooks/use_reset_password_form.d.ts +28 -0
- package/dist/components/layouts/reset_password/hooks/use_reset_password_form.d.ts.map +1 -0
- package/dist/components/layouts/reset_password/hooks/use_reset_password_form.js +201 -0
- package/dist/components/layouts/reset_password/index.d.ts +23 -0
- package/dist/components/layouts/reset_password/index.d.ts.map +1 -0
- package/dist/components/layouts/reset_password/index.js +53 -0
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts +20 -0
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/already_logged_in_guard.js +32 -0
- package/dist/components/layouts/shared/components/auth_page_shell.d.ts +7 -0
- package/dist/components/layouts/shared/components/auth_page_shell.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/auth_page_shell.js +12 -0
- package/dist/components/layouts/shared/components/field_error_message.d.ts +7 -0
- package/dist/components/layouts/shared/components/field_error_message.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/field_error_message.js +6 -0
- package/dist/components/layouts/shared/components/form_action_buttons.d.ts +14 -0
- package/dist/components/layouts/shared/components/form_action_buttons.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/form_action_buttons.js +15 -0
- package/dist/components/layouts/shared/components/form_field_wrapper.d.ts +11 -0
- package/dist/components/layouts/shared/components/form_field_wrapper.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/form_field_wrapper.js +9 -0
- package/dist/components/layouts/shared/components/form_header.d.ts +10 -0
- package/dist/components/layouts/shared/components/form_header.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/form_header.js +5 -0
- package/dist/components/layouts/shared/components/logout_button.d.ts +7 -0
- package/dist/components/layouts/shared/components/logout_button.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/logout_button.js +44 -0
- package/dist/components/layouts/shared/components/password_field.d.ts +13 -0
- package/dist/components/layouts/shared/components/password_field.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/password_field.js +13 -0
- package/dist/components/layouts/shared/components/profile_pic_menu.d.ts +22 -0
- package/dist/components/layouts/shared/components/profile_pic_menu.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/profile_pic_menu.js +169 -0
- package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts +12 -0
- package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.js +16 -0
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts +6 -0
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +15 -0
- package/dist/components/layouts/shared/components/standalone_layout_wrapper.d.ts +11 -0
- package/dist/components/layouts/shared/components/standalone_layout_wrapper.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/standalone_layout_wrapper.js +10 -0
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts +12 -0
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/two_column_auth_layout.js +8 -0
- package/dist/components/layouts/shared/components/unauthorized_guard.d.ts +14 -0
- package/dist/components/layouts/shared/components/unauthorized_guard.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/unauthorized_guard.js +30 -0
- package/dist/components/layouts/shared/components/visual_panel.d.ts +9 -0
- package/dist/components/layouts/shared/components/visual_panel.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/visual_panel.js +10 -0
- package/dist/components/layouts/shared/config/layout_customization.d.ts +38 -0
- package/dist/components/layouts/shared/config/layout_customization.d.ts.map +1 -0
- package/dist/components/layouts/shared/config/layout_customization.js +19 -0
- package/dist/components/layouts/shared/data/layout_data_client.d.ts +6 -0
- package/dist/components/layouts/shared/data/layout_data_client.d.ts.map +1 -0
- package/dist/components/layouts/shared/data/layout_data_client.js +9 -0
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +20 -0
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -0
- package/dist/components/layouts/shared/hooks/use_auth_status.js +71 -0
- package/dist/components/layouts/shared/hooks/use_hazo_auth.d.ts +48 -0
- package/dist/components/layouts/shared/hooks/use_hazo_auth.d.ts.map +1 -0
- package/dist/components/layouts/shared/hooks/use_hazo_auth.js +90 -0
- package/dist/components/layouts/shared/index.d.ts +24 -0
- package/dist/components/layouts/shared/index.d.ts.map +1 -0
- package/dist/components/layouts/shared/index.js +27 -0
- package/dist/components/layouts/shared/utils/ip_address.d.ts +7 -0
- package/dist/components/layouts/shared/utils/ip_address.d.ts.map +1 -0
- package/dist/components/layouts/shared/utils/ip_address.js +34 -0
- package/dist/components/layouts/shared/utils/validation.d.ts +15 -0
- package/dist/components/layouts/shared/utils/validation.d.ts.map +1 -0
- package/dist/components/layouts/shared/utils/validation.js +45 -0
- package/dist/components/layouts/user_management/components/roles_matrix.d.ts +29 -0
- package/dist/components/layouts/user_management/components/roles_matrix.d.ts.map +1 -0
- package/dist/components/layouts/user_management/components/roles_matrix.js +287 -0
- package/dist/components/layouts/user_management/index.d.ts +13 -0
- package/dist/components/layouts/user_management/index.d.ts.map +1 -0
- package/dist/components/layouts/user_management/index.js +495 -0
- package/dist/components/ui/alert-dialog.d.ts +21 -0
- package/dist/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/components/ui/alert-dialog.js +62 -0
- package/dist/components/ui/avatar.d.ts +7 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/avatar.js +32 -0
- package/dist/components/ui/button.d.ts +12 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +45 -0
- package/dist/components/ui/checkbox.d.ts +5 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/checkbox.js +23 -0
- package/dist/components/ui/dialog.d.ts +20 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dialog.js +52 -0
- package/dist/components/ui/dropdown-menu.d.ts +28 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.js +72 -0
- package/dist/components/ui/hazo_ui_tooltip.d.ts +26 -0
- package/dist/components/ui/hazo_ui_tooltip.d.ts.map +1 -0
- package/dist/components/ui/hazo_ui_tooltip.js +17 -0
- package/dist/components/ui/index.d.ts +20 -0
- package/dist/components/ui/index.d.ts.map +1 -0
- package/dist/components/ui/index.js +21 -0
- package/dist/components/ui/input.d.ts +4 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +20 -0
- package/dist/components/ui/label.d.ts +6 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +24 -0
- package/dist/components/ui/separator.d.ts +5 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/separator.js +22 -0
- package/dist/components/ui/sheet.d.ts +23 -0
- package/dist/components/ui/sheet.d.ts.map +1 -0
- package/dist/components/ui/sheet.js +66 -0
- package/dist/components/ui/sidebar.d.ts +66 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/sidebar.js +267 -0
- package/dist/components/ui/skeleton.d.ts +3 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +18 -0
- package/dist/components/ui/sonner.d.ts +5 -0
- package/dist/components/ui/sonner.d.ts.map +1 -0
- package/dist/components/ui/sonner.js +28 -0
- package/dist/components/ui/switch.d.ts +5 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/switch.js +22 -0
- package/dist/components/ui/table.d.ts +11 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/table.js +55 -0
- package/dist/components/ui/tabs.d.ts +8 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/tabs.js +33 -0
- package/dist/components/ui/tooltip.d.ts +8 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +25 -0
- package/dist/components/ui/vertical-tabs.d.ts +8 -0
- package/dist/components/ui/vertical-tabs.d.ts.map +1 -0
- package/dist/components/ui/vertical-tabs.js +37 -0
- package/dist/hooks/use-mobile.d.ts +2 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-mobile.js +15 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/lib/already_logged_in_config.server.d.ts +14 -0
- package/dist/lib/already_logged_in_config.server.d.ts.map +1 -0
- package/dist/lib/already_logged_in_config.server.js +29 -0
- package/dist/lib/app_logger.d.ts +12 -0
- package/dist/lib/app_logger.d.ts.map +1 -0
- package/dist/lib/app_logger.js +14 -0
- package/dist/lib/auth/auth_cache.d.ts +83 -0
- package/dist/lib/auth/auth_cache.d.ts.map +1 -0
- package/dist/lib/auth/auth_cache.js +158 -0
- package/dist/lib/auth/auth_rate_limiter.d.ts +39 -0
- package/dist/lib/auth/auth_rate_limiter.d.ts.map +1 -0
- package/dist/lib/auth/auth_rate_limiter.js +95 -0
- package/dist/lib/auth/auth_types.d.ts +53 -0
- package/dist/lib/auth/auth_types.d.ts.map +1 -0
- package/dist/lib/auth/auth_types.js +16 -0
- package/dist/lib/auth/auth_utils.server.d.ts +47 -0
- package/dist/lib/auth/auth_utils.server.d.ts.map +1 -0
- package/dist/lib/auth/auth_utils.server.js +150 -0
- package/dist/lib/auth/hazo_get_auth.server.d.ts +12 -0
- package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -0
- package/dist/lib/auth/hazo_get_auth.server.js +256 -0
- package/dist/lib/auth/index.d.ts +9 -0
- package/dist/lib/auth/index.d.ts.map +1 -0
- package/dist/lib/auth/index.js +12 -0
- package/dist/lib/auth/server_auth.d.ts +26 -0
- package/dist/lib/auth/server_auth.d.ts.map +1 -0
- package/dist/lib/auth/server_auth.js +62 -0
- package/dist/lib/auth_utility_config.server.d.ts +20 -0
- package/dist/lib/auth_utility_config.server.d.ts.map +1 -0
- package/dist/lib/auth_utility_config.server.js +64 -0
- package/dist/lib/config/config_loader.server.d.ts +44 -0
- package/dist/lib/config/config_loader.server.d.ts.map +1 -0
- package/dist/lib/config/config_loader.server.js +122 -0
- package/dist/lib/email_verification_config.server.d.ts +14 -0
- package/dist/lib/email_verification_config.server.d.ts.map +1 -0
- package/dist/lib/email_verification_config.server.js +20 -0
- package/dist/lib/file_types_config.server.d.ts +11 -0
- package/dist/lib/file_types_config.server.d.ts.map +1 -0
- package/dist/lib/file_types_config.server.js +16 -0
- package/dist/lib/forgot_password_config.server.d.ts +14 -0
- package/dist/lib/forgot_password_config.server.d.ts.map +1 -0
- package/dist/lib/forgot_password_config.server.js +20 -0
- package/dist/lib/hazo_connect_instance.server.d.ts +17 -0
- package/dist/lib/hazo_connect_instance.server.d.ts.map +1 -0
- package/dist/lib/hazo_connect_instance.server.js +88 -0
- package/dist/lib/hazo_connect_setup.d.ts +2 -0
- package/dist/lib/hazo_connect_setup.d.ts.map +1 -0
- package/dist/lib/hazo_connect_setup.js +49 -0
- package/dist/lib/hazo_connect_setup.server.d.ts +20 -0
- package/dist/lib/hazo_connect_setup.server.d.ts.map +1 -0
- package/dist/lib/hazo_connect_setup.server.js +138 -0
- package/dist/lib/index.d.ts +28 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +35 -0
- package/dist/lib/login_config.server.d.ts +20 -0
- package/dist/lib/login_config.server.d.ts.map +1 -0
- package/dist/lib/login_config.server.js +37 -0
- package/dist/lib/messages_config.server.d.ts +13 -0
- package/dist/lib/messages_config.server.d.ts.map +1 -0
- package/dist/lib/messages_config.server.js +18 -0
- package/dist/lib/migrations/apply_migration.d.ts +22 -0
- package/dist/lib/migrations/apply_migration.d.ts.map +1 -0
- package/dist/lib/migrations/apply_migration.js +78 -0
- package/dist/lib/my_settings_config.server.d.ts +65 -0
- package/dist/lib/my_settings_config.server.d.ts.map +1 -0
- package/dist/lib/my_settings_config.server.js +67 -0
- package/dist/lib/password_requirements_config.server.d.ts +15 -0
- package/dist/lib/password_requirements_config.server.d.ts.map +1 -0
- package/dist/lib/password_requirements_config.server.js +26 -0
- package/dist/lib/profile_pic_menu_config.server.d.ts +26 -0
- package/dist/lib/profile_pic_menu_config.server.d.ts.map +1 -0
- package/dist/lib/profile_pic_menu_config.server.js +95 -0
- package/dist/lib/profile_picture_config.server.d.ts +16 -0
- package/dist/lib/profile_picture_config.server.d.ts.map +1 -0
- package/dist/lib/profile_picture_config.server.js +40 -0
- package/dist/lib/register_config.server.d.ts +24 -0
- package/dist/lib/register_config.server.d.ts.map +1 -0
- package/dist/lib/register_config.server.js +39 -0
- package/dist/lib/reset_password_config.server.d.ts +25 -0
- package/dist/lib/reset_password_config.server.d.ts.map +1 -0
- package/dist/lib/reset_password_config.server.js +38 -0
- package/dist/lib/services/email_service.d.ts +44 -0
- package/dist/lib/services/email_service.d.ts.map +1 -0
- package/dist/lib/services/email_service.js +480 -0
- package/dist/lib/services/email_verification_service.d.ts +35 -0
- package/dist/lib/services/email_verification_service.d.ts.map +1 -0
- package/dist/lib/services/email_verification_service.js +208 -0
- package/dist/lib/services/index.d.ts +13 -0
- package/dist/lib/services/index.d.ts.map +1 -0
- package/dist/lib/services/index.js +14 -0
- package/dist/lib/services/login_service.d.ts +20 -0
- package/dist/lib/services/login_service.d.ts.map +1 -0
- package/dist/lib/services/login_service.js +94 -0
- package/dist/lib/services/password_change_service.d.ts +19 -0
- package/dist/lib/services/password_change_service.d.ts.map +1 -0
- package/dist/lib/services/password_change_service.js +118 -0
- package/dist/lib/services/password_reset_service.d.ts +52 -0
- package/dist/lib/services/password_reset_service.d.ts.map +1 -0
- package/dist/lib/services/password_reset_service.js +318 -0
- package/dist/lib/services/profile_picture_remove_service.d.ts +15 -0
- package/dist/lib/services/profile_picture_remove_service.d.ts.map +1 -0
- package/dist/lib/services/profile_picture_remove_service.js +94 -0
- package/dist/lib/services/profile_picture_service.d.ts +45 -0
- package/dist/lib/services/profile_picture_service.d.ts.map +1 -0
- package/dist/lib/services/profile_picture_service.js +183 -0
- package/dist/lib/services/profile_picture_source_mapper.d.ts +23 -0
- package/dist/lib/services/profile_picture_source_mapper.d.ts.map +1 -0
- package/dist/lib/services/profile_picture_source_mapper.js +45 -0
- package/dist/lib/services/registration_service.d.ts +20 -0
- package/dist/lib/services/registration_service.d.ts.map +1 -0
- package/dist/lib/services/registration_service.js +147 -0
- package/dist/lib/services/token_service.d.ts +20 -0
- package/dist/lib/services/token_service.d.ts.map +1 -0
- package/dist/lib/services/token_service.js +201 -0
- package/dist/lib/services/user_profiles_service.d.ts +31 -0
- package/dist/lib/services/user_profiles_service.d.ts.map +1 -0
- package/dist/lib/services/user_profiles_service.js +99 -0
- package/dist/lib/services/user_update_service.d.ts +23 -0
- package/dist/lib/services/user_update_service.d.ts.map +1 -0
- package/dist/lib/services/user_update_service.js +103 -0
- package/dist/lib/ui_shell_config.server.d.ts +16 -0
- package/dist/lib/ui_shell_config.server.d.ts.map +1 -0
- package/dist/lib/ui_shell_config.server.js +28 -0
- package/dist/lib/ui_sizes_config.server.d.ts +17 -0
- package/dist/lib/ui_sizes_config.server.d.ts.map +1 -0
- package/dist/lib/ui_sizes_config.server.js +22 -0
- package/dist/lib/user_fields_config.server.d.ts +13 -0
- package/dist/lib/user_fields_config.server.d.ts.map +1 -0
- package/dist/lib/user_fields_config.server.js +21 -0
- package/dist/lib/user_management_config.server.d.ts +10 -0
- package/dist/lib/user_management_config.server.d.ts.map +1 -0
- package/dist/lib/user_management_config.server.js +26 -0
- package/dist/lib/utils/api_route_helpers.d.ts +13 -0
- package/dist/lib/utils/api_route_helpers.d.ts.map +1 -0
- package/dist/lib/utils/api_route_helpers.js +58 -0
- package/dist/lib/utils/error_sanitizer.d.ts +16 -0
- package/dist/lib/utils/error_sanitizer.d.ts.map +1 -0
- package/dist/lib/utils/error_sanitizer.js +39 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +9 -0
- package/dist/server/config/config_loader.d.ts +26 -0
- package/dist/server/config/config_loader.d.ts.map +1 -0
- package/dist/server/config/config_loader.js +329 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +32 -0
- package/dist/server/logging/logger_service.d.ts +3 -0
- package/dist/server/logging/logger_service.d.ts.map +1 -0
- package/dist/server/logging/logger_service.js +37 -0
- package/dist/server/routes/root_router.d.ts +3 -0
- package/dist/server/routes/root_router.d.ts.map +1 -0
- package/dist/server/routes/root_router.js +14 -0
- package/dist/server/server.d.ts +3 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +25 -0
- package/dist/server/types/app_types.d.ts +53 -0
- package/dist/server/types/app_types.d.ts.map +1 -0
- package/dist/server/types/app_types.js +1 -0
- package/migrations/003_add_url_on_logon_to_hazo_users.sql +8 -0
- package/next.config.mjs +12 -0
- package/package.json +38 -1
- package/src/components/index.ts +7 -0
- package/src/components/layouts/email_verification/config/email_verification_field_config.ts +2 -2
- package/src/components/layouts/email_verification/hooks/use_email_verification.ts +3 -3
- package/src/components/layouts/email_verification/index.tsx +11 -11
- package/src/components/layouts/forgot_password/config/forgot_password_field_config.ts +2 -2
- package/src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts +3 -3
- package/src/components/layouts/forgot_password/index.tsx +10 -10
- package/src/components/layouts/index.ts +26 -0
- package/src/components/layouts/login/config/login_field_config.ts +2 -2
- package/src/components/layouts/login/hooks/use_login_form.ts +5 -5
- package/src/components/layouts/login/index.tsx +11 -11
- package/src/components/layouts/my_settings/components/editable_field.tsx +3 -3
- package/src/components/layouts/my_settings/components/password_change_dialog.tsx +5 -5
- package/src/components/layouts/my_settings/components/profile_picture_dialog.tsx +7 -7
- package/src/components/layouts/my_settings/components/profile_picture_display.tsx +2 -2
- package/src/components/layouts/my_settings/components/profile_picture_gravatar_tab.tsx +3 -3
- package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +5 -5
- package/src/components/layouts/my_settings/components/profile_picture_upload_tab.tsx +4 -4
- package/src/components/layouts/my_settings/config/my_settings_field_config.ts +2 -2
- package/src/components/layouts/my_settings/hooks/use_my_settings.ts +2 -2
- package/src/components/layouts/my_settings/index.tsx +10 -10
- package/src/components/layouts/register/config/register_field_config.ts +2 -2
- package/src/components/layouts/register/hooks/use_register_form.ts +4 -4
- package/src/components/layouts/register/index.tsx +11 -11
- package/src/components/layouts/reset_password/config/reset_password_field_config.ts +2 -2
- package/src/components/layouts/reset_password/hooks/use_reset_password_form.ts +4 -4
- package/src/components/layouts/reset_password/index.tsx +10 -10
- package/src/components/layouts/shared/components/already_logged_in_guard.tsx +4 -4
- package/src/components/layouts/shared/components/auth_page_shell.tsx +3 -3
- package/src/components/layouts/shared/components/form_action_buttons.tsx +2 -2
- package/src/components/layouts/shared/components/form_field_wrapper.tsx +2 -2
- package/src/components/layouts/shared/components/logout_button.tsx +2 -2
- package/src/components/layouts/shared/components/password_field.tsx +3 -3
- package/src/components/layouts/shared/components/profile_pic_menu.tsx +5 -5
- package/src/components/layouts/shared/components/profile_pic_menu_wrapper.tsx +2 -2
- package/src/components/layouts/shared/components/sidebar_layout_wrapper.tsx +3 -3
- package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +1 -1
- package/src/components/layouts/shared/components/two_column_auth_layout.tsx +1 -1
- package/src/components/layouts/shared/components/unauthorized_guard.tsx +2 -2
- package/src/components/layouts/shared/hooks/use_hazo_auth.ts +1 -1
- package/src/components/layouts/shared/index.ts +34 -0
- package/src/components/layouts/shared/utils/validation.ts +1 -1
- package/src/components/layouts/user_management/components/roles_matrix.tsx +7 -7
- package/src/components/layouts/user_management/index.tsx +11 -11
- package/src/components/ui/alert-dialog.tsx +2 -2
- package/src/components/ui/avatar.tsx +1 -1
- package/src/components/ui/button.tsx +1 -1
- package/src/components/ui/checkbox.tsx +1 -1
- package/src/components/ui/dialog.tsx +1 -1
- package/src/components/ui/dropdown-menu.tsx +1 -1
- package/src/components/ui/hazo_ui_tooltip.tsx +1 -1
- package/src/components/ui/index.ts +22 -0
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/label.tsx +1 -1
- package/src/components/ui/separator.tsx +1 -1
- package/src/components/ui/sheet.tsx +1 -1
- package/src/components/ui/sidebar.tsx +8 -8
- package/src/components/ui/skeleton.tsx +1 -1
- package/src/components/ui/switch.tsx +1 -1
- package/src/components/ui/table.tsx +1 -1
- package/src/components/ui/tabs.tsx +1 -1
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/components/ui/vertical-tabs.tsx +1 -1
- package/src/index.ts +7 -0
- package/src/lib/already_logged_in_config.server.ts +1 -1
- package/src/lib/app_logger.ts +1 -1
- package/src/lib/auth/auth_cache.ts +1 -1
- package/src/lib/auth/auth_utils.server.ts +2 -2
- package/src/lib/auth/hazo_get_auth.server.ts +8 -8
- package/src/lib/auth/index.ts +23 -0
- package/src/lib/auth/server_auth.ts +2 -2
- package/src/lib/auth_utility_config.server.ts +1 -1
- package/src/lib/config/config_loader.server.ts +1 -1
- package/src/lib/email_verification_config.server.ts +1 -1
- package/src/lib/file_types_config.server.ts +1 -1
- package/src/lib/forgot_password_config.server.ts +1 -1
- package/src/lib/hazo_connect_instance.server.ts +2 -2
- package/src/lib/hazo_connect_setup.server.ts +2 -2
- package/src/lib/index.ts +44 -0
- package/src/lib/login_config.server.ts +2 -2
- package/src/lib/messages_config.server.ts +1 -1
- package/src/lib/my_settings_config.server.ts +7 -7
- package/src/lib/password_requirements_config.server.ts +1 -1
- package/src/lib/profile_pic_menu_config.server.ts +1 -1
- package/src/lib/profile_picture_config.server.ts +2 -2
- package/src/lib/register_config.server.ts +4 -4
- package/src/lib/reset_password_config.server.ts +3 -3
- package/src/lib/services/email_service.ts +2 -2
- package/src/lib/services/email_verification_service.ts +3 -3
- package/src/lib/services/index.ts +15 -0
- package/src/lib/services/login_service.ts +3 -3
- package/src/lib/services/password_change_service.ts +3 -3
- package/src/lib/services/password_reset_service.ts +3 -3
- package/src/lib/services/profile_picture_remove_service.ts +3 -3
- package/src/lib/services/profile_picture_service.ts +5 -5
- package/src/lib/services/registration_service.ts +8 -8
- package/src/lib/services/token_service.ts +2 -2
- package/src/lib/services/user_profiles_service.ts +2 -2
- package/src/lib/services/user_update_service.ts +4 -4
- package/src/lib/ui_shell_config.server.ts +1 -1
- package/src/lib/ui_sizes_config.server.ts +1 -1
- package/src/lib/user_fields_config.server.ts +1 -1
- package/src/lib/user_management_config.server.ts +1 -2
- package/src/lib/utils/error_sanitizer.ts +1 -1
- package/src/routes/index.ts +34 -0
- package/src/server/config/config_loader.ts +2 -2
- package/src/server/index.ts +2 -2
- package/src/server/logging/logger_service.ts +1 -1
- package/src/server/server.ts +2 -2
- package/src/server/types/express.d.ts +1 -1
- package/tsconfig.build.json +39 -0
- package/tsconfig.json +5 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// file_description: encapsulate forgot password form state, validation, and data interactions
|
|
2
|
+
// section: imports
|
|
3
|
+
import { useCallback, useMemo, useState } from "react";
|
|
4
|
+
import { toast } from "sonner";
|
|
5
|
+
import { FORGOT_PASSWORD_FIELD_IDS } from "hazo_auth/components/layouts/forgot_password/config/forgot_password_field_config";
|
|
6
|
+
import { validateEmail } from "hazo_auth/components/layouts/shared/utils/validation";
|
|
7
|
+
// section: helpers
|
|
8
|
+
const buildInitialValues = () => ({
|
|
9
|
+
[FORGOT_PASSWORD_FIELD_IDS.EMAIL]: "",
|
|
10
|
+
});
|
|
11
|
+
// section: hook
|
|
12
|
+
export const use_forgot_password_form = ({ dataClient, }) => {
|
|
13
|
+
const [values, setValues] = useState(buildInitialValues);
|
|
14
|
+
const [errors, setErrors] = useState({});
|
|
15
|
+
const [emailTouched, setEmailTouched] = useState(false);
|
|
16
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
17
|
+
const isSubmitDisabled = useMemo(() => {
|
|
18
|
+
if (isSubmitting) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const hasEmptyField = Object.values(values).some((fieldValue) => fieldValue.trim() === "");
|
|
22
|
+
const hasErrors = Object.keys(errors).length > 0;
|
|
23
|
+
return hasEmptyField || hasErrors;
|
|
24
|
+
}, [errors, values, isSubmitting]);
|
|
25
|
+
const handleFieldChange = useCallback((fieldId, value) => {
|
|
26
|
+
setValues((previousValues) => {
|
|
27
|
+
const nextValues = Object.assign(Object.assign({}, previousValues), { [fieldId]: value });
|
|
28
|
+
setErrors((previousErrors) => {
|
|
29
|
+
const updatedErrors = Object.assign({}, previousErrors);
|
|
30
|
+
// Only validate email on change if it has been touched (blurred)
|
|
31
|
+
if (fieldId === FORGOT_PASSWORD_FIELD_IDS.EMAIL && emailTouched) {
|
|
32
|
+
const emailError = validateEmail(value);
|
|
33
|
+
if (emailError) {
|
|
34
|
+
updatedErrors[FORGOT_PASSWORD_FIELD_IDS.EMAIL] = emailError;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
delete updatedErrors[FORGOT_PASSWORD_FIELD_IDS.EMAIL];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return updatedErrors;
|
|
41
|
+
});
|
|
42
|
+
return nextValues;
|
|
43
|
+
});
|
|
44
|
+
}, [emailTouched]);
|
|
45
|
+
const handleEmailBlur = useCallback(() => {
|
|
46
|
+
setEmailTouched(true);
|
|
47
|
+
// Validate email on blur
|
|
48
|
+
setErrors((previousErrors) => {
|
|
49
|
+
const updatedErrors = Object.assign({}, previousErrors);
|
|
50
|
+
const emailValue = values[FORGOT_PASSWORD_FIELD_IDS.EMAIL];
|
|
51
|
+
const emailError = validateEmail(emailValue);
|
|
52
|
+
if (emailError) {
|
|
53
|
+
updatedErrors[FORGOT_PASSWORD_FIELD_IDS.EMAIL] = emailError;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
delete updatedErrors[FORGOT_PASSWORD_FIELD_IDS.EMAIL];
|
|
57
|
+
}
|
|
58
|
+
return updatedErrors;
|
|
59
|
+
});
|
|
60
|
+
}, [values]);
|
|
61
|
+
const handleSubmit = useCallback(async (event) => {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
// Final validation
|
|
64
|
+
const emailError = validateEmail(values[FORGOT_PASSWORD_FIELD_IDS.EMAIL]);
|
|
65
|
+
if (emailError) {
|
|
66
|
+
setErrors({
|
|
67
|
+
[FORGOT_PASSWORD_FIELD_IDS.EMAIL]: emailError,
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
setIsSubmitting(true);
|
|
72
|
+
setErrors({});
|
|
73
|
+
try {
|
|
74
|
+
const response = await fetch("/api/hazo_auth/forgot_password", {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers: {
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
email: values[FORGOT_PASSWORD_FIELD_IDS.EMAIL],
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
const data = await response.json();
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
throw new Error(data.error || "Password reset request failed");
|
|
86
|
+
}
|
|
87
|
+
// Show success notification
|
|
88
|
+
toast.success("Password reset link sent", {
|
|
89
|
+
description: "If an account with that email exists, a password reset link has been sent.",
|
|
90
|
+
});
|
|
91
|
+
// Reset form on success
|
|
92
|
+
setValues(buildInitialValues());
|
|
93
|
+
setErrors({});
|
|
94
|
+
setEmailTouched(false);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const errorMessage = error instanceof Error ? error.message : "Password reset request failed. Please try again.";
|
|
98
|
+
// Show error notification
|
|
99
|
+
toast.error("Password reset failed", {
|
|
100
|
+
description: errorMessage,
|
|
101
|
+
});
|
|
102
|
+
// Set error state
|
|
103
|
+
setErrors({
|
|
104
|
+
submit: errorMessage,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
setIsSubmitting(false);
|
|
109
|
+
}
|
|
110
|
+
}, [values, dataClient]);
|
|
111
|
+
const handleCancel = useCallback(() => {
|
|
112
|
+
setValues(buildInitialValues());
|
|
113
|
+
setErrors({});
|
|
114
|
+
setEmailTouched(false);
|
|
115
|
+
}, []);
|
|
116
|
+
return {
|
|
117
|
+
values,
|
|
118
|
+
errors,
|
|
119
|
+
isSubmitDisabled,
|
|
120
|
+
isSubmitting,
|
|
121
|
+
emailTouched,
|
|
122
|
+
handleFieldChange,
|
|
123
|
+
handleEmailBlur,
|
|
124
|
+
handleSubmit,
|
|
125
|
+
handleCancel,
|
|
126
|
+
};
|
|
127
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ButtonPaletteOverrides, type LayoutFieldMapOverrides, type LayoutLabelOverrides } from "hazo_auth/components/layouts/shared/config/layout_customization";
|
|
2
|
+
import { type LayoutDataClient } from "hazo_auth/components/layouts/shared/data/layout_data_client";
|
|
3
|
+
export type ForgotPasswordLayoutProps<TClient = unknown> = {
|
|
4
|
+
image_src: string;
|
|
5
|
+
image_alt: string;
|
|
6
|
+
image_background_color?: string;
|
|
7
|
+
field_overrides?: LayoutFieldMapOverrides;
|
|
8
|
+
labels?: LayoutLabelOverrides;
|
|
9
|
+
button_colors?: ButtonPaletteOverrides;
|
|
10
|
+
data_client: LayoutDataClient<TClient>;
|
|
11
|
+
alreadyLoggedInMessage?: string;
|
|
12
|
+
showLogoutButton?: boolean;
|
|
13
|
+
showReturnHomeButton?: boolean;
|
|
14
|
+
returnHomeButtonLabel?: string;
|
|
15
|
+
returnHomePath?: string;
|
|
16
|
+
};
|
|
17
|
+
export default function forgot_password_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, data_client, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, }: ForgotPasswordLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/forgot_password/index.tsx"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,iEAAiE,CAAC;AAWzE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,6DAA6D,CAAC;AAGpG,MAAM,MAAM,yBAAyB,CAAC,OAAO,GAAG,OAAO,IAAI;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AASF,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,OAAO,EAAE,EACtD,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,WAAW,EACX,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,GACrB,EAAE,yBAAyB,CAAC,OAAO,CAAC,2CAsGpC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// file_description: forgot password layout component built atop shared layout utilities
|
|
2
|
+
// section: client_directive
|
|
3
|
+
"use client";
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
5
|
+
// section: imports
|
|
6
|
+
import { Input } from "hazo_auth/components/ui/input";
|
|
7
|
+
import { FormFieldWrapper } from "hazo_auth/components/layouts/shared/components/form_field_wrapper";
|
|
8
|
+
import { FormHeader } from "hazo_auth/components/layouts/shared/components/form_header";
|
|
9
|
+
import { FormActionButtons } from "hazo_auth/components/layouts/shared/components/form_action_buttons";
|
|
10
|
+
import { TwoColumnAuthLayout } from "hazo_auth/components/layouts/shared/components/two_column_auth_layout";
|
|
11
|
+
import { AlreadyLoggedInGuard } from "hazo_auth/components/layouts/shared/components/already_logged_in_guard";
|
|
12
|
+
import { FORGOT_PASSWORD_FIELD_IDS, createForgotPasswordFieldDefinitions, resolveForgotPasswordButtonPalette, resolveForgotPasswordLabels, } from "hazo_auth/components/layouts/forgot_password/config/forgot_password_field_config";
|
|
13
|
+
import { use_forgot_password_form, } from "hazo_auth/components/layouts/forgot_password/hooks/use_forgot_password_form";
|
|
14
|
+
const ORDERED_FIELDS = [
|
|
15
|
+
FORGOT_PASSWORD_FIELD_IDS.EMAIL,
|
|
16
|
+
];
|
|
17
|
+
// section: component
|
|
18
|
+
export default function forgot_password_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, data_client, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", }) {
|
|
19
|
+
const fieldDefinitions = createForgotPasswordFieldDefinitions(field_overrides);
|
|
20
|
+
const resolvedLabels = resolveForgotPasswordLabels(labels);
|
|
21
|
+
const resolvedButtonPalette = resolveForgotPasswordButtonPalette(button_colors);
|
|
22
|
+
const form = use_forgot_password_form({
|
|
23
|
+
dataClient: data_client,
|
|
24
|
+
});
|
|
25
|
+
const renderFields = (formState) => {
|
|
26
|
+
return ORDERED_FIELDS.map((fieldId) => {
|
|
27
|
+
const fieldDefinition = fieldDefinitions[fieldId];
|
|
28
|
+
const fieldValue = formState.values[fieldId];
|
|
29
|
+
const fieldError = formState.errors[fieldId];
|
|
30
|
+
const inputElement = (_jsx(Input, { id: fieldDefinition.id, type: fieldDefinition.type, value: fieldValue, onChange: (event) => formState.handleFieldChange(fieldId, event.target.value), onBlur: fieldId === FORGOT_PASSWORD_FIELD_IDS.EMAIL
|
|
31
|
+
? formState.handleEmailBlur
|
|
32
|
+
: undefined, autoComplete: fieldDefinition.autoComplete, placeholder: fieldDefinition.placeholder, "aria-label": fieldDefinition.ariaLabel, className: "cls_forgot_password_layout_field_input" }));
|
|
33
|
+
// Only show email error if field has been touched (blurred)
|
|
34
|
+
const shouldShowError = fieldId === FORGOT_PASSWORD_FIELD_IDS.EMAIL
|
|
35
|
+
? formState.emailTouched && fieldError
|
|
36
|
+
? fieldError
|
|
37
|
+
: undefined
|
|
38
|
+
: fieldError;
|
|
39
|
+
return (_jsx(FormFieldWrapper, { fieldId: fieldDefinition.id, label: fieldDefinition.label, input: inputElement, errorMessage: shouldShowError }, fieldId));
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsx(FormHeader, { heading: resolvedLabels.heading, subHeading: resolvedLabels.subHeading }), _jsxs("form", { className: "cls_forgot_password_layout_form_fields flex flex-col gap-5", onSubmit: form.handleSubmit, "aria-label": "Forgot password form", children: [renderFields(form), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: form.isSubmitDisabled, onCancel: form.handleCancel, submitAriaLabel: "Submit forgot password form", cancelAriaLabel: "Cancel forgot password form" }), form.isSubmitting && (_jsx("div", { className: "cls_forgot_password_submitting_indicator text-sm text-slate-600 text-center", children: "Sending reset link..." }))] })] }) }) }));
|
|
43
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { default as LoginLayout } from "./login/index";
|
|
2
|
+
export type { LoginLayoutProps } from "./login/index";
|
|
3
|
+
export { default as RegisterLayout } from "./register/index";
|
|
4
|
+
export type { RegisterLayoutProps } from "./register/index";
|
|
5
|
+
export { default as ForgotPasswordLayout } from "./forgot_password/index";
|
|
6
|
+
export type { ForgotPasswordLayoutProps } from "./forgot_password/index";
|
|
7
|
+
export { default as ResetPasswordLayout } from "./reset_password/index";
|
|
8
|
+
export type { ResetPasswordLayoutProps } from "./reset_password/index";
|
|
9
|
+
export { default as EmailVerificationLayout } from "./email_verification/index";
|
|
10
|
+
export type { EmailVerificationLayoutProps } from "./email_verification/index";
|
|
11
|
+
export { default as MySettingsLayout } from "./my_settings/index";
|
|
12
|
+
export type { MySettingsLayoutProps } from "./my_settings/index";
|
|
13
|
+
export { UserManagementLayout } from "./user_management/index";
|
|
14
|
+
export type { UserManagementLayoutProps } from "./user_management/index";
|
|
15
|
+
export * from "./shared/index";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/layouts/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC1E,YAAY,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEzE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACxE,YAAY,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAChF,YAAY,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAClE,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,YAAY,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAGzE,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// file_description: barrel export for all layout components
|
|
2
|
+
// section: layout_exports
|
|
3
|
+
export { default as LoginLayout } from "./login/index";
|
|
4
|
+
export { default as RegisterLayout } from "./register/index";
|
|
5
|
+
export { default as ForgotPasswordLayout } from "./forgot_password/index";
|
|
6
|
+
export { default as ResetPasswordLayout } from "./reset_password/index";
|
|
7
|
+
export { default as EmailVerificationLayout } from "./email_verification/index";
|
|
8
|
+
export { default as MySettingsLayout } from "./my_settings/index";
|
|
9
|
+
export { UserManagementLayout } from "./user_management/index";
|
|
10
|
+
// section: shared_exports
|
|
11
|
+
export * from "./shared/index";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LayoutFieldMap, LayoutFieldMapOverrides } from "hazo_auth/components/layouts/shared/config/layout_customization";
|
|
2
|
+
import { type ButtonPaletteDefaults, type ButtonPaletteOverrides, type LayoutLabelDefaults, type LayoutLabelOverrides } from "hazo_auth/components/layouts/shared/config/layout_customization";
|
|
3
|
+
export declare const LOGIN_FIELD_IDS: {
|
|
4
|
+
readonly EMAIL: "email_address";
|
|
5
|
+
readonly PASSWORD: "password";
|
|
6
|
+
};
|
|
7
|
+
export type LoginFieldId = (typeof LOGIN_FIELD_IDS)[keyof typeof LOGIN_FIELD_IDS];
|
|
8
|
+
export declare const createLoginFieldDefinitions: (overrides?: LayoutFieldMapOverrides) => LayoutFieldMap;
|
|
9
|
+
export declare const resolveLoginLabels: (overrides?: LayoutLabelOverrides) => LayoutLabelDefaults;
|
|
10
|
+
export declare const resolveLoginButtonPalette: (overrides?: ButtonPaletteOverrides) => ButtonPaletteDefaults;
|
|
11
|
+
//# sourceMappingURL=login_field_config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login_field_config.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/login/config/login_field_config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,iEAAiE,CAAC;AAC/H,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAC1B,MAAM,iEAAiE,CAAC;AAGzE,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAsBlF,eAAO,MAAM,2BAA2B,GACtC,YAAY,uBAAuB,mBAC2B,CAAC;AAUjE,eAAO,MAAM,kBAAkB,GAAI,YAAY,oBAAoB,wBACnB,CAAC;AAUjD,eAAO,MAAM,yBAAyB,GAAI,YAAY,sBAAsB,0BACZ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { resolveButtonPalette, resolveFieldDefinitions, resolveLabels, } from "hazo_auth/components/layouts/shared/config/layout_customization";
|
|
2
|
+
// section: field_identifiers
|
|
3
|
+
export const LOGIN_FIELD_IDS = {
|
|
4
|
+
EMAIL: "email_address",
|
|
5
|
+
PASSWORD: "password",
|
|
6
|
+
};
|
|
7
|
+
// section: field_definitions
|
|
8
|
+
const LOGIN_FIELD_DEFINITIONS = {
|
|
9
|
+
[LOGIN_FIELD_IDS.EMAIL]: {
|
|
10
|
+
id: LOGIN_FIELD_IDS.EMAIL,
|
|
11
|
+
label: "Email address",
|
|
12
|
+
type: "email",
|
|
13
|
+
autoComplete: "email",
|
|
14
|
+
placeholder: "Enter your email address",
|
|
15
|
+
ariaLabel: "Email address input field",
|
|
16
|
+
},
|
|
17
|
+
[LOGIN_FIELD_IDS.PASSWORD]: {
|
|
18
|
+
id: LOGIN_FIELD_IDS.PASSWORD,
|
|
19
|
+
label: "Password",
|
|
20
|
+
type: "password",
|
|
21
|
+
autoComplete: "current-password",
|
|
22
|
+
placeholder: "Enter your password",
|
|
23
|
+
ariaLabel: "Password input field",
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
export const createLoginFieldDefinitions = (overrides) => resolveFieldDefinitions(LOGIN_FIELD_DEFINITIONS, overrides);
|
|
27
|
+
// section: label_defaults
|
|
28
|
+
const LOGIN_LABEL_DEFAULTS = {
|
|
29
|
+
heading: "Sign in to your account",
|
|
30
|
+
subHeading: "Enter your credentials to access your secure workspace.",
|
|
31
|
+
submitButton: "Login",
|
|
32
|
+
cancelButton: "Cancel",
|
|
33
|
+
};
|
|
34
|
+
export const resolveLoginLabels = (overrides) => resolveLabels(LOGIN_LABEL_DEFAULTS, overrides);
|
|
35
|
+
// section: button_palette_defaults
|
|
36
|
+
const LOGIN_BUTTON_PALETTE_DEFAULTS = {
|
|
37
|
+
submitBackground: "#0f172a",
|
|
38
|
+
submitText: "#ffffff",
|
|
39
|
+
cancelBorder: "#cbd5f5",
|
|
40
|
+
cancelText: "#0f172a",
|
|
41
|
+
};
|
|
42
|
+
export const resolveLoginButtonPalette = (overrides) => resolveButtonPalette(LOGIN_BUTTON_PALETTE_DEFAULTS, overrides);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { LayoutDataClient } from "hazo_auth/components/layouts/shared/data/layout_data_client";
|
|
2
|
+
import { type LoginFieldId } from "hazo_auth/components/layouts/login/config/login_field_config";
|
|
3
|
+
export type LoginFormValues = Record<LoginFieldId, string>;
|
|
4
|
+
export type LoginFormErrors = Partial<Record<LoginFieldId, string>>;
|
|
5
|
+
export type PasswordVisibilityState = {
|
|
6
|
+
password: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type UseLoginFormParams<TClient = unknown> = {
|
|
9
|
+
dataClient: LayoutDataClient<TClient>;
|
|
10
|
+
logger?: {
|
|
11
|
+
info: (message: string, data?: Record<string, unknown>) => void;
|
|
12
|
+
error: (message: string, data?: Record<string, unknown>) => void;
|
|
13
|
+
warn: (message: string, data?: Record<string, unknown>) => void;
|
|
14
|
+
debug: (message: string, data?: Record<string, unknown>) => void;
|
|
15
|
+
};
|
|
16
|
+
redirectRoute?: string;
|
|
17
|
+
successMessage?: string;
|
|
18
|
+
urlOnLogon?: string;
|
|
19
|
+
};
|
|
20
|
+
export type UseLoginFormResult = {
|
|
21
|
+
values: LoginFormValues;
|
|
22
|
+
errors: LoginFormErrors;
|
|
23
|
+
passwordVisibility: PasswordVisibilityState;
|
|
24
|
+
isSubmitDisabled: boolean;
|
|
25
|
+
emailTouched: boolean;
|
|
26
|
+
isSuccess: boolean;
|
|
27
|
+
handleFieldChange: (fieldId: LoginFieldId, value: string) => void;
|
|
28
|
+
handleEmailBlur: () => void;
|
|
29
|
+
togglePasswordVisibility: () => void;
|
|
30
|
+
handleSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
|
|
31
|
+
handleCancel: () => void;
|
|
32
|
+
};
|
|
33
|
+
export declare const use_login_form: <TClient>({ dataClient, logger, redirectRoute, successMessage, urlOnLogon, }: UseLoginFormParams<TClient>) => UseLoginFormResult;
|
|
34
|
+
//# sourceMappingURL=use_login_form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_login_form.d.ts","sourceRoot":"","sources":["../../../../../src/components/layouts/login/hooks/use_login_form.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6DAA6D,CAAC;AACpG,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,8DAA8D,CAAC;AAMlH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAC3D,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;AACpE,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,OAAO,GAAG,OAAO,IAAI;IAClD,UAAU,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QACjE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,kBAAkB,EAAE,uBAAuB,CAAC;IAC5C,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClE,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,wBAAwB,EAAE,MAAM,IAAI,CAAC;IACrC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IAChE,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAkBF,eAAO,MAAM,cAAc,GAAI,OAAO,EAAG,oEAMtC,kBAAkB,CAAC,OAAO,CAAC,KAAG,kBA0NhC,CAAC"}
|
|
@@ -0,0 +1,196 @@
|
|
|
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 { LOGIN_FIELD_IDS } from "hazo_auth/components/layouts/login/config/login_field_config";
|
|
6
|
+
import { validateEmail } from "hazo_auth/components/layouts/shared/utils/validation";
|
|
7
|
+
import { get_client_ip } from "hazo_auth/components/layouts/shared/utils/ip_address";
|
|
8
|
+
import { trigger_auth_status_refresh } from "hazo_auth/components/layouts/shared/hooks/use_auth_status";
|
|
9
|
+
// section: helpers
|
|
10
|
+
const buildInitialValues = () => ({
|
|
11
|
+
[LOGIN_FIELD_IDS.EMAIL]: "",
|
|
12
|
+
[LOGIN_FIELD_IDS.PASSWORD]: "",
|
|
13
|
+
});
|
|
14
|
+
const get_filename = () => {
|
|
15
|
+
return "use_login_form.ts";
|
|
16
|
+
};
|
|
17
|
+
const get_line_number = () => {
|
|
18
|
+
// This is a placeholder - in a real implementation, you might use Error stack trace
|
|
19
|
+
return 0;
|
|
20
|
+
};
|
|
21
|
+
// section: hook
|
|
22
|
+
export const use_login_form = ({ dataClient, logger, redirectRoute, successMessage = "Successfully logged in", urlOnLogon, }) => {
|
|
23
|
+
const router = useRouter();
|
|
24
|
+
const [values, setValues] = useState(buildInitialValues);
|
|
25
|
+
const [errors, setErrors] = useState({});
|
|
26
|
+
const [passwordVisibility, setPasswordVisibility] = useState({
|
|
27
|
+
password: false,
|
|
28
|
+
});
|
|
29
|
+
const [clientIp, setClientIp] = useState("unknown");
|
|
30
|
+
const [emailTouched, setEmailTouched] = useState(false);
|
|
31
|
+
const [isSuccess, setIsSuccess] = useState(false);
|
|
32
|
+
// section: ip_collection
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
let isMounted = true;
|
|
35
|
+
void get_client_ip().then((ip) => {
|
|
36
|
+
if (isMounted) {
|
|
37
|
+
setClientIp(ip);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return () => {
|
|
41
|
+
isMounted = false;
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
const isSubmitDisabled = useMemo(() => {
|
|
45
|
+
const allFieldsEmpty = Object.values(values).every((fieldValue) => fieldValue.trim() === "");
|
|
46
|
+
return allFieldsEmpty;
|
|
47
|
+
}, [values]);
|
|
48
|
+
const togglePasswordVisibility = useCallback(() => {
|
|
49
|
+
setPasswordVisibility((previous) => ({
|
|
50
|
+
password: !previous.password,
|
|
51
|
+
}));
|
|
52
|
+
}, []);
|
|
53
|
+
const handleFieldChange = useCallback((fieldId, value) => {
|
|
54
|
+
setValues((previousValues) => {
|
|
55
|
+
const nextValues = Object.assign(Object.assign({}, previousValues), { [fieldId]: value });
|
|
56
|
+
setErrors((previousErrors) => {
|
|
57
|
+
const updatedErrors = Object.assign({}, previousErrors);
|
|
58
|
+
// Only validate email on change if it has been touched (blurred)
|
|
59
|
+
if (fieldId === LOGIN_FIELD_IDS.EMAIL && emailTouched) {
|
|
60
|
+
const emailError = validateEmail(value);
|
|
61
|
+
if (emailError) {
|
|
62
|
+
updatedErrors[LOGIN_FIELD_IDS.EMAIL] = emailError;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
delete updatedErrors[LOGIN_FIELD_IDS.EMAIL];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return updatedErrors;
|
|
69
|
+
});
|
|
70
|
+
return nextValues;
|
|
71
|
+
});
|
|
72
|
+
}, [emailTouched]);
|
|
73
|
+
const handleEmailBlur = useCallback(() => {
|
|
74
|
+
setEmailTouched(true);
|
|
75
|
+
// Validate email on blur
|
|
76
|
+
setErrors((previousErrors) => {
|
|
77
|
+
const updatedErrors = Object.assign({}, previousErrors);
|
|
78
|
+
const emailValue = values[LOGIN_FIELD_IDS.EMAIL];
|
|
79
|
+
const emailError = validateEmail(emailValue);
|
|
80
|
+
if (emailError) {
|
|
81
|
+
updatedErrors[LOGIN_FIELD_IDS.EMAIL] = emailError;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
delete updatedErrors[LOGIN_FIELD_IDS.EMAIL];
|
|
85
|
+
}
|
|
86
|
+
return updatedErrors;
|
|
87
|
+
});
|
|
88
|
+
}, [values]);
|
|
89
|
+
// section: login_attempt_logging
|
|
90
|
+
const log_login_attempt = useCallback((success, errorMessage) => {
|
|
91
|
+
if (!logger) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const timestamp = new Date().toISOString();
|
|
95
|
+
const logData = Object.assign({ filename: get_filename(), line_number: get_line_number(), email: values[LOGIN_FIELD_IDS.EMAIL], ip_address: clientIp, timestamp,
|
|
96
|
+
success }, (errorMessage ? { error_message: errorMessage } : {}));
|
|
97
|
+
if (success) {
|
|
98
|
+
logger.info("login_attempt_successful", logData);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
logger.error("login_attempt_failed", logData);
|
|
102
|
+
}
|
|
103
|
+
}, [logger, values, clientIp]);
|
|
104
|
+
const handleSubmit = useCallback(async (event) => {
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
const email = values[LOGIN_FIELD_IDS.EMAIL];
|
|
107
|
+
const password = values[LOGIN_FIELD_IDS.PASSWORD];
|
|
108
|
+
try {
|
|
109
|
+
// Update IP address if still unknown
|
|
110
|
+
const currentIp = clientIp === "unknown" ? await get_client_ip() : clientIp;
|
|
111
|
+
setClientIp(currentIp);
|
|
112
|
+
// Attempt login via API route
|
|
113
|
+
const response = await fetch("/api/hazo_auth/login", {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: {
|
|
116
|
+
"Content-Type": "application/json",
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify({
|
|
119
|
+
email,
|
|
120
|
+
password,
|
|
121
|
+
url_on_logon: urlOnLogon,
|
|
122
|
+
}),
|
|
123
|
+
});
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
if (!response.ok || !data.success) {
|
|
126
|
+
// Check if email is not verified
|
|
127
|
+
if (data.email_not_verified) {
|
|
128
|
+
// Redirect to verify_email page with email and message
|
|
129
|
+
const emailParam = encodeURIComponent(email);
|
|
130
|
+
const messageParam = encodeURIComponent("Your email address has not been verified. Please verify your email to continue.");
|
|
131
|
+
router.push(`/hazo_auth/verify_email?email=${emailParam}&message=${messageParam}`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Login failed for other reasons
|
|
135
|
+
const errorMessage = data.error || "Login failed. Please try again.";
|
|
136
|
+
// Log failed login attempt
|
|
137
|
+
log_login_attempt(false, errorMessage);
|
|
138
|
+
// Set error state (remain on same page)
|
|
139
|
+
setErrors({
|
|
140
|
+
[LOGIN_FIELD_IDS.EMAIL]: errorMessage,
|
|
141
|
+
});
|
|
142
|
+
setIsSuccess(false);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
// Login successful
|
|
146
|
+
// Log successful login attempt
|
|
147
|
+
log_login_attempt(true);
|
|
148
|
+
// Trigger auth status refresh in all components (navbar, sidebar, etc.)
|
|
149
|
+
trigger_auth_status_refresh();
|
|
150
|
+
// Refresh the page to update authentication state (cookies are set server-side)
|
|
151
|
+
router.refresh();
|
|
152
|
+
// Use redirectUrl from server response if available, otherwise fall back to redirectRoute prop
|
|
153
|
+
// The server logic already prioritizes: query param > stored DB value > config > default "/"
|
|
154
|
+
const finalRedirectUrl = data.redirectUrl || redirectRoute;
|
|
155
|
+
if (finalRedirectUrl) {
|
|
156
|
+
router.push(finalRedirectUrl);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// Otherwise, show success message
|
|
160
|
+
setIsSuccess(true);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
165
|
+
// Log failed login attempt
|
|
166
|
+
log_login_attempt(false, errorMessage);
|
|
167
|
+
// Set error state (remain on same page)
|
|
168
|
+
setErrors({
|
|
169
|
+
[LOGIN_FIELD_IDS.EMAIL]: errorMessage,
|
|
170
|
+
});
|
|
171
|
+
setIsSuccess(false);
|
|
172
|
+
}
|
|
173
|
+
}, [values, clientIp, log_login_attempt, redirectRoute, router, urlOnLogon]);
|
|
174
|
+
const handleCancel = useCallback(() => {
|
|
175
|
+
setValues(buildInitialValues());
|
|
176
|
+
setErrors({});
|
|
177
|
+
setPasswordVisibility({
|
|
178
|
+
password: false,
|
|
179
|
+
});
|
|
180
|
+
setEmailTouched(false);
|
|
181
|
+
setIsSuccess(false);
|
|
182
|
+
}, []);
|
|
183
|
+
return {
|
|
184
|
+
values,
|
|
185
|
+
errors,
|
|
186
|
+
passwordVisibility,
|
|
187
|
+
isSubmitDisabled,
|
|
188
|
+
emailTouched,
|
|
189
|
+
isSuccess,
|
|
190
|
+
handleFieldChange,
|
|
191
|
+
handleEmailBlur,
|
|
192
|
+
togglePasswordVisibility,
|
|
193
|
+
handleSubmit,
|
|
194
|
+
handleCancel,
|
|
195
|
+
};
|
|
196
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ButtonPaletteOverrides, type LayoutFieldMapOverrides, type LayoutLabelOverrides } from "hazo_auth/components/layouts/shared/config/layout_customization";
|
|
2
|
+
import { type LayoutDataClient } from "hazo_auth/components/layouts/shared/data/layout_data_client";
|
|
3
|
+
export type LoginLayoutProps<TClient = unknown> = {
|
|
4
|
+
image_src: string;
|
|
5
|
+
image_alt: string;
|
|
6
|
+
image_background_color?: string;
|
|
7
|
+
field_overrides?: LayoutFieldMapOverrides;
|
|
8
|
+
labels?: LayoutLabelOverrides;
|
|
9
|
+
button_colors?: ButtonPaletteOverrides;
|
|
10
|
+
data_client: LayoutDataClient<TClient>;
|
|
11
|
+
logger?: {
|
|
12
|
+
info: (message: string, data?: Record<string, unknown>) => void;
|
|
13
|
+
error: (message: string, data?: Record<string, unknown>) => void;
|
|
14
|
+
warn: (message: string, data?: Record<string, unknown>) => void;
|
|
15
|
+
debug: (message: string, data?: Record<string, unknown>) => void;
|
|
16
|
+
};
|
|
17
|
+
redirectRoute?: string;
|
|
18
|
+
successMessage?: string;
|
|
19
|
+
alreadyLoggedInMessage?: string;
|
|
20
|
+
showLogoutButton?: boolean;
|
|
21
|
+
showReturnHomeButton?: boolean;
|
|
22
|
+
returnHomeButtonLabel?: string;
|
|
23
|
+
returnHomePath?: string;
|
|
24
|
+
forgot_password_path?: string;
|
|
25
|
+
forgot_password_label?: string;
|
|
26
|
+
create_account_path?: string;
|
|
27
|
+
create_account_label?: string;
|
|
28
|
+
urlOnLogon?: string;
|
|
29
|
+
};
|
|
30
|
+
export default function login_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, data_client, logger, redirectRoute, successMessage, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, forgot_password_path, forgot_password_label, create_account_path, create_account_label, urlOnLogon, }: LoginLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/login/index.tsx"],"names":[],"mappings":"AAcA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,iEAAiE,CAAC;AAWzE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,6DAA6D,CAAC;AAGpG,MAAM,MAAM,gBAAgB,CAAC,OAAO,GAAG,OAAO,IAAI;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QACjE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAUF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,OAAO,EAAE,EAC5C,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,WAAW,EACX,MAAM,EACN,aAAa,EACb,cAAyC,EACzC,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,oBAAmD,EACnD,qBAA0C,EAC1C,mBAA2C,EAC3C,oBAAuC,EACvC,UAAU,GACX,EAAE,gBAAgB,CAAC,OAAO,CAAC,2CAiK3B"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// file_description: login layout component built atop shared layout utilities
|
|
2
|
+
// section: client_directive
|
|
3
|
+
"use client";
|
|
4
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
5
|
+
// section: imports
|
|
6
|
+
import Link from "next/link";
|
|
7
|
+
import { Input } from "hazo_auth/components/ui/input";
|
|
8
|
+
import { PasswordField } from "hazo_auth/components/layouts/shared/components/password_field";
|
|
9
|
+
import { FormFieldWrapper } from "hazo_auth/components/layouts/shared/components/form_field_wrapper";
|
|
10
|
+
import { FormHeader } from "hazo_auth/components/layouts/shared/components/form_header";
|
|
11
|
+
import { FormActionButtons } from "hazo_auth/components/layouts/shared/components/form_action_buttons";
|
|
12
|
+
import { TwoColumnAuthLayout } from "hazo_auth/components/layouts/shared/components/two_column_auth_layout";
|
|
13
|
+
import { CheckCircle } from "lucide-react";
|
|
14
|
+
import { AlreadyLoggedInGuard } from "hazo_auth/components/layouts/shared/components/already_logged_in_guard";
|
|
15
|
+
import { LOGIN_FIELD_IDS, createLoginFieldDefinitions, resolveLoginButtonPalette, resolveLoginLabels, } from "hazo_auth/components/layouts/login/config/login_field_config";
|
|
16
|
+
import { use_login_form, } from "hazo_auth/components/layouts/login/hooks/use_login_form";
|
|
17
|
+
const ORDERED_FIELDS = [
|
|
18
|
+
LOGIN_FIELD_IDS.EMAIL,
|
|
19
|
+
LOGIN_FIELD_IDS.PASSWORD,
|
|
20
|
+
];
|
|
21
|
+
// section: component
|
|
22
|
+
export default function login_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, data_client, logger, redirectRoute, successMessage = "Successfully logged in", alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", forgot_password_path = "/hazo_auth/forgot_password", forgot_password_label = "Forgot password?", create_account_path = "/hazo_auth/register", create_account_label = "Create account", urlOnLogon, }) {
|
|
23
|
+
const fieldDefinitions = createLoginFieldDefinitions(field_overrides);
|
|
24
|
+
const resolvedLabels = resolveLoginLabels(labels);
|
|
25
|
+
const resolvedButtonPalette = resolveLoginButtonPalette(button_colors);
|
|
26
|
+
const form = use_login_form({
|
|
27
|
+
dataClient: data_client,
|
|
28
|
+
logger,
|
|
29
|
+
redirectRoute,
|
|
30
|
+
successMessage,
|
|
31
|
+
urlOnLogon: urlOnLogon,
|
|
32
|
+
});
|
|
33
|
+
const renderFields = (formState) => {
|
|
34
|
+
return ORDERED_FIELDS.map((fieldId) => {
|
|
35
|
+
const fieldDefinition = fieldDefinitions[fieldId];
|
|
36
|
+
const fieldValue = formState.values[fieldId];
|
|
37
|
+
const fieldError = formState.errors[fieldId];
|
|
38
|
+
const isPasswordField = fieldDefinition.type === "password";
|
|
39
|
+
const inputElement = isPasswordField ? (_jsx(PasswordField, { inputId: fieldDefinition.id, ariaLabel: fieldDefinition.ariaLabel, value: fieldValue, placeholder: fieldDefinition.placeholder, autoComplete: fieldDefinition.autoComplete, isVisible: formState.passwordVisibility.password, onChange: (nextValue) => formState.handleFieldChange(fieldId, nextValue), onToggleVisibility: formState.togglePasswordVisibility, errorMessage: fieldError })) : (_jsx(Input, { id: fieldDefinition.id, type: fieldDefinition.type, value: fieldValue, onChange: (event) => formState.handleFieldChange(fieldId, event.target.value), onBlur: fieldId === LOGIN_FIELD_IDS.EMAIL
|
|
40
|
+
? formState.handleEmailBlur
|
|
41
|
+
: undefined, autoComplete: fieldDefinition.autoComplete, placeholder: fieldDefinition.placeholder, "aria-label": fieldDefinition.ariaLabel, className: "cls_login_layout_field_input" }));
|
|
42
|
+
// Only show email error if field has been touched (blurred)
|
|
43
|
+
const shouldShowError = isPasswordField
|
|
44
|
+
? undefined
|
|
45
|
+
: fieldId === LOGIN_FIELD_IDS.EMAIL
|
|
46
|
+
? formState.emailTouched && fieldError
|
|
47
|
+
? fieldError
|
|
48
|
+
: undefined
|
|
49
|
+
: fieldError;
|
|
50
|
+
return (_jsx(FormFieldWrapper, { fieldId: fieldDefinition.id, label: fieldDefinition.label, input: inputElement, errorMessage: shouldShowError }, fieldId));
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
// Show success message if login was successful and no redirect route is provided
|
|
54
|
+
if (form.isSuccess) {
|
|
55
|
+
return (_jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsx(FormHeader, { heading: resolvedLabels.heading, subHeading: resolvedLabels.subHeading }), _jsxs("div", { className: "cls_login_layout_success flex flex-col items-center justify-center gap-4 p-8 text-center", children: [_jsx(CheckCircle, { className: "cls_login_layout_success_icon h-16 w-16 text-green-600", "aria-hidden": "true" }), _jsx("p", { className: "cls_login_layout_success_message text-lg font-medium text-slate-900", children: successMessage })] })] }) }));
|
|
56
|
+
}
|
|
57
|
+
return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsx(FormHeader, { heading: resolvedLabels.heading, subHeading: resolvedLabels.subHeading }), _jsxs("form", { className: "cls_login_layout_form_fields flex flex-col gap-5", onSubmit: form.handleSubmit, "aria-label": "Login form", children: [renderFields(form), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: form.isSubmitDisabled, onCancel: form.handleCancel, submitAriaLabel: "Submit login form", cancelAriaLabel: "Cancel login form" }), _jsxs("div", { className: "cls_login_layout_support_links flex flex-col gap-1 text-sm text-muted-foreground", children: [_jsx(Link, { href: forgot_password_path, className: "cls_login_layout_forgot_password_link text-primary underline-offset-4 hover:underline", "aria-label": "Go to forgot password page", children: forgot_password_label }), _jsx(Link, { href: create_account_path, className: "cls_login_layout_create_account_link text-primary underline-offset-4 hover:underline", "aria-label": "Go to create account page", children: create_account_label })] })] })] }) }) }));
|
|
58
|
+
}
|