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.
- package/SETUP_CHECKLIST.md +708 -0
- package/dist/app/api/hazo_auth/change_password/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/change_password/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/change_password/route.js +98 -0
- package/dist/app/api/hazo_auth/forgot_password/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/forgot_password/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/forgot_password/route.js +78 -0
- package/dist/app/api/hazo_auth/get_auth/route.d.ts +10 -0
- package/dist/app/api/hazo_auth/get_auth/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/get_auth/route.js +63 -0
- package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts +14 -0
- package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/invalidate_cache/route.js +96 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts +13 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/library_photos/route.js +55 -0
- package/dist/app/api/hazo_auth/login/route.d.ts +12 -0
- package/dist/app/api/hazo_auth/login/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/login/route.js +140 -0
- package/dist/app/api/hazo_auth/logout/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/logout/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/logout/route.js +71 -0
- package/dist/app/api/hazo_auth/me/route.d.ts +3 -0
- package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/me/route.js +34 -0
- package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts +7 -0
- package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/profile_picture/[filename]/route.js +43 -0
- package/dist/app/api/hazo_auth/register/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/register/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/register/route.js +80 -0
- package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/remove_profile_picture/route.js +64 -0
- package/dist/app/api/hazo_auth/resend_verification/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/resend_verification/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/resend_verification/route.js +79 -0
- package/dist/app/api/hazo_auth/reset_password/route.d.ts +8 -0
- package/dist/app/api/hazo_auth/reset_password/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/reset_password/route.js +76 -0
- package/dist/app/api/hazo_auth/update_user/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/update_user/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/update_user/route.js +95 -0
- package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/upload_profile_picture/route.js +204 -0
- package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts +6 -0
- package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/validate_reset_token/route.js +58 -0
- package/dist/app/api/hazo_auth/verify_email/route.d.ts +11 -0
- package/dist/app/api/hazo_auth/verify_email/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/verify_email/route.js +63 -0
- package/dist/cli/generate.d.ts +2 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +117 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +120 -0
- package/dist/cli/validate.d.ts +15 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +509 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/card.js +45 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -1
- package/dist/hooks/use-mobile.js +17 -3
- package/dist/server/routes/change_password.d.ts +2 -0
- package/dist/server/routes/change_password.d.ts.map +1 -0
- package/dist/server/routes/change_password.js +2 -0
- package/dist/server/routes/forgot_password.d.ts +2 -0
- package/dist/server/routes/forgot_password.d.ts.map +1 -0
- package/dist/server/routes/forgot_password.js +2 -0
- package/dist/server/routes/get_auth.d.ts +2 -0
- package/dist/server/routes/get_auth.d.ts.map +1 -0
- package/dist/server/routes/get_auth.js +2 -0
- package/dist/server/routes/index.d.ts +18 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +24 -0
- package/dist/server/routes/invalidate_cache.d.ts +2 -0
- package/dist/server/routes/invalidate_cache.d.ts.map +1 -0
- package/dist/server/routes/invalidate_cache.js +2 -0
- package/dist/server/routes/library_photos.d.ts +2 -0
- package/dist/server/routes/library_photos.d.ts.map +1 -0
- package/dist/server/routes/library_photos.js +2 -0
- package/dist/server/routes/login.d.ts +2 -0
- package/dist/server/routes/login.d.ts.map +1 -0
- package/dist/server/routes/login.js +2 -0
- package/dist/server/routes/logout.d.ts +2 -0
- package/dist/server/routes/logout.d.ts.map +1 -0
- package/dist/server/routes/logout.js +2 -0
- package/dist/server/routes/me.d.ts +2 -0
- package/dist/server/routes/me.d.ts.map +1 -0
- package/dist/server/routes/me.js +2 -0
- package/dist/server/routes/profile_picture_filename.d.ts +2 -0
- package/dist/server/routes/profile_picture_filename.d.ts.map +1 -0
- package/dist/server/routes/profile_picture_filename.js +3 -0
- package/dist/server/routes/register.d.ts +2 -0
- package/dist/server/routes/register.d.ts.map +1 -0
- package/dist/server/routes/register.js +2 -0
- package/dist/server/routes/remove_profile_picture.d.ts +2 -0
- package/dist/server/routes/remove_profile_picture.d.ts.map +1 -0
- package/dist/server/routes/remove_profile_picture.js +2 -0
- package/dist/server/routes/resend_verification.d.ts +2 -0
- package/dist/server/routes/resend_verification.d.ts.map +1 -0
- package/dist/server/routes/resend_verification.js +2 -0
- package/dist/server/routes/reset_password.d.ts +2 -0
- package/dist/server/routes/reset_password.d.ts.map +1 -0
- package/dist/server/routes/reset_password.js +2 -0
- package/dist/server/routes/update_user.d.ts +2 -0
- package/dist/server/routes/update_user.d.ts.map +1 -0
- package/dist/server/routes/update_user.js +2 -0
- package/dist/server/routes/upload_profile_picture.d.ts +2 -0
- package/dist/server/routes/upload_profile_picture.d.ts.map +1 -0
- package/dist/server/routes/upload_profile_picture.js +2 -0
- package/dist/server/routes/validate_reset_token.d.ts +2 -0
- package/dist/server/routes/validate_reset_token.d.ts.map +1 -0
- package/dist/server/routes/validate_reset_token.js +2 -0
- package/dist/server/routes/verify_email.d.ts +2 -0
- package/dist/server/routes/verify_email.d.ts.map +1 -0
- package/dist/server/routes/verify_email.js +2 -0
- package/package.json +12 -17
- package/components.json +0 -22
- package/instrumentation.ts +0 -32
- package/migrations/001_add_token_type_to_refresh_tokens.sql +0 -14
- package/migrations/002_add_name_to_hazo_users.sql +0 -7
- package/migrations/003_add_url_on_logon_to_hazo_users.sql +0 -8
- package/next.config.mjs +0 -67
- package/postcss.config.mjs +0 -8
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/next.svg +0 -1
- package/public/vercel.svg +0 -1
- package/public/window.svg +0 -1
- package/scripts/apply_migration.ts +0 -118
- package/scripts/init_users.ts +0 -378
- package/src/app/api/hazo_auth/auth/upload_profile_picture/route.ts +0 -268
- package/src/app/api/hazo_auth/change_password/route.ts +0 -132
- package/src/app/api/hazo_auth/forgot_password/route.ts +0 -107
- package/src/app/api/hazo_auth/get_auth/route.ts +0 -89
- package/src/app/api/hazo_auth/invalidate_cache/route.ts +0 -139
- package/src/app/api/hazo_auth/library_photos/route.ts +0 -73
- package/src/app/api/hazo_auth/login/route.ts +0 -181
- package/src/app/api/hazo_auth/logout/route.ts +0 -89
- package/src/app/api/hazo_auth/me/route.ts +0 -47
- package/src/app/api/hazo_auth/profile_picture/[filename]/route.ts +0 -67
- package/src/app/api/hazo_auth/register/route.ts +0 -109
- package/src/app/api/hazo_auth/remove_profile_picture/route.ts +0 -86
- package/src/app/api/hazo_auth/resend_verification/route.ts +0 -108
- package/src/app/api/hazo_auth/reset_password/route.ts +0 -107
- package/src/app/api/hazo_auth/update_user/route.ts +0 -126
- package/src/app/api/hazo_auth/upload_profile_picture/route.ts +0 -268
- package/src/app/api/hazo_auth/user_management/permissions/route.ts +0 -367
- package/src/app/api/hazo_auth/user_management/roles/route.ts +0 -442
- package/src/app/api/hazo_auth/user_management/users/roles/route.ts +0 -367
- package/src/app/api/hazo_auth/user_management/users/route.ts +0 -239
- package/src/app/api/hazo_auth/validate_reset_token/route.ts +0 -83
- package/src/app/api/hazo_auth/verify_email/route.ts +0 -88
- package/src/app/api/migrations/apply/route.ts +0 -91
- package/src/app/favicon.ico +0 -0
- package/src/app/fonts/GeistMonoVF.woff +0 -0
- package/src/app/fonts/GeistVF.woff +0 -0
- package/src/app/globals.css +0 -89
- package/src/app/hazo_auth/forgot_password/forgot_password_page_client.tsx +0 -60
- package/src/app/hazo_auth/forgot_password/page.tsx +0 -24
- package/src/app/hazo_auth/login/login_page_client.tsx +0 -86
- package/src/app/hazo_auth/login/page.tsx +0 -38
- package/src/app/hazo_auth/my_settings/my_settings_page_client.tsx +0 -120
- package/src/app/hazo_auth/my_settings/page.tsx +0 -40
- package/src/app/hazo_auth/register/page.tsx +0 -36
- package/src/app/hazo_auth/register/register_page_client.tsx +0 -81
- package/src/app/hazo_auth/reset_password/page.tsx +0 -29
- package/src/app/hazo_auth/reset_password/reset_password_page_client.tsx +0 -81
- package/src/app/hazo_auth/user_management/page.tsx +0 -14
- package/src/app/hazo_auth/user_management/user_management_page_client.tsx +0 -16
- package/src/app/hazo_auth/verify_email/page.tsx +0 -24
- package/src/app/hazo_auth/verify_email/verify_email_page_client.tsx +0 -60
- package/src/app/hazo_connect/api/sqlite/data/route.ts +0 -203
- package/src/app/hazo_connect/api/sqlite/schema/route.ts +0 -45
- package/src/app/hazo_connect/api/sqlite/tables/route.ts +0 -36
- package/src/app/hazo_connect/sqlite_admin/page.tsx +0 -51
- package/src/app/hazo_connect/sqlite_admin/sqlite-admin-client.tsx +0 -984
- package/src/app/layout.tsx +0 -43
- package/src/app/page.tsx +0 -170
- package/src/components/index.ts +0 -7
- package/src/components/layouts/email_verification/config/email_verification_field_config.ts +0 -86
- package/src/components/layouts/email_verification/hooks/use_email_verification.ts +0 -297
- package/src/components/layouts/email_verification/index.tsx +0 -297
- package/src/components/layouts/forgot_password/config/forgot_password_field_config.ts +0 -58
- package/src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts +0 -179
- package/src/components/layouts/forgot_password/index.tsx +0 -168
- package/src/components/layouts/index.ts +0 -26
- package/src/components/layouts/login/config/login_field_config.ts +0 -67
- package/src/components/layouts/login/hooks/use_login_form.ts +0 -286
- package/src/components/layouts/login/index.tsx +0 -252
- package/src/components/layouts/my_settings/components/editable_field.tsx +0 -177
- package/src/components/layouts/my_settings/components/password_change_dialog.tsx +0 -301
- package/src/components/layouts/my_settings/components/profile_picture_dialog.tsx +0 -385
- package/src/components/layouts/my_settings/components/profile_picture_display.tsx +0 -66
- package/src/components/layouts/my_settings/components/profile_picture_gravatar_tab.tsx +0 -143
- package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +0 -311
- package/src/components/layouts/my_settings/components/profile_picture_upload_tab.tsx +0 -341
- package/src/components/layouts/my_settings/config/my_settings_field_config.ts +0 -61
- package/src/components/layouts/my_settings/hooks/use_my_settings.ts +0 -458
- package/src/components/layouts/my_settings/index.tsx +0 -351
- package/src/components/layouts/register/config/register_field_config.ts +0 -101
- package/src/components/layouts/register/hooks/use_register_form.ts +0 -275
- package/src/components/layouts/register/index.tsx +0 -226
- package/src/components/layouts/reset_password/config/reset_password_field_config.ts +0 -86
- package/src/components/layouts/reset_password/hooks/use_reset_password_form.ts +0 -276
- package/src/components/layouts/reset_password/index.tsx +0 -294
- package/src/components/layouts/shared/components/already_logged_in_guard.tsx +0 -95
- package/src/components/layouts/shared/components/auth_page_shell.tsx +0 -36
- package/src/components/layouts/shared/components/field_error_message.tsx +0 -29
- package/src/components/layouts/shared/components/form_action_buttons.tsx +0 -64
- package/src/components/layouts/shared/components/form_field_wrapper.tsx +0 -44
- package/src/components/layouts/shared/components/form_header.tsx +0 -36
- package/src/components/layouts/shared/components/logout_button.tsx +0 -76
- package/src/components/layouts/shared/components/password_field.tsx +0 -72
- package/src/components/layouts/shared/components/profile_pic_menu.tsx +0 -321
- package/src/components/layouts/shared/components/profile_pic_menu_wrapper.tsx +0 -40
- package/src/components/layouts/shared/components/sidebar_layout_wrapper.tsx +0 -214
- package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +0 -53
- package/src/components/layouts/shared/components/two_column_auth_layout.tsx +0 -44
- package/src/components/layouts/shared/components/unauthorized_guard.tsx +0 -78
- package/src/components/layouts/shared/components/visual_panel.tsx +0 -41
- package/src/components/layouts/shared/config/layout_customization.ts +0 -95
- package/src/components/layouts/shared/data/layout_data_client.ts +0 -19
- package/src/components/layouts/shared/hooks/use_auth_status.ts +0 -103
- package/src/components/layouts/shared/hooks/use_hazo_auth.ts +0 -158
- package/src/components/layouts/shared/index.ts +0 -34
- package/src/components/layouts/shared/utils/ip_address.ts +0 -37
- package/src/components/layouts/shared/utils/validation.ts +0 -66
- package/src/components/layouts/user_management/components/roles_matrix.tsx +0 -607
- package/src/components/layouts/user_management/index.tsx +0 -1295
- package/src/components/ui/alert-dialog.tsx +0 -141
- package/src/components/ui/avatar.tsx +0 -50
- package/src/components/ui/button.tsx +0 -57
- package/src/components/ui/checkbox.tsx +0 -30
- package/src/components/ui/dialog.tsx +0 -122
- package/src/components/ui/dropdown-menu.tsx +0 -201
- package/src/components/ui/hazo_ui_tooltip.tsx +0 -67
- package/src/components/ui/index.ts +0 -22
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/label.tsx +0 -26
- package/src/components/ui/separator.tsx +0 -31
- package/src/components/ui/sheet.tsx +0 -139
- package/src/components/ui/sidebar.tsx +0 -773
- package/src/components/ui/skeleton.tsx +0 -15
- package/src/components/ui/sonner.tsx +0 -31
- package/src/components/ui/switch.tsx +0 -29
- package/src/components/ui/table.tsx +0 -120
- package/src/components/ui/tabs.tsx +0 -55
- package/src/components/ui/tooltip.tsx +0 -32
- package/src/components/ui/vertical-tabs.tsx +0 -59
- package/src/hooks/use-mobile.tsx +0 -19
- package/src/index.ts +0 -7
- package/src/lib/already_logged_in_config.server.ts +0 -46
- package/src/lib/app_logger.ts +0 -24
- package/src/lib/auth/auth_cache.ts +0 -220
- package/src/lib/auth/auth_rate_limiter.ts +0 -121
- package/src/lib/auth/auth_types.ts +0 -65
- package/src/lib/auth/auth_utils.server.ts +0 -196
- package/src/lib/auth/hazo_get_auth.server.ts +0 -333
- package/src/lib/auth/index.ts +0 -23
- package/src/lib/auth/server_auth.ts +0 -88
- package/src/lib/auth_utility_config.server.ts +0 -136
- package/src/lib/config/config_loader.server.ts +0 -164
- package/src/lib/email_verification_config.server.ts +0 -32
- package/src/lib/file_types_config.server.ts +0 -25
- package/src/lib/forgot_password_config.server.ts +0 -32
- package/src/lib/hazo_connect_instance.server.ts +0 -101
- package/src/lib/hazo_connect_setup.server.ts +0 -194
- package/src/lib/hazo_connect_setup.ts +0 -54
- package/src/lib/index.ts +0 -44
- package/src/lib/login_config.server.ts +0 -71
- package/src/lib/messages_config.server.ts +0 -45
- package/src/lib/migrations/apply_migration.ts +0 -105
- package/src/lib/my_settings_config.server.ts +0 -135
- package/src/lib/password_requirements_config.server.ts +0 -39
- package/src/lib/profile_pic_menu_config.server.ts +0 -138
- package/src/lib/profile_picture_config.server.ts +0 -56
- package/src/lib/register_config.server.ts +0 -73
- package/src/lib/reset_password_config.server.ts +0 -75
- package/src/lib/services/email_service.ts +0 -581
- package/src/lib/services/email_verification_service.ts +0 -270
- package/src/lib/services/index.ts +0 -15
- package/src/lib/services/login_service.ts +0 -134
- package/src/lib/services/password_change_service.ts +0 -154
- package/src/lib/services/password_reset_service.ts +0 -405
- package/src/lib/services/profile_picture_remove_service.ts +0 -120
- package/src/lib/services/profile_picture_service.ts +0 -215
- package/src/lib/services/profile_picture_source_mapper.ts +0 -62
- package/src/lib/services/registration_service.ts +0 -184
- package/src/lib/services/token_service.ts +0 -240
- package/src/lib/services/user_profiles_service.ts +0 -143
- package/src/lib/services/user_update_service.ts +0 -141
- package/src/lib/ui_shell_config.server.ts +0 -73
- package/src/lib/ui_sizes_config.server.ts +0 -37
- package/src/lib/user_fields_config.server.ts +0 -31
- package/src/lib/user_management_config.server.ts +0 -39
- package/src/lib/utils/api_route_helpers.ts +0 -60
- package/src/lib/utils/error_sanitizer.ts +0 -75
- package/src/lib/utils.ts +0 -11
- package/src/middleware.ts +0 -94
- package/src/routes/index.ts +0 -34
- package/src/server/config/config_loader.ts +0 -496
- package/src/server/index.ts +0 -38
- package/src/server/logging/logger_service.ts +0 -56
- package/src/server/routes/root_router.ts +0 -16
- package/src/server/server.ts +0 -28
- package/src/server/types/app_types.ts +0 -74
- package/src/server/types/express.d.ts +0 -16
- package/src/stories/email_verification_layout.stories.tsx +0 -137
- package/src/stories/forgot_password_layout.stories.tsx +0 -85
- package/src/stories/login_layout.stories.tsx +0 -85
- package/src/stories/project_overview.stories.tsx +0 -33
- package/src/stories/register_layout.stories.tsx +0 -107
- package/tailwind.config.ts +0 -77
- package/tsconfig.build.json +0 -36
- package/tsconfig.json +0 -28
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
// file_description: service for password reset operations using hazo_connect
|
|
2
|
-
// section: imports
|
|
3
|
-
import type { HazoConnectAdapter } from "hazo_connect";
|
|
4
|
-
import { createCrudService } from "hazo_connect/server";
|
|
5
|
-
import { create_token } from "./token_service";
|
|
6
|
-
import argon2 from "argon2";
|
|
7
|
-
import { create_app_logger } from "../app_logger";
|
|
8
|
-
import { send_template_email } from "./email_service";
|
|
9
|
-
|
|
10
|
-
// section: types
|
|
11
|
-
export type PasswordResetRequestData = {
|
|
12
|
-
email: string;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type PasswordResetRequestResult = {
|
|
16
|
-
success: boolean;
|
|
17
|
-
error?: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type PasswordResetData = {
|
|
21
|
-
token: string;
|
|
22
|
-
new_password: string;
|
|
23
|
-
minimum_length?: number; // Optional: if not provided, defaults to 8
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type PasswordResetResult = {
|
|
27
|
-
success: boolean;
|
|
28
|
-
user_id?: string;
|
|
29
|
-
email?: string;
|
|
30
|
-
error?: string;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export type PasswordResetTokenValidationData = {
|
|
34
|
-
token: string;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export type PasswordResetTokenValidationResult = {
|
|
38
|
-
success: boolean;
|
|
39
|
-
error?: string;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// section: helpers
|
|
43
|
-
/**
|
|
44
|
-
* Requests a password reset for a user by email
|
|
45
|
-
* Generates a secure token, hashes it, and stores it in hazo_refresh_tokens with token_type = 'password_reset'
|
|
46
|
-
* Invalidates any existing password reset tokens for the user before creating a new one
|
|
47
|
-
* @param adapter - The hazo_connect adapter instance
|
|
48
|
-
* @param data - Password reset request data (email)
|
|
49
|
-
* @returns Password reset request result with success status or error
|
|
50
|
-
*/
|
|
51
|
-
export async function request_password_reset(
|
|
52
|
-
adapter: HazoConnectAdapter,
|
|
53
|
-
data: PasswordResetRequestData,
|
|
54
|
-
): Promise<PasswordResetRequestResult> {
|
|
55
|
-
try {
|
|
56
|
-
const { email } = data;
|
|
57
|
-
|
|
58
|
-
// Create CRUD service for hazo_users table
|
|
59
|
-
const users_service = createCrudService(adapter, "hazo_users");
|
|
60
|
-
|
|
61
|
-
// Find user by email
|
|
62
|
-
const users = await users_service.findBy({
|
|
63
|
-
email_address: email,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// If user not found, return success anyway (to prevent email enumeration)
|
|
67
|
-
if (!Array.isArray(users) || users.length === 0) {
|
|
68
|
-
return {
|
|
69
|
-
success: true,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const user = users[0];
|
|
74
|
-
const user_id = user.id as string;
|
|
75
|
-
|
|
76
|
-
// Create password reset token using shared token service
|
|
77
|
-
const token_result = await create_token({
|
|
78
|
-
adapter,
|
|
79
|
-
user_id,
|
|
80
|
-
token_type: "password_reset",
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
if (!token_result.success) {
|
|
84
|
-
return {
|
|
85
|
-
success: false,
|
|
86
|
-
error: token_result.error || "Failed to create password reset token",
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Send password reset email if token was created successfully
|
|
91
|
-
if (token_result.raw_token) {
|
|
92
|
-
const email_result = await send_template_email("forgot_password", email, {
|
|
93
|
-
token: token_result.raw_token,
|
|
94
|
-
user_email: email,
|
|
95
|
-
user_name: user.name as string | undefined,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
if (!email_result.success) {
|
|
99
|
-
const logger = create_app_logger();
|
|
100
|
-
logger.error("password_reset_service_email_send_failed", {
|
|
101
|
-
filename: "password_reset_service.ts",
|
|
102
|
-
line_number: 0,
|
|
103
|
-
user_id,
|
|
104
|
-
email,
|
|
105
|
-
error: email_result.error,
|
|
106
|
-
note: "Password reset token created but email failed to send",
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
success: true,
|
|
113
|
-
};
|
|
114
|
-
} catch (error) {
|
|
115
|
-
const error_message =
|
|
116
|
-
error instanceof Error ? error.message : "Unknown error";
|
|
117
|
-
|
|
118
|
-
return {
|
|
119
|
-
success: false,
|
|
120
|
-
error: error_message,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Validates a password reset token without resetting the password
|
|
127
|
-
* Verifies the token exists and checks if it has expired
|
|
128
|
-
* @param adapter - The hazo_connect adapter instance
|
|
129
|
-
* @param data - Token validation data (token)
|
|
130
|
-
* @returns Token validation result with success status or error
|
|
131
|
-
*/
|
|
132
|
-
export async function validate_password_reset_token(
|
|
133
|
-
adapter: HazoConnectAdapter,
|
|
134
|
-
data: PasswordResetTokenValidationData,
|
|
135
|
-
): Promise<PasswordResetTokenValidationResult> {
|
|
136
|
-
try {
|
|
137
|
-
const { token } = data;
|
|
138
|
-
|
|
139
|
-
// Create CRUD service for hazo_refresh_tokens table
|
|
140
|
-
const tokens_service = createCrudService(adapter, "hazo_refresh_tokens");
|
|
141
|
-
|
|
142
|
-
// Find all password reset tokens
|
|
143
|
-
// If token_type column doesn't exist, query all tokens and filter manually
|
|
144
|
-
let all_tokens: unknown[] = [];
|
|
145
|
-
try {
|
|
146
|
-
all_tokens = (await tokens_service.findBy({
|
|
147
|
-
token_type: "password_reset",
|
|
148
|
-
})) as unknown[];
|
|
149
|
-
} catch (error) {
|
|
150
|
-
// If token_type column doesn't exist, get all tokens and we'll verify each one
|
|
151
|
-
const logger = create_app_logger();
|
|
152
|
-
const error_message = error instanceof Error ? error.message : "Unknown error";
|
|
153
|
-
logger.warn("password_reset_service_token_type_column_missing", {
|
|
154
|
-
filename: "password_reset_service.ts",
|
|
155
|
-
line_number: 0,
|
|
156
|
-
error: error_message,
|
|
157
|
-
note: "token_type column may not exist, querying all tokens",
|
|
158
|
-
});
|
|
159
|
-
try {
|
|
160
|
-
// Query all tokens (will need to verify each one)
|
|
161
|
-
all_tokens = (await tokens_service.findBy({})) as unknown[];
|
|
162
|
-
} catch (fallbackError) {
|
|
163
|
-
const fallback_error_message = fallbackError instanceof Error ? fallbackError.message : "Unknown error";
|
|
164
|
-
logger.error("password_reset_service_query_tokens_failed", {
|
|
165
|
-
filename: "password_reset_service.ts",
|
|
166
|
-
line_number: 0,
|
|
167
|
-
error: fallback_error_message,
|
|
168
|
-
});
|
|
169
|
-
return {
|
|
170
|
-
success: false,
|
|
171
|
-
error: "Invalid or expired reset token",
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (!Array.isArray(all_tokens) || all_tokens.length === 0) {
|
|
177
|
-
return {
|
|
178
|
-
success: false,
|
|
179
|
-
error: "Invalid or expired reset token",
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Find the matching token by verifying the hash
|
|
184
|
-
let matching_token = null;
|
|
185
|
-
|
|
186
|
-
for (const stored_token of all_tokens) {
|
|
187
|
-
try {
|
|
188
|
-
const token_hash = (stored_token as { token_hash: string }).token_hash;
|
|
189
|
-
const is_valid = await argon2.verify(token_hash, token);
|
|
190
|
-
|
|
191
|
-
if (is_valid) {
|
|
192
|
-
matching_token = stored_token;
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
} catch {
|
|
196
|
-
// Continue to next token if verification fails
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (!matching_token) {
|
|
202
|
-
return {
|
|
203
|
-
success: false,
|
|
204
|
-
error: "Invalid or expired reset token",
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Check if token has expired
|
|
209
|
-
const expires_at = new Date((matching_token as { expires_at: string }).expires_at);
|
|
210
|
-
const now = new Date();
|
|
211
|
-
|
|
212
|
-
if (expires_at < now) {
|
|
213
|
-
return {
|
|
214
|
-
success: false,
|
|
215
|
-
error: "Reset token has expired",
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return {
|
|
220
|
-
success: true,
|
|
221
|
-
};
|
|
222
|
-
} catch (error) {
|
|
223
|
-
const error_message =
|
|
224
|
-
error instanceof Error ? error.message : "Unknown error";
|
|
225
|
-
|
|
226
|
-
return {
|
|
227
|
-
success: false,
|
|
228
|
-
error: error_message,
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Resets a user's password using a password reset token
|
|
235
|
-
* Verifies the token, checks expiration, updates password, and deletes the token
|
|
236
|
-
* @param adapter - The hazo_connect adapter instance
|
|
237
|
-
* @param data - Password reset data (token, new_password)
|
|
238
|
-
* @returns Password reset result with success status, user_id, email, or error
|
|
239
|
-
*/
|
|
240
|
-
export async function reset_password(
|
|
241
|
-
adapter: HazoConnectAdapter,
|
|
242
|
-
data: PasswordResetData,
|
|
243
|
-
): Promise<PasswordResetResult> {
|
|
244
|
-
try {
|
|
245
|
-
const { token, new_password, minimum_length = 8 } = data;
|
|
246
|
-
|
|
247
|
-
// Validate password
|
|
248
|
-
if (!new_password || new_password.length < minimum_length) {
|
|
249
|
-
return {
|
|
250
|
-
success: false,
|
|
251
|
-
error: `Password must be at least ${minimum_length} character${minimum_length === 1 ? "" : "s"} long`,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Create CRUD service for hazo_refresh_tokens table
|
|
256
|
-
const tokens_service = createCrudService(adapter, "hazo_refresh_tokens");
|
|
257
|
-
|
|
258
|
-
// Find all password reset tokens
|
|
259
|
-
// If token_type column doesn't exist, query all tokens and filter manually
|
|
260
|
-
let all_tokens: unknown[] = [];
|
|
261
|
-
try {
|
|
262
|
-
all_tokens = (await tokens_service.findBy({
|
|
263
|
-
token_type: "password_reset",
|
|
264
|
-
})) as unknown[];
|
|
265
|
-
} catch (error) {
|
|
266
|
-
// If token_type column doesn't exist, get all tokens and we'll verify each one
|
|
267
|
-
const logger = create_app_logger();
|
|
268
|
-
const error_message = error instanceof Error ? error.message : "Unknown error";
|
|
269
|
-
logger.warn("password_reset_service_token_type_column_missing", {
|
|
270
|
-
filename: "password_reset_service.ts",
|
|
271
|
-
line_number: 0,
|
|
272
|
-
error: error_message,
|
|
273
|
-
note: "token_type column may not exist, querying all tokens",
|
|
274
|
-
});
|
|
275
|
-
try {
|
|
276
|
-
// Query all tokens (will need to verify each one)
|
|
277
|
-
all_tokens = (await tokens_service.findBy({})) as unknown[];
|
|
278
|
-
} catch (fallbackError) {
|
|
279
|
-
const fallback_error_message = fallbackError instanceof Error ? fallbackError.message : "Unknown error";
|
|
280
|
-
logger.error("password_reset_service_query_tokens_failed", {
|
|
281
|
-
filename: "password_reset_service.ts",
|
|
282
|
-
line_number: 0,
|
|
283
|
-
error: fallback_error_message,
|
|
284
|
-
});
|
|
285
|
-
return {
|
|
286
|
-
success: false,
|
|
287
|
-
error: "Invalid or expired reset token",
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (!Array.isArray(all_tokens) || all_tokens.length === 0) {
|
|
293
|
-
return {
|
|
294
|
-
success: false,
|
|
295
|
-
error: "Invalid or expired reset token",
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Find the matching token by verifying the hash
|
|
300
|
-
let matching_token = null;
|
|
301
|
-
let user_id: string | null = null;
|
|
302
|
-
|
|
303
|
-
for (const stored_token of all_tokens) {
|
|
304
|
-
try {
|
|
305
|
-
const token_hash = (stored_token as { token_hash: string }).token_hash;
|
|
306
|
-
const is_valid = await argon2.verify(token_hash, token);
|
|
307
|
-
|
|
308
|
-
if (is_valid) {
|
|
309
|
-
matching_token = stored_token;
|
|
310
|
-
user_id = (stored_token as { user_id: string }).user_id;
|
|
311
|
-
break;
|
|
312
|
-
}
|
|
313
|
-
} catch {
|
|
314
|
-
// Continue to next token if verification fails
|
|
315
|
-
continue;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (!matching_token || !user_id) {
|
|
320
|
-
return {
|
|
321
|
-
success: false,
|
|
322
|
-
error: "Invalid or expired reset token",
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Check if token has expired
|
|
327
|
-
const expires_at = new Date((matching_token as { expires_at: string }).expires_at);
|
|
328
|
-
const now = new Date();
|
|
329
|
-
|
|
330
|
-
if (expires_at < now) {
|
|
331
|
-
// Delete expired token
|
|
332
|
-
await tokens_service.deleteById((matching_token as { id: unknown }).id);
|
|
333
|
-
|
|
334
|
-
return {
|
|
335
|
-
success: false,
|
|
336
|
-
error: "Reset token has expired",
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Get user email before updating
|
|
341
|
-
const users_service = createCrudService(adapter, "hazo_users");
|
|
342
|
-
const users = await users_service.findBy({
|
|
343
|
-
id: user_id,
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
if (!Array.isArray(users) || users.length === 0) {
|
|
347
|
-
return {
|
|
348
|
-
success: false,
|
|
349
|
-
error: "User not found",
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
const user = users[0];
|
|
354
|
-
const email = user.email_address as string;
|
|
355
|
-
|
|
356
|
-
// Hash the new password
|
|
357
|
-
const password_hash = await argon2.hash(new_password);
|
|
358
|
-
|
|
359
|
-
// Update user's password
|
|
360
|
-
const now_iso = new Date().toISOString();
|
|
361
|
-
await users_service.updateById(
|
|
362
|
-
user_id,
|
|
363
|
-
{
|
|
364
|
-
password_hash: password_hash,
|
|
365
|
-
changed_at: now_iso,
|
|
366
|
-
},
|
|
367
|
-
);
|
|
368
|
-
|
|
369
|
-
// Delete the used token
|
|
370
|
-
await tokens_service.deleteById((matching_token as { id: unknown }).id);
|
|
371
|
-
|
|
372
|
-
// Send password changed notification email
|
|
373
|
-
const email_result = await send_template_email("password_changed", email, {
|
|
374
|
-
user_email: email,
|
|
375
|
-
user_name: user.name as string | undefined,
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
if (!email_result.success) {
|
|
379
|
-
const logger = create_app_logger();
|
|
380
|
-
logger.error("password_reset_service_password_changed_email_failed", {
|
|
381
|
-
filename: "password_reset_service.ts",
|
|
382
|
-
line_number: 0,
|
|
383
|
-
user_id,
|
|
384
|
-
email,
|
|
385
|
-
error: email_result.error,
|
|
386
|
-
note: "Password was reset successfully but notification email failed to send",
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return {
|
|
391
|
-
success: true,
|
|
392
|
-
user_id,
|
|
393
|
-
email,
|
|
394
|
-
};
|
|
395
|
-
} catch (error) {
|
|
396
|
-
const error_message =
|
|
397
|
-
error instanceof Error ? error.message : "Unknown error";
|
|
398
|
-
|
|
399
|
-
return {
|
|
400
|
-
success: false,
|
|
401
|
-
error: error_message,
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
// file_description: service for removing profile pictures (deleting files and clearing database)
|
|
2
|
-
// section: imports
|
|
3
|
-
import type { HazoConnectAdapter } from "hazo_connect";
|
|
4
|
-
import { createCrudService } from "hazo_connect/server";
|
|
5
|
-
import { map_db_source_to_ui } from "./profile_picture_source_mapper";
|
|
6
|
-
import { get_profile_picture_config } from "../profile_picture_config.server";
|
|
7
|
-
import { create_app_logger } from "../app_logger";
|
|
8
|
-
import fs from "fs";
|
|
9
|
-
import path from "path";
|
|
10
|
-
|
|
11
|
-
// section: types
|
|
12
|
-
export type RemoveProfilePictureResult = {
|
|
13
|
-
success: boolean;
|
|
14
|
-
error?: string;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// section: helpers
|
|
18
|
-
/**
|
|
19
|
-
* Removes user profile picture
|
|
20
|
-
* - If source is "upload": deletes the uploaded file and clears profile_picture_url and profile_source
|
|
21
|
-
* - If source is "gravatar" or "library": clears profile_picture_url and profile_source
|
|
22
|
-
* @param adapter - The hazo_connect adapter instance
|
|
23
|
-
* @param user_id - User ID
|
|
24
|
-
* @returns Remove result with success status or error
|
|
25
|
-
*/
|
|
26
|
-
export async function remove_user_profile_picture(
|
|
27
|
-
adapter: HazoConnectAdapter,
|
|
28
|
-
user_id: string,
|
|
29
|
-
): Promise<RemoveProfilePictureResult> {
|
|
30
|
-
try {
|
|
31
|
-
const users_service = createCrudService(adapter, "hazo_users");
|
|
32
|
-
|
|
33
|
-
// Get current user data
|
|
34
|
-
const users = await users_service.findBy({
|
|
35
|
-
id: user_id,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
if (!Array.isArray(users) || users.length === 0) {
|
|
39
|
-
return {
|
|
40
|
-
success: false,
|
|
41
|
-
error: "User not found",
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const current_user = users[0];
|
|
46
|
-
const profile_picture_url = (current_user.profile_picture_url as string) || null;
|
|
47
|
-
const profile_source_db = (current_user.profile_source as string) || null;
|
|
48
|
-
|
|
49
|
-
if (!profile_picture_url || !profile_source_db) {
|
|
50
|
-
// No profile picture to remove
|
|
51
|
-
return {
|
|
52
|
-
success: true,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Map database source to UI source
|
|
57
|
-
const profile_source_ui = map_db_source_to_ui(profile_source_db);
|
|
58
|
-
|
|
59
|
-
// If source is "upload", delete the file
|
|
60
|
-
if (profile_source_ui === "upload") {
|
|
61
|
-
try {
|
|
62
|
-
const config = get_profile_picture_config();
|
|
63
|
-
|
|
64
|
-
if (config.upload_photo_path) {
|
|
65
|
-
// Extract filename from URL (e.g., /api/hazo_auth/profile_picture/user_id.jpg)
|
|
66
|
-
const fileName = profile_picture_url.split("/").pop();
|
|
67
|
-
|
|
68
|
-
if (fileName && fileName.startsWith(user_id)) {
|
|
69
|
-
// Resolve upload path
|
|
70
|
-
const uploadPath = path.isAbsolute(config.upload_photo_path)
|
|
71
|
-
? config.upload_photo_path
|
|
72
|
-
: path.resolve(process.cwd(), config.upload_photo_path);
|
|
73
|
-
|
|
74
|
-
const filePath = path.join(uploadPath, fileName);
|
|
75
|
-
|
|
76
|
-
// Delete file if it exists
|
|
77
|
-
if (fs.existsSync(filePath)) {
|
|
78
|
-
fs.unlinkSync(filePath);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
} catch (error) {
|
|
83
|
-
// Log error but continue with database update
|
|
84
|
-
const logger = create_app_logger();
|
|
85
|
-
const error_message = error instanceof Error ? error.message : "Unknown error";
|
|
86
|
-
logger.warn("profile_picture_remove_file_delete_failed", {
|
|
87
|
-
filename: "profile_picture_remove_service.ts",
|
|
88
|
-
line_number: 0,
|
|
89
|
-
user_id,
|
|
90
|
-
profile_picture_url,
|
|
91
|
-
error: error_message,
|
|
92
|
-
});
|
|
93
|
-
// Don't fail the request if file deletion fails - still clear the database
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Clear profile picture URL and source in database
|
|
98
|
-
// Note: profile_source has a CHECK constraint, so we'll set it to null
|
|
99
|
-
// If the database doesn't allow null, we may need to handle it differently
|
|
100
|
-
const update_data: Record<string, unknown> = {
|
|
101
|
-
changed_at: new Date().toISOString(),
|
|
102
|
-
profile_picture_url: null,
|
|
103
|
-
profile_source: null,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
await users_service.updateById(user_id, update_data);
|
|
107
|
-
|
|
108
|
-
return {
|
|
109
|
-
success: true,
|
|
110
|
-
};
|
|
111
|
-
} catch (error) {
|
|
112
|
-
const error_message = error instanceof Error ? error.message : "Unknown error";
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
success: false,
|
|
116
|
-
error: error_message,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|