hazo_auth 4.2.0 → 4.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.
Files changed (136) 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 +117 -0
  17. package/cli-src/lib/auth/auth_utils.server.ts +196 -0
  18. package/cli-src/lib/auth/dev_lock_validator.edge.ts +171 -0
  19. package/cli-src/lib/auth/hazo_get_auth.server.ts +583 -0
  20. package/cli-src/lib/auth/index.ts +23 -0
  21. package/cli-src/lib/auth/nextauth_config.ts +227 -0
  22. package/cli-src/lib/auth/org_cache.ts +148 -0
  23. package/cli-src/lib/auth/scope_cache.ts +233 -0
  24. package/cli-src/lib/auth/server_auth.ts +88 -0
  25. package/cli-src/lib/auth/session_token_validator.edge.ts +92 -0
  26. package/cli-src/lib/auth_utility_config.server.ts +136 -0
  27. package/cli-src/lib/config/config_loader.server.ts +164 -0
  28. package/cli-src/lib/config/default_config.ts +243 -0
  29. package/cli-src/lib/dev_lock_config.server.ts +148 -0
  30. package/cli-src/lib/email_verification_config.server.ts +63 -0
  31. package/cli-src/lib/file_types_config.server.ts +25 -0
  32. package/cli-src/lib/forgot_password_config.server.ts +63 -0
  33. package/cli-src/lib/hazo_connect_instance.server.ts +101 -0
  34. package/cli-src/lib/hazo_connect_setup.server.ts +194 -0
  35. package/cli-src/lib/hazo_connect_setup.ts +54 -0
  36. package/cli-src/lib/index.ts +46 -0
  37. package/cli-src/lib/login_config.server.ts +106 -0
  38. package/cli-src/lib/messages_config.server.ts +45 -0
  39. package/cli-src/lib/migrations/apply_migration.ts +105 -0
  40. package/cli-src/lib/multi_tenancy_config.server.ts +94 -0
  41. package/cli-src/lib/my_settings_config.server.ts +135 -0
  42. package/cli-src/lib/oauth_config.server.ts +87 -0
  43. package/cli-src/lib/password_requirements_config.server.ts +40 -0
  44. package/cli-src/lib/profile_pic_menu_config.server.ts +138 -0
  45. package/cli-src/lib/profile_picture_config.server.ts +56 -0
  46. package/cli-src/lib/register_config.server.ts +101 -0
  47. package/cli-src/lib/reset_password_config.server.ts +103 -0
  48. package/cli-src/lib/scope_hierarchy_config.server.ts +151 -0
  49. package/cli-src/lib/services/email_service.ts +587 -0
  50. package/cli-src/lib/services/email_verification_service.ts +270 -0
  51. package/cli-src/lib/services/index.ts +16 -0
  52. package/cli-src/lib/services/login_service.ts +150 -0
  53. package/cli-src/lib/services/oauth_service.ts +494 -0
  54. package/cli-src/lib/services/org_service.ts +965 -0
  55. package/cli-src/lib/services/password_change_service.ts +154 -0
  56. package/cli-src/lib/services/password_reset_service.ts +418 -0
  57. package/cli-src/lib/services/profile_picture_remove_service.ts +120 -0
  58. package/cli-src/lib/services/profile_picture_service.ts +451 -0
  59. package/cli-src/lib/services/profile_picture_source_mapper.ts +62 -0
  60. package/cli-src/lib/services/registration_service.ts +185 -0
  61. package/cli-src/lib/services/scope_labels_service.ts +348 -0
  62. package/cli-src/lib/services/scope_service.ts +778 -0
  63. package/cli-src/lib/services/session_token_service.ts +178 -0
  64. package/cli-src/lib/services/token_service.ts +240 -0
  65. package/cli-src/lib/services/user_profiles_cache.ts +189 -0
  66. package/cli-src/lib/services/user_profiles_service.ts +264 -0
  67. package/cli-src/lib/services/user_scope_service.ts +554 -0
  68. package/cli-src/lib/services/user_update_service.ts +141 -0
  69. package/cli-src/lib/ui_shell_config.server.ts +73 -0
  70. package/cli-src/lib/ui_sizes_config.server.ts +37 -0
  71. package/cli-src/lib/user_fields_config.server.ts +31 -0
  72. package/cli-src/lib/user_management_config.server.ts +39 -0
  73. package/cli-src/lib/user_profiles_config.server.ts +55 -0
  74. package/cli-src/lib/utils/api_route_helpers.ts +60 -0
  75. package/cli-src/lib/utils/error_sanitizer.ts +75 -0
  76. package/cli-src/lib/utils/password_validator.ts +65 -0
  77. package/cli-src/lib/utils.ts +11 -0
  78. package/cli-src/server/logging/logger_service.ts +56 -0
  79. package/cli-src/server/types/app_types.ts +74 -0
  80. package/cli-src/server/types/express.d.ts +16 -0
  81. package/dist/cli/index.js +18 -0
  82. package/dist/cli/init_users.d.ts +17 -0
  83. package/dist/cli/init_users.d.ts.map +1 -0
  84. package/dist/cli/init_users.js +307 -0
  85. package/dist/components/layouts/dev_lock/index.d.ts +29 -0
  86. package/dist/components/layouts/dev_lock/index.d.ts.map +1 -0
  87. package/dist/components/layouts/dev_lock/index.js +60 -0
  88. package/dist/components/layouts/index.d.ts +2 -0
  89. package/dist/components/layouts/index.d.ts.map +1 -1
  90. package/dist/components/layouts/index.js +1 -0
  91. package/dist/components/layouts/org_management/index.d.ts +26 -0
  92. package/dist/components/layouts/org_management/index.d.ts.map +1 -0
  93. package/dist/components/layouts/org_management/index.js +75 -0
  94. package/dist/components/layouts/shared/config/layout_customization.d.ts +2 -7
  95. package/dist/components/layouts/shared/config/layout_customization.d.ts.map +1 -1
  96. package/dist/components/layouts/user_management/components/org_hierarchy_tab.d.ts +13 -0
  97. package/dist/components/layouts/user_management/components/org_hierarchy_tab.d.ts.map +1 -0
  98. package/dist/components/layouts/user_management/components/org_hierarchy_tab.js +276 -0
  99. package/dist/components/layouts/user_management/index.d.ts +3 -1
  100. package/dist/components/layouts/user_management/index.d.ts.map +1 -1
  101. package/dist/components/layouts/user_management/index.js +10 -4
  102. package/dist/lib/auth/auth_types.d.ts +6 -0
  103. package/dist/lib/auth/auth_types.d.ts.map +1 -1
  104. package/dist/lib/auth/dev_lock_validator.edge.d.ts +38 -0
  105. package/dist/lib/auth/dev_lock_validator.edge.d.ts.map +1 -0
  106. package/dist/lib/auth/dev_lock_validator.edge.js +122 -0
  107. package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -1
  108. package/dist/lib/auth/hazo_get_auth.server.js +61 -1
  109. package/dist/lib/auth/org_cache.d.ts +65 -0
  110. package/dist/lib/auth/org_cache.d.ts.map +1 -0
  111. package/dist/lib/auth/org_cache.js +103 -0
  112. package/dist/lib/config/default_config.d.ts +76 -0
  113. package/dist/lib/config/default_config.d.ts.map +1 -1
  114. package/dist/lib/config/default_config.js +42 -0
  115. package/dist/lib/dev_lock_config.server.d.ts +41 -0
  116. package/dist/lib/dev_lock_config.server.d.ts.map +1 -0
  117. package/dist/lib/dev_lock_config.server.js +50 -0
  118. package/dist/lib/multi_tenancy_config.server.d.ts +30 -0
  119. package/dist/lib/multi_tenancy_config.server.d.ts.map +1 -0
  120. package/dist/lib/multi_tenancy_config.server.js +41 -0
  121. package/dist/lib/services/org_service.d.ts +191 -0
  122. package/dist/lib/services/org_service.d.ts.map +1 -0
  123. package/dist/lib/services/org_service.js +746 -0
  124. package/dist/lib/utils/password_validator.d.ts +7 -1
  125. package/dist/lib/utils/password_validator.d.ts.map +1 -1
  126. package/dist/page_components/dev_lock.d.ts +11 -0
  127. package/dist/page_components/dev_lock.d.ts.map +1 -0
  128. package/dist/page_components/dev_lock.js +17 -0
  129. package/dist/page_components/index.d.ts +1 -0
  130. package/dist/page_components/index.d.ts.map +1 -1
  131. package/dist/page_components/index.js +1 -0
  132. package/dist/page_components/org_management.d.ts +27 -0
  133. package/dist/page_components/org_management.d.ts.map +1 -0
  134. package/dist/page_components/org_management.js +18 -0
  135. package/hazo_auth_config.example.ini +30 -0
  136. package/package.json +27 -3
