hazo_auth 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/bin/hazo_auth.mjs +35 -0
  2. package/cli-src/assets/images/forgot_password_default.jpg +0 -0
  3. package/cli-src/assets/images/login_default.jpg +0 -0
  4. package/cli-src/assets/images/register_default.jpg +0 -0
  5. package/cli-src/assets/images/reset_password_default.jpg +0 -0
  6. package/cli-src/assets/images/verify_email_default.jpg +0 -0
  7. package/cli-src/cli/generate.ts +276 -0
  8. package/cli-src/cli/index.ts +207 -0
  9. package/cli-src/cli/init.ts +254 -0
  10. package/cli-src/cli/init_users.ts +376 -0
  11. package/cli-src/cli/validate.ts +581 -0
  12. package/cli-src/lib/already_logged_in_config.server.ts +46 -0
  13. package/cli-src/lib/app_logger.ts +24 -0
  14. package/cli-src/lib/auth/auth_cache.ts +220 -0
  15. package/cli-src/lib/auth/auth_rate_limiter.ts +121 -0
  16. package/cli-src/lib/auth/auth_types.ts +110 -0
  17. package/cli-src/lib/auth/auth_utils.server.ts +196 -0
  18. package/cli-src/lib/auth/hazo_get_auth.server.ts +512 -0
  19. package/cli-src/lib/auth/index.ts +23 -0
  20. package/cli-src/lib/auth/nextauth_config.ts +227 -0
  21. package/cli-src/lib/auth/scope_cache.ts +233 -0
  22. package/cli-src/lib/auth/server_auth.ts +88 -0
  23. package/cli-src/lib/auth/session_token_validator.edge.ts +91 -0
  24. package/cli-src/lib/auth_utility_config.server.ts +136 -0
  25. package/cli-src/lib/config/config_loader.server.ts +164 -0
  26. package/cli-src/lib/config/default_config.ts +199 -0
  27. package/cli-src/lib/email_verification_config.server.ts +63 -0
  28. package/cli-src/lib/file_types_config.server.ts +25 -0
  29. package/cli-src/lib/forgot_password_config.server.ts +63 -0
  30. package/cli-src/lib/hazo_connect_instance.server.ts +101 -0
  31. package/cli-src/lib/hazo_connect_setup.server.ts +194 -0
  32. package/cli-src/lib/hazo_connect_setup.ts +54 -0
  33. package/cli-src/lib/index.ts +46 -0
  34. package/cli-src/lib/login_config.server.ts +106 -0
  35. package/cli-src/lib/messages_config.server.ts +45 -0
  36. package/cli-src/lib/migrations/apply_migration.ts +105 -0
  37. package/cli-src/lib/my_settings_config.server.ts +135 -0
  38. package/cli-src/lib/oauth_config.server.ts +87 -0
  39. package/cli-src/lib/password_requirements_config.server.ts +40 -0
  40. package/cli-src/lib/profile_pic_menu_config.server.ts +138 -0
  41. package/cli-src/lib/profile_picture_config.server.ts +56 -0
  42. package/cli-src/lib/register_config.server.ts +101 -0
  43. package/cli-src/lib/reset_password_config.server.ts +103 -0
  44. package/cli-src/lib/scope_hierarchy_config.server.ts +151 -0
  45. package/cli-src/lib/services/email_service.ts +587 -0
  46. package/cli-src/lib/services/email_verification_service.ts +270 -0
  47. package/cli-src/lib/services/index.ts +16 -0
  48. package/cli-src/lib/services/login_service.ts +150 -0
  49. package/cli-src/lib/services/oauth_service.ts +494 -0
  50. package/cli-src/lib/services/password_change_service.ts +154 -0
  51. package/cli-src/lib/services/password_reset_service.ts +418 -0
  52. package/cli-src/lib/services/profile_picture_remove_service.ts +120 -0
  53. package/cli-src/lib/services/profile_picture_service.ts +451 -0
  54. package/cli-src/lib/services/profile_picture_source_mapper.ts +62 -0
  55. package/cli-src/lib/services/registration_service.ts +185 -0
  56. package/cli-src/lib/services/scope_labels_service.ts +348 -0
  57. package/cli-src/lib/services/scope_service.ts +778 -0
  58. package/cli-src/lib/services/session_token_service.ts +177 -0
  59. package/cli-src/lib/services/token_service.ts +240 -0
  60. package/cli-src/lib/services/user_profiles_cache.ts +189 -0
  61. package/cli-src/lib/services/user_profiles_service.ts +264 -0
  62. package/cli-src/lib/services/user_scope_service.ts +554 -0
  63. package/cli-src/lib/services/user_update_service.ts +141 -0
  64. package/cli-src/lib/ui_shell_config.server.ts +73 -0
  65. package/cli-src/lib/ui_sizes_config.server.ts +37 -0
  66. package/cli-src/lib/user_fields_config.server.ts +31 -0
  67. package/cli-src/lib/user_management_config.server.ts +39 -0
  68. package/cli-src/lib/user_profiles_config.server.ts +55 -0
  69. package/cli-src/lib/utils/api_route_helpers.ts +60 -0
  70. package/cli-src/lib/utils/error_sanitizer.ts +75 -0
  71. package/cli-src/lib/utils/password_validator.ts +65 -0
  72. package/cli-src/lib/utils.ts +11 -0
  73. package/cli-src/server/logging/logger_service.ts +56 -0
  74. package/dist/cli/index.js +18 -0
  75. package/dist/cli/init_users.d.ts +17 -0
  76. package/dist/cli/init_users.d.ts.map +1 -0
  77. package/dist/cli/init_users.js +307 -0
  78. package/dist/components/layouts/shared/config/layout_customization.d.ts +2 -7
  79. package/dist/components/layouts/shared/config/layout_customization.d.ts.map +1 -1
  80. package/dist/lib/utils/password_validator.d.ts +7 -1
  81. package/dist/lib/utils/password_validator.d.ts.map +1 -1
  82. package/package.json +5 -2
@@ -0,0 +1,135 @@
1
+ // file_description: server-only helper to read my settings layout configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_value } from "./config/config_loader.server";
4
+ import { get_user_fields_config } from "./user_fields_config.server";
5
+ import { get_password_requirements_config } from "./password_requirements_config.server";
6
+ import { get_profile_picture_config } from "./profile_picture_config.server";
7
+ import { get_messages_config } from "./messages_config.server";
8
+ import { get_ui_sizes_config } from "./ui_sizes_config.server";
9
+ import { get_file_types_config } from "./file_types_config.server";
10
+
11
+ // section: types
12
+ export type MySettingsConfig = {
13
+ userFields: {
14
+ show_name_field: boolean;
15
+ show_email_field: boolean;
16
+ show_password_field: boolean;
17
+ };
18
+ passwordRequirements: {
19
+ minimum_length: number;
20
+ require_uppercase: boolean;
21
+ require_lowercase: boolean;
22
+ require_number: boolean;
23
+ require_special: boolean;
24
+ };
25
+ profilePicture: {
26
+ allow_photo_upload: boolean;
27
+ upload_photo_path?: string;
28
+ max_photo_size: number;
29
+ user_photo_default: boolean;
30
+ user_photo_default_priority1: "gravatar" | "library";
31
+ user_photo_default_priority2?: "library" | "gravatar";
32
+ library_photo_path: string;
33
+ };
34
+ heading?: string;
35
+ subHeading?: string;
36
+ profilePhotoLabel?: string;
37
+ profilePhotoRecommendation?: string;
38
+ uploadPhotoButtonLabel?: string;
39
+ removePhotoButtonLabel?: string;
40
+ profileInformationLabel?: string;
41
+ passwordLabel?: string;
42
+ currentPasswordLabel?: string;
43
+ newPasswordLabel?: string;
44
+ confirmPasswordLabel?: string;
45
+ savePasswordButtonLabel?: string;
46
+ unauthorizedMessage?: string;
47
+ loginButtonLabel?: string;
48
+ loginPath?: string;
49
+ messages: {
50
+ photo_upload_disabled_message: string;
51
+ gravatar_setup_message: string;
52
+ gravatar_no_account_message: string;
53
+ library_tooltip_message: string;
54
+ };
55
+ uiSizes: {
56
+ gravatar_size: number;
57
+ profile_picture_size: number;
58
+ tooltip_icon_size_default: number;
59
+ tooltip_icon_size_small: number;
60
+ library_photo_grid_columns: number;
61
+ library_photo_preview_size: number;
62
+ image_compression_max_dimension: number;
63
+ upload_file_hard_limit_bytes: number;
64
+ };
65
+ fileTypes: {
66
+ allowed_image_extensions: string[];
67
+ allowed_image_mime_types: string[];
68
+ };
69
+ };
70
+
71
+ // section: helpers
72
+ /**
73
+ * Reads my settings layout configuration from hazo_auth_config.ini file
74
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
75
+ * @returns My settings configuration options
76
+ */
77
+ export function get_my_settings_config(): MySettingsConfig {
78
+ const section = "hazo_auth__my_settings_layout";
79
+
80
+ // Get shared user fields config
81
+ const userFields = get_user_fields_config();
82
+
83
+ // Get shared password requirements
84
+ const passwordRequirements = get_password_requirements_config();
85
+
86
+ // Get profile picture configuration
87
+ const profilePicture = get_profile_picture_config();
88
+
89
+ // Get messages, UI sizes, and file types configuration
90
+ const messages = get_messages_config();
91
+ const uiSizes = get_ui_sizes_config();
92
+ const fileTypes = get_file_types_config();
93
+
94
+ // Read optional labels with defaults
95
+ const heading = get_config_value(section, "heading", "Account Settings");
96
+ const subHeading = get_config_value(section, "sub_heading", "Manage your profile, password, and email preferences.");
97
+ const profilePhotoLabel = get_config_value(section, "profile_photo_label", "Profile Photo");
98
+ const profilePhotoRecommendation = get_config_value(section, "profile_photo_recommendation", "Recommended size: 200x200px. JPG, PNG.");
99
+ const uploadPhotoButtonLabel = get_config_value(section, "upload_photo_button_label", "Upload New Photo");
100
+ const removePhotoButtonLabel = get_config_value(section, "remove_photo_button_label", "Remove");
101
+ const profileInformationLabel = get_config_value(section, "profile_information_label", "Profile Information");
102
+ const passwordLabel = get_config_value(section, "password_label", "Password");
103
+ const currentPasswordLabel = get_config_value(section, "current_password_label", "Current Password");
104
+ const newPasswordLabel = get_config_value(section, "new_password_label", "New Password");
105
+ const confirmPasswordLabel = get_config_value(section, "confirm_password_label", "Confirm Password");
106
+ const savePasswordButtonLabel = get_config_value(section, "save_password_button_label", "Save Password");
107
+ const unauthorizedMessage = get_config_value(section, "unauthorized_message", "You must be logged in to access this page.");
108
+ const loginButtonLabel = get_config_value(section, "login_button_label", "Go to login");
109
+ const loginPath = get_config_value(section, "login_path", "/hazo_auth/login");
110
+
111
+ return {
112
+ userFields,
113
+ passwordRequirements,
114
+ profilePicture,
115
+ heading,
116
+ subHeading,
117
+ profilePhotoLabel,
118
+ profilePhotoRecommendation,
119
+ uploadPhotoButtonLabel,
120
+ removePhotoButtonLabel,
121
+ profileInformationLabel,
122
+ passwordLabel,
123
+ currentPasswordLabel,
124
+ newPasswordLabel,
125
+ confirmPasswordLabel,
126
+ savePasswordButtonLabel,
127
+ unauthorizedMessage,
128
+ loginButtonLabel,
129
+ loginPath,
130
+ messages,
131
+ uiSizes,
132
+ fileTypes,
133
+ };
134
+ }
135
+
@@ -0,0 +1,87 @@
1
+ // file_description: server-only helper to read OAuth configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_value, get_config_boolean } from "./config/config_loader.server";
4
+ import { DEFAULT_OAUTH } from "./config/default_config";
5
+
6
+ // section: types
7
+ export type OAuthConfig = {
8
+ /** Enable Google OAuth login */
9
+ enable_google: boolean;
10
+ /** Enable traditional email/password login */
11
+ enable_email_password: boolean;
12
+ /** Auto-link Google login to existing unverified email/password accounts */
13
+ auto_link_unverified_accounts: boolean;
14
+ /** Text displayed on the Google sign-in button */
15
+ google_button_text: string;
16
+ /** Text displayed on the divider between OAuth and email/password form */
17
+ oauth_divider_text: string;
18
+ };
19
+
20
+ // section: constants
21
+ const SECTION_NAME = "hazo_auth__oauth";
22
+
23
+ // section: helpers
24
+ /**
25
+ * Reads OAuth configuration from hazo_auth_config.ini file
26
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
27
+ * @returns OAuth configuration options
28
+ */
29
+ export function get_oauth_config(): OAuthConfig {
30
+ const enable_google = get_config_boolean(
31
+ SECTION_NAME,
32
+ "enable_google",
33
+ DEFAULT_OAUTH.enable_google
34
+ );
35
+
36
+ const enable_email_password = get_config_boolean(
37
+ SECTION_NAME,
38
+ "enable_email_password",
39
+ DEFAULT_OAUTH.enable_email_password
40
+ );
41
+
42
+ const auto_link_unverified_accounts = get_config_boolean(
43
+ SECTION_NAME,
44
+ "auto_link_unverified_accounts",
45
+ DEFAULT_OAUTH.auto_link_unverified_accounts
46
+ );
47
+
48
+ const google_button_text = get_config_value(
49
+ SECTION_NAME,
50
+ "google_button_text",
51
+ DEFAULT_OAUTH.google_button_text
52
+ );
53
+
54
+ const oauth_divider_text = get_config_value(
55
+ SECTION_NAME,
56
+ "oauth_divider_text",
57
+ DEFAULT_OAUTH.oauth_divider_text
58
+ );
59
+
60
+ return {
61
+ enable_google,
62
+ enable_email_password,
63
+ auto_link_unverified_accounts,
64
+ google_button_text,
65
+ oauth_divider_text,
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Helper to check if Google OAuth is enabled
71
+ * @returns true if Google OAuth is enabled in config
72
+ */
73
+ export function is_google_oauth_enabled(): boolean {
74
+ return get_config_boolean(SECTION_NAME, "enable_google", DEFAULT_OAUTH.enable_google);
75
+ }
76
+
77
+ /**
78
+ * Helper to check if email/password login is enabled
79
+ * @returns true if email/password login is enabled in config
80
+ */
81
+ export function is_email_password_enabled(): boolean {
82
+ return get_config_boolean(
83
+ SECTION_NAME,
84
+ "enable_email_password",
85
+ DEFAULT_OAUTH.enable_email_password
86
+ );
87
+ }
@@ -0,0 +1,40 @@
1
+ // file_description: server-only helper to read shared password requirements configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_number, get_config_boolean } from "./config/config_loader.server";
4
+ import { DEFAULT_PASSWORD_REQUIREMENTS } from "./config/default_config";
5
+
6
+ // section: types
7
+ export type PasswordRequirementsConfig = {
8
+ minimum_length: number;
9
+ require_uppercase: boolean;
10
+ require_lowercase: boolean;
11
+ require_number: boolean;
12
+ require_special: boolean;
13
+ };
14
+
15
+ // section: helpers
16
+ /**
17
+ * Reads shared password requirements configuration from hazo_auth_config.ini file
18
+ * Falls back to centralized defaults if hazo_auth_config.ini is not found or section is missing
19
+ * This configuration is used by both register and reset password layouts
20
+ * @returns Password requirements configuration options
21
+ */
22
+ export function get_password_requirements_config(): PasswordRequirementsConfig {
23
+ const section = "hazo_auth__password_requirements";
24
+
25
+ // Read password requirements with centralized defaults
26
+ const minimum_length = get_config_number(section, "minimum_length", DEFAULT_PASSWORD_REQUIREMENTS.minimum_length);
27
+ const require_uppercase = get_config_boolean(section, "require_uppercase", DEFAULT_PASSWORD_REQUIREMENTS.require_uppercase);
28
+ const require_lowercase = get_config_boolean(section, "require_lowercase", DEFAULT_PASSWORD_REQUIREMENTS.require_lowercase);
29
+ const require_number = get_config_boolean(section, "require_number", DEFAULT_PASSWORD_REQUIREMENTS.require_number);
30
+ const require_special = get_config_boolean(section, "require_special", DEFAULT_PASSWORD_REQUIREMENTS.require_special);
31
+
32
+ return {
33
+ minimum_length,
34
+ require_uppercase,
35
+ require_lowercase,
36
+ require_number,
37
+ require_special,
38
+ };
39
+ }
40
+
@@ -0,0 +1,138 @@
1
+ // file_description: server-only helper to read profile picture menu configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_value, get_config_boolean, get_config_array } from "./config/config_loader.server";
4
+
5
+ // section: types
6
+ // Note: These types are also used in client components, but TypeScript types are erased at runtime
7
+ // so importing from a server file is safe for type-only imports
8
+ export type MenuItemType = "info" | "link" | "separator";
9
+
10
+ export type ProfilePicMenuMenuItem = {
11
+ type: MenuItemType;
12
+ label?: string; // For info and link types
13
+ value?: string; // For info type (e.g., user name, email)
14
+ href?: string; // For link type
15
+ order: number; // Ordering within type group
16
+ id: string; // Unique identifier for the item
17
+ };
18
+
19
+ export type ProfilePicMenuConfig = {
20
+ show_single_button: boolean;
21
+ sign_up_label: string;
22
+ sign_in_label: string;
23
+ register_path: string;
24
+ login_path: string;
25
+ settings_path: string;
26
+ logout_path: string;
27
+ custom_menu_items: ProfilePicMenuMenuItem[];
28
+ };
29
+
30
+ // section: helpers
31
+ /**
32
+ * Parses custom menu items from config string
33
+ * Format: "type:label:order" or "type:label:href:order" for links
34
+ * Example: "link:My Custom Link:/custom:3"
35
+ * @param items_string - Comma-separated string of menu items
36
+ * @returns Array of parsed menu items
37
+ */
38
+ function parse_custom_menu_items(items_string: string[]): ProfilePicMenuMenuItem[] {
39
+ const items: ProfilePicMenuMenuItem[] = [];
40
+
41
+ items_string.forEach((item_string, index) => {
42
+ const parts = item_string.split(":").map((p) => p.trim());
43
+
44
+ if (parts.length < 3) {
45
+ return; // Invalid format, skip
46
+ }
47
+
48
+ const type = parts[0] as MenuItemType;
49
+ if (type !== "info" && type !== "link" && type !== "separator") {
50
+ return; // Invalid type, skip
51
+ }
52
+
53
+ if (type === "separator") {
54
+ const order = parseInt(parts[1] || "1", 10);
55
+ items.push({
56
+ type: "separator",
57
+ order: isNaN(order) ? 1 : order,
58
+ id: `custom_separator_${index}`,
59
+ });
60
+ return;
61
+ }
62
+
63
+ if (type === "info") {
64
+ const label = parts[1] || "";
65
+ const value = parts[2] || "";
66
+ const order = parseInt(parts[3] || "1", 10);
67
+
68
+ if (!label || !value) {
69
+ return; // Invalid format, skip
70
+ }
71
+
72
+ items.push({
73
+ type: "info",
74
+ label,
75
+ value,
76
+ order: isNaN(order) ? 1 : order,
77
+ id: `custom_info_${index}`,
78
+ });
79
+ return;
80
+ }
81
+
82
+ if (type === "link") {
83
+ const label = parts[1] || "";
84
+ const href = parts[2] || "";
85
+ const order = parseInt(parts[3] || "1", 10);
86
+
87
+ if (!label || !href) {
88
+ return; // Invalid format, skip
89
+ }
90
+
91
+ items.push({
92
+ type: "link",
93
+ label,
94
+ href,
95
+ order: isNaN(order) ? 1 : order,
96
+ id: `custom_link_${index}`,
97
+ });
98
+ }
99
+ });
100
+
101
+ return items;
102
+ }
103
+
104
+ /**
105
+ * Reads profile picture menu configuration from hazo_auth_config.ini file
106
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
107
+ * @returns Profile picture menu configuration options
108
+ */
109
+ export function get_profile_pic_menu_config(): ProfilePicMenuConfig {
110
+ const section = "hazo_auth__profile_pic_menu";
111
+
112
+ // Read button configuration
113
+ const show_single_button = get_config_boolean(section, "show_single_button", false);
114
+ const sign_up_label = get_config_value(section, "sign_up_label", "Sign Up");
115
+ const sign_in_label = get_config_value(section, "sign_in_label", "Sign In");
116
+ const register_path = get_config_value(section, "register_path", "/hazo_auth/register");
117
+ const login_path = get_config_value(section, "login_path", "/hazo_auth/login");
118
+
119
+ // Read menu paths
120
+ const settings_path = get_config_value(section, "settings_path", "/hazo_auth/my_settings");
121
+ const logout_path = get_config_value(section, "logout_path", "/api/hazo_auth/logout");
122
+
123
+ // Read custom menu items
124
+ const custom_items_string = get_config_array(section, "custom_menu_items", []);
125
+ const custom_menu_items = parse_custom_menu_items(custom_items_string);
126
+
127
+ return {
128
+ show_single_button,
129
+ sign_up_label,
130
+ sign_in_label,
131
+ register_path,
132
+ login_path,
133
+ settings_path,
134
+ logout_path,
135
+ custom_menu_items,
136
+ };
137
+ }
138
+
@@ -0,0 +1,56 @@
1
+ // file_description: server-only helper to read profile picture configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_boolean, get_config_value, get_config_number, read_config_section } from "./config/config_loader.server";
4
+ import { create_app_logger } from "./app_logger";
5
+
6
+ // section: types
7
+ export type ProfilePictureConfig = {
8
+ allow_photo_upload: boolean;
9
+ upload_photo_path?: string;
10
+ max_photo_size: number; // in bytes
11
+ user_photo_default: boolean;
12
+ user_photo_default_priority1: "gravatar" | "library";
13
+ user_photo_default_priority2?: "library" | "gravatar";
14
+ library_photo_path: string; // relative to public directory
15
+ };
16
+
17
+ // section: helpers
18
+ /**
19
+ * Reads profile picture configuration from hazo_auth_config.ini file
20
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
21
+ * @returns Profile picture configuration options
22
+ */
23
+ export function get_profile_picture_config(): ProfilePictureConfig {
24
+ const logger = create_app_logger();
25
+ const section = "hazo_auth__profile_picture";
26
+
27
+ // Read configuration with defaults
28
+ const allow_photo_upload = get_config_boolean(section, "allow_photo_upload", false);
29
+ const upload_photo_path = get_config_value(section, "upload_photo_path", "");
30
+ const max_photo_size = get_config_number(section, "max_photo_size", 51200); // Default: 50kb
31
+ const user_photo_default = get_config_boolean(section, "user_photo_default", true);
32
+ const user_photo_default_priority1 = (get_config_value(section, "user_photo_default_priority1", "gravatar") as "gravatar" | "library");
33
+ const priority2_value = get_config_value(section, "user_photo_default_priority2", "");
34
+ const user_photo_default_priority2 = priority2_value ? (priority2_value as "library" | "gravatar") : undefined;
35
+ const library_photo_path = get_config_value(section, "library_photo_path", "/profile_pictures/library");
36
+
37
+ // Validate upload_photo_path if allow_photo_upload is true
38
+ if (allow_photo_upload && !upload_photo_path) {
39
+ logger.warn("profile_picture_config_validation_failed", {
40
+ filename: "profile_picture_config.server.ts",
41
+ line_number: 0,
42
+ message: "allow_photo_upload is true but upload_photo_path is not set",
43
+ });
44
+ }
45
+
46
+ return {
47
+ allow_photo_upload,
48
+ upload_photo_path: upload_photo_path || undefined,
49
+ max_photo_size,
50
+ user_photo_default,
51
+ user_photo_default_priority1,
52
+ user_photo_default_priority2,
53
+ library_photo_path,
54
+ };
55
+ }
56
+
@@ -0,0 +1,101 @@
1
+ // file_description: server-only helper to read register layout configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_boolean, get_config_value, read_config_section } from "./config/config_loader.server";
4
+ import { get_password_requirements_config } from "./password_requirements_config.server";
5
+ import { get_already_logged_in_config } from "./already_logged_in_config.server";
6
+ import { get_user_fields_config } from "./user_fields_config.server";
7
+ import registerDefaultImage from "../assets/images/register_default.jpg";
8
+
9
+ // section: types
10
+ import type { StaticImageData } from "next/image";
11
+
12
+ export type RegisterConfig = {
13
+ showNameField: boolean;
14
+ passwordRequirements: {
15
+ minimum_length: number;
16
+ require_uppercase: boolean;
17
+ require_lowercase: boolean;
18
+ require_number: boolean;
19
+ require_special: boolean;
20
+ };
21
+ alreadyLoggedInMessage: string;
22
+ showLogoutButton: boolean;
23
+ showReturnHomeButton: boolean;
24
+ returnHomeButtonLabel: string;
25
+ returnHomePath: string;
26
+ signInPath: string;
27
+ signInLabel: string;
28
+ imageSrc: string | StaticImageData;
29
+ imageAlt: string;
30
+ imageBackgroundColor: string;
31
+ };
32
+
33
+ // section: helpers
34
+ /**
35
+ * Reads register layout configuration from hazo_auth_config.ini file
36
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
37
+ * @returns Register configuration options
38
+ */
39
+ export function get_register_config(): RegisterConfig {
40
+ // Get shared user fields config (preferred) or fall back to register section for backwards compatibility
41
+ const userFieldsConfig = get_user_fields_config();
42
+ const register_section = read_config_section("hazo_auth__register_layout");
43
+
44
+ // Use register section if explicitly set, otherwise use shared config
45
+ const showNameField = register_section?.show_name_field !== undefined
46
+ ? get_config_boolean("hazo_auth__register_layout", "show_name_field", true)
47
+ : userFieldsConfig.show_name_field;
48
+
49
+ // Get shared password requirements
50
+ const passwordRequirements = get_password_requirements_config();
51
+
52
+ // Get shared already logged in config
53
+ const alreadyLoggedInConfig = get_already_logged_in_config();
54
+
55
+ // Read sign in link configuration
56
+ const signInPath = get_config_value(
57
+ "hazo_auth__register_layout",
58
+ "sign_in_path",
59
+ "/hazo_auth/login"
60
+ );
61
+ const signInLabel = get_config_value(
62
+ "hazo_auth__register_layout",
63
+ "sign_in_label",
64
+ "Sign in"
65
+ );
66
+
67
+ // Read image configuration
68
+ // If not set in config, falls back to default image from assets
69
+ const imageSrc = get_config_value(
70
+ "hazo_auth__register_layout",
71
+ "image_src",
72
+ "" // Empty string means not set in config
73
+ ) || registerDefaultImage;
74
+
75
+ const imageAlt = get_config_value(
76
+ "hazo_auth__register_layout",
77
+ "image_alt",
78
+ "Modern building representing user registration"
79
+ );
80
+ const imageBackgroundColor = get_config_value(
81
+ "hazo_auth__register_layout",
82
+ "image_background_color",
83
+ "#e2e8f0"
84
+ );
85
+
86
+ return {
87
+ showNameField,
88
+ passwordRequirements,
89
+ alreadyLoggedInMessage: alreadyLoggedInConfig.message,
90
+ showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
91
+ showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
92
+ returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
93
+ returnHomePath: alreadyLoggedInConfig.returnHomePath,
94
+ signInPath,
95
+ signInLabel,
96
+ imageSrc,
97
+ imageAlt,
98
+ imageBackgroundColor,
99
+ };
100
+ }
101
+
@@ -0,0 +1,103 @@
1
+ // file_description: server-only helper to read reset password layout configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_value } from "./config/config_loader.server";
4
+ import { get_already_logged_in_config } from "./already_logged_in_config.server";
5
+ import { get_password_requirements_config } from "./password_requirements_config.server";
6
+ import resetPasswordDefaultImage from "../assets/images/reset_password_default.jpg";
7
+
8
+ // section: types
9
+ import type { StaticImageData } from "next/image";
10
+
11
+ export type ResetPasswordConfig = {
12
+ errorMessage: string;
13
+ successMessage: string;
14
+ loginPath: string;
15
+ forgotPasswordPath: string;
16
+ alreadyLoggedInMessage: string;
17
+ showLogoutButton: boolean;
18
+ showReturnHomeButton: boolean;
19
+ returnHomeButtonLabel: string;
20
+ returnHomePath: string;
21
+ passwordRequirements: {
22
+ minimum_length: number;
23
+ require_uppercase: boolean;
24
+ require_lowercase: boolean;
25
+ require_number: boolean;
26
+ require_special: boolean;
27
+ };
28
+ imageSrc: string | StaticImageData;
29
+ imageAlt: string;
30
+ imageBackgroundColor: string;
31
+ };
32
+
33
+ // section: helpers
34
+ /**
35
+ * Reads reset password layout configuration from hazo_auth_config.ini file
36
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
37
+ * @returns Reset password configuration options
38
+ */
39
+ export function get_reset_password_config(): ResetPasswordConfig {
40
+ const section = "hazo_auth__reset_password_layout";
41
+
42
+ // Get shared already logged in config
43
+ const alreadyLoggedInConfig = get_already_logged_in_config();
44
+
45
+ // Read error message (defaults to standard message)
46
+ const errorMessage = get_config_value(
47
+ section,
48
+ "error_message",
49
+ "Reset password link invalid or has expired. Please go to Reset Password page to get a new link."
50
+ );
51
+
52
+ // Read success message (defaults to standard message)
53
+ const successMessage = get_config_value(
54
+ section,
55
+ "success_message",
56
+ "Password reset successfully. Redirecting to login..."
57
+ );
58
+
59
+ // Read login path (defaults to "/hazo_auth/login")
60
+ const loginPath = get_config_value(section, "login_path", "/hazo_auth/login");
61
+
62
+ // Read forgot password path (defaults to "/hazo_auth/forgot_password")
63
+ const forgotPasswordPath = get_config_value(section, "forgot_password_path", "/hazo_auth/forgot_password");
64
+
65
+ // Get shared password requirements
66
+ const passwordRequirements = get_password_requirements_config();
67
+
68
+ // Read image configuration
69
+ // If not set in config, falls back to default image from assets
70
+ const imageSrc = get_config_value(
71
+ section,
72
+ "image_src",
73
+ "" // Empty string means not set in config
74
+ ) || resetPasswordDefaultImage;
75
+
76
+ const imageAlt = get_config_value(
77
+ section,
78
+ "image_alt",
79
+ "Reset password illustration"
80
+ );
81
+ const imageBackgroundColor = get_config_value(
82
+ section,
83
+ "image_background_color",
84
+ "#f1f5f9"
85
+ );
86
+
87
+ return {
88
+ errorMessage,
89
+ successMessage,
90
+ loginPath,
91
+ forgotPasswordPath,
92
+ alreadyLoggedInMessage: alreadyLoggedInConfig.message,
93
+ showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
94
+ showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
95
+ returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
96
+ returnHomePath: alreadyLoggedInConfig.returnHomePath,
97
+ passwordRequirements,
98
+ imageSrc,
99
+ imageAlt,
100
+ imageBackgroundColor,
101
+ };
102
+ }
103
+