@@ -0,0 +1,46 @@
1
+ // file_description: barrel export for lib utilities
2
+ // section: auth_exports
3
+ export * from "./auth/index";
4
+
5
+ // section: service_exports
6
+ export * from "./services/index";
7
+
8
+ // section: utility_exports
9
+ export { cn, merge_class_names } from "./utils.js";
10
+
11
+ // section: config_exports
12
+ export { get_config_value, get_config_number, get_config_boolean, get_config_array, read_config_section } from "./config/config_loader.server.js";
13
+
14
+ // section: hazo_connect_exports
15
+ export { create_sqlite_hazo_connect } from "./hazo_connect_setup.js";
16
+ export { get_hazo_connect_instance } from "./hazo_connect_instance.server.js";
17
+
18
+ // section: logger_exports
19
+ export { create_app_logger } from "./app_logger.js";
20
+
21
+ // section: config_server_exports
22
+ export { get_login_config } from "./login_config.server.js";
23
+ export { get_register_config } from "./register_config.server.js";
24
+ export { get_forgot_password_config } from "./forgot_password_config.server.js";
25
+ export { get_reset_password_config } from "./reset_password_config.server.js";
26
+ export { get_email_verification_config } from "./email_verification_config.server.js";
27
+ export { get_my_settings_config } from "./my_settings_config.server.js";
28
+ export { get_user_management_config } from "./user_management_config.server.js";
29
+ export { get_profile_picture_config } from "./profile_picture_config.server.js";
30
+ export { get_profile_pic_menu_config } from "./profile_pic_menu_config.server.js";
31
+ export { get_already_logged_in_config } from "./already_logged_in_config.server.js";
32
+ export { get_ui_shell_config } from "./ui_shell_config.server.js";
33
+ export { get_ui_sizes_config } from "./ui_sizes_config.server.js";
34
+ export { get_auth_utility_config } from "./auth_utility_config.server.js";
35
+ export { get_password_requirements_config } from "./password_requirements_config.server.js";
36
+ export { get_messages_config } from "./messages_config.server.js";
37
+ export { get_user_fields_config } from "./user_fields_config.server.js";
38
+ export { get_file_types_config } from "./file_types_config.server.js";
39
+ export { get_oauth_config, is_google_oauth_enabled, is_email_password_enabled } from "./oauth_config.server.js";
40
+ export type { OAuthConfig } from "./oauth_config.server";
41
+
42
+ // section: util_exports
43
+ export { sanitize_error_for_user } from "./utils/error_sanitizer.js";
44
+ export type { ErrorSanitizationOptions } from "./utils/error_sanitizer";
45
+ export * from "./utils/api_route_helpers";
46
+
@@ -0,0 +1,106 @@
1
+ // file_description: server-only helper to read login layout configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_value } from "./config/config_loader.server.js";
4
+ import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
5
+ import { get_oauth_config, type OAuthConfig } from "./oauth_config.server.js";
6
+ import loginDefaultImage from "../assets/images/login_default.jpg.js";
7
+
8
+ // section: types
9
+ import type { StaticImageData } from "next/image";
10
+
11
+ export type LoginConfig = {
12
+ redirectRoute?: string;
13
+ successMessage: string;
14
+ alreadyLoggedInMessage: string;
15
+ showLogoutButton: boolean;
16
+ showReturnHomeButton: boolean;
17
+ returnHomeButtonLabel: string;
18
+ returnHomePath: string;
19
+ forgotPasswordPath: string;
20
+ forgotPasswordLabel: string;
21
+ createAccountPath: string;
22
+ createAccountLabel: string;
23
+ imageSrc: string | StaticImageData;
24
+ imageAlt: string;
25
+ imageBackgroundColor: string;
26
+ /** OAuth configuration */
27
+ oauth: OAuthConfig;
28
+ };
29
+
30
+ // section: helpers
31
+ /**
32
+ * Reads login layout configuration from hazo_auth_config.ini file
33
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
34
+ * @returns Login configuration options
35
+ */
36
+ export function get_login_config(): LoginConfig {
37
+ const section = "hazo_auth__login_layout";
38
+
39
+ // Read redirect route (optional)
40
+ const redirectRouteValue = get_config_value(section, "redirect_route_on_successful_login", "");
41
+ const redirectRoute = redirectRouteValue || undefined;
42
+
43
+ // Read success message (defaults to "Successfully logged in")
44
+ const successMessage = get_config_value(section, "success_message", "Successfully logged in");
45
+
46
+ const forgotPasswordPath = get_config_value(
47
+ section,
48
+ "forgot_password_path",
49
+ "/hazo_auth/forgot_password"
50
+ );
51
+ const forgotPasswordLabel = get_config_value(
52
+ section,
53
+ "forgot_password_label",
54
+ "Forgot password?"
55
+ );
56
+ const createAccountPath = get_config_value(section, "create_account_path", "/hazo_auth/register");
57
+ const createAccountLabel = get_config_value(
58
+ section,
59
+ "create_account_label",
60
+ "Create account"
61
+ );
62
+
63
+ // Get shared already logged in config
64
+ const alreadyLoggedInConfig = get_already_logged_in_config();
65
+
66
+ // Read image configuration
67
+ // If not set in config, falls back to default image from assets
68
+ const imageSrc = get_config_value(
69
+ section,
70
+ "image_src",
71
+ "" // Empty string means not set in config
72
+ ) || loginDefaultImage;
73
+
74
+ const imageAlt = get_config_value(
75
+ section,
76
+ "image_alt",
77
+ "Secure login illustration"
78
+ );
79
+ const imageBackgroundColor = get_config_value(
80
+ section,
81
+ "image_background_color",
82
+ "#f1f5f9"
83
+ );
84
+
85
+ // Get OAuth configuration
86
+ const oauth = get_oauth_config();
87
+
88
+ return {
89
+ redirectRoute,
90
+ successMessage,
91
+ alreadyLoggedInMessage: alreadyLoggedInConfig.message,
92
+ showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
93
+ showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
94
+ returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
95
+ returnHomePath: alreadyLoggedInConfig.returnHomePath,
96
+ forgotPasswordPath,
97
+ forgotPasswordLabel,
98
+ createAccountPath,
99
+ createAccountLabel,
100
+ imageSrc,
101
+ imageAlt,
102
+ imageBackgroundColor,
103
+ oauth,
104
+ };
105
+ }
106
+
@@ -0,0 +1,45 @@
1
+ // file_description: server-only helper to read user-facing messages from hazo_auth_config.ini
2
+ // section: imports
3
+ import { get_config_value } from "./config/config_loader.server.js";
4
+
5
+ // section: types
6
+ export type MessagesConfig = {
7
+ photo_upload_disabled_message: string;
8
+ gravatar_setup_message: string;
9
+ gravatar_no_account_message: string;
10
+ library_tooltip_message: string;
11
+ };
12
+
13
+ // section: helpers
14
+ /**
15
+ * Reads user-facing messages from hazo_auth_config.ini file
16
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
17
+ * @returns Messages configuration options
18
+ */
19
+ export function get_messages_config(): MessagesConfig {
20
+ const section = "hazo_auth__messages";
21
+
22
+ return {
23
+ photo_upload_disabled_message: get_config_value(
24
+ section,
25
+ "photo_upload_disabled_message",
26
+ "Photo upload is not enabled. Please contact your administrator."
27
+ ),
28
+ gravatar_setup_message: get_config_value(
29
+ section,
30
+ "gravatar_setup_message",
31
+ "To set up your Gravatar:"
32
+ ),
33
+ gravatar_no_account_message: get_config_value(
34
+ section,
35
+ "gravatar_no_account_message",
36
+ "You don't have a Gravatar account set up for this email address."
37
+ ),
38
+ library_tooltip_message: get_config_value(
39
+ section,
40
+ "library_tooltip_message",
41
+ "Select another tab image style to remove this image"
42
+ ),
43
+ };
44
+ }
45
+
@@ -0,0 +1,105 @@
1
+ // file_description: helper to apply database migrations using hazo_connect
2
+ // section: imports
3
+ import type { HazoConnectAdapter } from "hazo_connect";
4
+ import { createCrudService } from "hazo_connect/server";
5
+ import fs from "fs";
6
+ import path from "path";
7
+
8
+ // section: helpers
9
+ /**
10
+ * Applies a SQL migration file to the database
11
+ * For SQLite, we need to execute raw SQL statements
12
+ * @param adapter - The hazo_connect adapter instance
13
+ * @param migration_file_path - Path to the SQL migration file
14
+ * @returns Success status and error message if any
15
+ */
16
+ export async function apply_migration(
17
+ adapter: HazoConnectAdapter,
18
+ migration_file_path: string,
19
+ ): Promise<{ success: boolean; error?: string }> {
20
+ try {
21
+ // Read the migration file
22
+ const migration_sql = fs.readFileSync(migration_file_path, "utf-8");
23
+
24
+ // Split SQL statements by semicolon and execute each one
25
+ // Remove comments and empty statements
26
+ const statements = migration_sql
27
+ .split(";")
28
+ .map((stmt) => stmt.trim())
29
+ .filter((stmt) => stmt.length > 0 && !stmt.startsWith("--"));
30
+
31
+ // Execute each statement
32
+ // For SQLite via hazo_connect, we may need to use a raw query method
33
+ // Since hazo_connect doesn't expose raw SQL execution directly,
34
+ // we'll try to use the adapter's internal methods or skip migration
35
+ // and rely on the fallback in token_service
36
+
37
+ // For now, we'll log that migration should be applied manually
38
+ // The token_service has fallback logic to work without token_type column
39
+ if (process.env.NODE_ENV === "development") {
40
+ console.log(
41
+ `[migrations] Migration file found: ${migration_file_path}`,
42
+ "\n[migrations] Note: Raw SQL execution not available via hazo_connect adapter.",
43
+ "\n[migrations] Please apply migration manually or ensure token_type column exists."
44
+ );
45
+ }
46
+
47
+ // Try to check if token_type column already exists by querying the schema
48
+ // If it doesn't exist, we'll rely on the fallback in token_service
49
+ return { success: true };
50
+ } catch (error) {
51
+ const error_message =
52
+ error instanceof Error ? error.message : "Unknown error";
53
+
54
+ return {
55
+ success: false,
56
+ error: error_message,
57
+ };
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Applies all migrations in the migrations directory
63
+ * @param adapter - The hazo_connect adapter instance
64
+ * @returns Success status and error message if any
65
+ */
66
+ export async function apply_all_migrations(
67
+ adapter: HazoConnectAdapter,
68
+ ): Promise<{ success: boolean; error?: string }> {
69
+ try {
70
+ const migrations_dir = path.resolve(process.cwd(), "migrations");
71
+
72
+ if (!fs.existsSync(migrations_dir)) {
73
+ return { success: true }; // No migrations directory, nothing to apply
74
+ }
75
+
76
+ // Get all SQL files in migrations directory, sorted by name
77
+ const migration_files = fs
78
+ .readdirSync(migrations_dir)
79
+ .filter((file) => file.endsWith(".sql"))
80
+ .sort();
81
+
82
+ for (const migration_file of migration_files) {
83
+ const migration_path = path.join(migrations_dir, migration_file);
84
+ const result = await apply_migration(adapter, migration_path);
85
+
86
+ if (!result.success) {
87
+ return {
88
+ success: false,
89
+ error: `Failed to apply migration ${migration_file}: ${result.error}`,
90
+ };
91
+ }
92
+ }
93
+
94
+ return { success: true };
95
+ } catch (error) {
96
+ const error_message =
97
+ error instanceof Error ? error.message : "Unknown error";
98
+
99
+ return {
100
+ success: false,
101
+ error: error_message,
102
+ };
103
+ }
104
+ }
105
+
@@ -0,0 +1,94 @@
1
+ // file_description: server-only helper to read multi-tenancy configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import {
4
+ get_config_value,
5
+ get_config_number,
6
+ get_config_boolean,
7
+ } from "./config/config_loader.server.js";
8
+ import { DEFAULT_MULTI_TENANCY } from "./config/default_config.js";
9
+
10
+ // section: types
11
+
12
+ /**
13
+ * Multi-tenancy configuration options
14
+ */
15
+ export type MultiTenancyConfig = {
16
+ /** Whether multi-tenancy is enabled (default: false) */
17
+ enable_multi_tenancy: boolean;
18
+ /** Cache TTL in minutes for org lookups (default: 15) */
19
+ org_cache_ttl_minutes: number;
20
+ /** Maximum entries in org cache (default: 1000) */
21
+ org_cache_max_entries: number;
22
+ /** Default user limit per organization (0 = unlimited) */
23
+ default_user_limit: number;
24
+ };
25
+
26
+ // section: constants
27
+
28
+ const SECTION_NAME = "hazo_auth__multi_tenancy";
29
+
30
+ // section: helpers
31
+
32
+ /**
33
+ * Reads multi-tenancy configuration from hazo_auth_config.ini file
34
+ * Falls back to defaults if config file is not found or section is missing
35
+ * @returns Multi-tenancy configuration options
36
+ */
37
+ export function get_multi_tenancy_config(): MultiTenancyConfig {
38
+ // Core multi-tenancy enablement
39
+ const enable_multi_tenancy = get_config_boolean(
40
+ SECTION_NAME,
41
+ "enable_multi_tenancy",
42
+ DEFAULT_MULTI_TENANCY.enable_multi_tenancy,
43
+ );
44
+
45
+ // Cache settings
46
+ const org_cache_ttl_minutes = get_config_number(
47
+ SECTION_NAME,
48
+ "org_cache_ttl_minutes",
49
+ DEFAULT_MULTI_TENANCY.org_cache_ttl_minutes,
50
+ );
51
+ const org_cache_max_entries = get_config_number(
52
+ SECTION_NAME,
53
+ "org_cache_max_entries",
54
+ DEFAULT_MULTI_TENANCY.org_cache_max_entries,
55
+ );
56
+
57
+ // Default user limit
58
+ const default_user_limit = get_config_number(
59
+ SECTION_NAME,
60
+ "default_user_limit",
61
+ DEFAULT_MULTI_TENANCY.default_user_limit,
62
+ );
63
+
64
+ return {
65
+ enable_multi_tenancy,
66
+ org_cache_ttl_minutes,
67
+ org_cache_max_entries,
68
+ default_user_limit,
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Checks if multi-tenancy is enabled in the configuration
74
+ * Convenience function for quick checks
75
+ */
76
+ export function is_multi_tenancy_enabled(): boolean {
77
+ return get_config_boolean(
78
+ SECTION_NAME,
79
+ "enable_multi_tenancy",
80
+ DEFAULT_MULTI_TENANCY.enable_multi_tenancy,
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Gets the default user limit from config
86
+ * Returns 0 if not configured (unlimited)
87
+ */
88
+ export function get_default_user_limit(): number {
89
+ return get_config_number(
90
+ SECTION_NAME,
91
+ "default_user_limit",
92
+ DEFAULT_MULTI_TENANCY.default_user_limit,
93
+ );
94
+ }
@@ -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.js";
4
+ import { get_user_fields_config } from "./user_fields_config.server.js";
5
+ import { get_password_requirements_config } from "./password_requirements_config.server.js";
6
+ import { get_profile_picture_config } from "./profile_picture_config.server.js";
7
+ import { get_messages_config } from "./messages_config.server.js";
8
+ import { get_ui_sizes_config } from "./ui_sizes_config.server.js";
9
+ import { get_file_types_config } from "./file_types_config.server.js";
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.js";
4
+ import { DEFAULT_OAUTH } from "./config/default_config.js";
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.js";
4
+ import { DEFAULT_PASSWORD_REQUIREMENTS } from "./config/default_config.js";
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
+