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,92 @@
1
+ // file_description: Edge-compatible JWT session token validator for Next.js proxy/middleware
2
+ // Uses jose library which works in Edge Runtime
3
+ // section: imports
4
+ import { jwtVerify } from "jose";
5
+ import type { NextRequest } from "next/server";
6
+
7
+ // section: types
8
+ export type ValidateSessionCookieResult = {
9
+ valid: boolean;
10
+ user_id?: string;
11
+ email?: string;
12
+ };
13
+
14
+ // section: helpers
15
+ /**
16
+ * Gets JWT secret from environment variables
17
+ * Works in Edge Runtime (no Node.js APIs)
18
+ * @returns JWT secret as Uint8Array for jose library
19
+ */
20
+ function get_jwt_secret(): Uint8Array | null {
21
+ const jwt_secret = process.env.JWT_SECRET;
22
+
23
+ if (!jwt_secret) {
24
+ // In Edge Runtime, we can't use logger, so we just return null
25
+ // The validation will fail gracefully
26
+ return null;
27
+ }
28
+
29
+ // Convert string secret to Uint8Array for jose
30
+ return new TextEncoder().encode(jwt_secret);
31
+ }
32
+
33
+ // section: main_function
34
+ /**
35
+ * Validates session cookie from NextRequest (Edge-compatible)
36
+ * Extracts hazo_auth_session cookie and validates JWT signature and expiry
37
+ * Works in Edge Runtime (Next.js proxy/middleware)
38
+ * @param request - NextRequest object
39
+ * @returns Validation result with user_id and email if valid
40
+ */
41
+ export async function validate_session_cookie(
42
+ request: NextRequest,
43
+ ): Promise<ValidateSessionCookieResult> {
44
+ try {
45
+ // Extract session cookie
46
+ const session_cookie = request.cookies.get("hazo_auth_session")?.value;
47
+
48
+ if (!session_cookie) {
49
+ return { valid: false };
50
+ }
51
+
52
+ // Get JWT secret
53
+ const secret = get_jwt_secret();
54
+
55
+ if (!secret) {
56
+ // JWT_SECRET not set - cannot validate
57
+ return { valid: false };
58
+ }
59
+
60
+ // Verify JWT signature and expiration
61
+ const { payload } = await jwtVerify(session_cookie, secret, {
62
+ algorithms: ["HS256"],
63
+ });
64
+
65
+ // Extract user_id and email from payload
66
+ const user_id = payload.user_id as string;
67
+ const email = payload.email as string;
68
+
69
+ if (!user_id || !email) {
70
+ return { valid: false };
71
+ }
72
+
73
+ return {
74
+ valid: true,
75
+ user_id,
76
+ email,
77
+ };
78
+ } catch (error) {
79
+ // jose throws JWTExpired, JWTInvalid, etc. - these are expected for invalid tokens
80
+ // In Edge Runtime, we can't log, so we just return invalid
81
+ return { valid: false };
82
+ }
83
+ }
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
@@ -0,0 +1,136 @@
1
+ // file_description: server-only helper to read auth utility configuration from hazo_auth_config.ini
2
+ // section: imports
3
+ import {
4
+ get_config_value,
5
+ get_config_number,
6
+ get_config_boolean,
7
+ get_config_array,
8
+ } from "./config/config_loader.server.js";
9
+
10
+ // section: types
11
+
12
+ /**
13
+ * Auth utility configuration options
14
+ */
15
+ export type AuthUtilityConfig = {
16
+ cache_max_users: number;
17
+ cache_ttl_minutes: number;
18
+ cache_max_age_minutes: number;
19
+ rate_limit_per_user: number;
20
+ rate_limit_per_ip: number;
21
+ log_permission_denials: boolean;
22
+ enable_friendly_error_messages: boolean;
23
+ permission_error_messages: Map<string, string>; // permission -> user-friendly message
24
+ };
25
+
26
+ // section: helpers
27
+
28
+ /**
29
+ * Parses permission error messages from config string
30
+ * Format: "permission1:message1,permission2:message2"
31
+ * @param config_value - Config string value
32
+ * @returns Map of permission to user-friendly message
33
+ */
34
+ function parse_permission_messages(
35
+ config_value: string,
36
+ ): Map<string, string> {
37
+ const messages = new Map<string, string>();
38
+
39
+ if (!config_value || config_value.trim().length === 0) {
40
+ return messages;
41
+ }
42
+
43
+ const pairs = config_value.split(",");
44
+ for (const pair of pairs) {
45
+ const trimmed = pair.trim();
46
+ if (trimmed.length === 0) {
47
+ continue;
48
+ }
49
+
50
+ const colon_index = trimmed.indexOf(":");
51
+ if (colon_index === -1) {
52
+ continue; // Skip invalid format
53
+ }
54
+
55
+ const permission = trimmed.substring(0, colon_index).trim();
56
+ const message = trimmed.substring(colon_index + 1).trim();
57
+
58
+ if (permission.length > 0 && message.length > 0) {
59
+ messages.set(permission, message);
60
+ }
61
+ }
62
+
63
+ return messages;
64
+ }
65
+
66
+ /**
67
+ * Reads auth utility configuration from hazo_auth_config.ini file
68
+ * Falls back to defaults if hazo_auth_config.ini is not found or section is missing
69
+ * @returns Auth utility configuration options
70
+ */
71
+ export function get_auth_utility_config(): AuthUtilityConfig {
72
+ const section_name = "hazo_auth__auth_utility";
73
+
74
+ // Cache settings
75
+ const cache_max_users = get_config_number(
76
+ section_name,
77
+ "cache_max_users",
78
+ 10000,
79
+ );
80
+ const cache_ttl_minutes = get_config_number(
81
+ section_name,
82
+ "cache_ttl_minutes",
83
+ 5, // Default: 5 minutes
84
+ );
85
+ const cache_max_age_minutes = get_config_number(
86
+ section_name,
87
+ "cache_max_age_minutes",
88
+ 10, // Default: 10 minutes (force refresh threshold)
89
+ );
90
+
91
+ // Rate limiting
92
+ const rate_limit_per_user = get_config_number(
93
+ section_name,
94
+ "rate_limit_per_user",
95
+ 100,
96
+ );
97
+ const rate_limit_per_ip = get_config_number(
98
+ section_name,
99
+ "rate_limit_per_ip",
100
+ 200,
101
+ );
102
+
103
+ // Permission check behavior
104
+ const log_permission_denials = get_config_boolean(
105
+ section_name,
106
+ "log_permission_denials",
107
+ true,
108
+ );
109
+ const enable_friendly_error_messages = get_config_boolean(
110
+ section_name,
111
+ "enable_friendly_error_messages",
112
+ true,
113
+ );
114
+
115
+ // Permission message mappings
116
+ const permission_messages_str = get_config_value(
117
+ section_name,
118
+ "permission_error_messages",
119
+ "",
120
+ );
121
+ const permission_error_messages = parse_permission_messages(
122
+ permission_messages_str,
123
+ );
124
+
125
+ return {
126
+ cache_max_users,
127
+ cache_ttl_minutes,
128
+ cache_max_age_minutes,
129
+ rate_limit_per_user,
130
+ rate_limit_per_ip,
131
+ log_permission_denials,
132
+ enable_friendly_error_messages,
133
+ permission_error_messages,
134
+ };
135
+ }
136
+
@@ -0,0 +1,164 @@
1
+ // file_description: shared utility for reading configuration from hazo_auth_config.ini using hazo_config
2
+ // section: imports
3
+ import { HazoConfig } from "hazo_config/dist/lib";
4
+ import path from "path";
5
+ import fs from "fs";
6
+ import { create_app_logger } from "../app_logger.js";
7
+
8
+ // section: constants
9
+ const DEFAULT_CONFIG_FILE = "hazo_auth_config.ini";
10
+
11
+ // section: helpers
12
+ /**
13
+ * Gets the default config file path
14
+ * @param custom_path - Optional custom config file path
15
+ * @returns Resolved config file path
16
+ */
17
+ function get_config_file_path(custom_path?: string): string {
18
+ if (custom_path) {
19
+ return path.isAbsolute(custom_path) ? custom_path : path.resolve(process.cwd(), custom_path);
20
+ }
21
+ return path.resolve(process.cwd(), DEFAULT_CONFIG_FILE);
22
+ }
23
+
24
+ /**
25
+ * Reads a section from the config file
26
+ * @param section_name - Name of the section to read (e.g., "hazo_auth__register_layout")
27
+ * @param file_path - Optional custom config file path (defaults to hazo_auth_config.ini)
28
+ * @returns Section data as Record<string, string> or undefined if not found
29
+ */
30
+ export function read_config_section(
31
+ section_name: string,
32
+ file_path?: string,
33
+ ): Record<string, string> | undefined {
34
+ const config_path = get_config_file_path(file_path);
35
+ const logger = create_app_logger();
36
+
37
+ if (!fs.existsSync(config_path)) {
38
+ return undefined;
39
+ }
40
+
41
+ try {
42
+ const hazo_config = new HazoConfig({
43
+ filePath: config_path,
44
+ });
45
+ return hazo_config.getSection(section_name);
46
+ } catch (error) {
47
+ const error_message = error instanceof Error ? error.message : "Unknown error";
48
+ logger.warn("config_loader_read_section_failed", {
49
+ filename: "config_loader.server.ts",
50
+ line_number: 0,
51
+ section_name,
52
+ config_path,
53
+ error: error_message,
54
+ });
55
+ return undefined;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Gets a single config value from a section
61
+ * @param section_name - Name of the section
62
+ * @param key - Key name within the section
63
+ * @param default_value - Default value if key is not found
64
+ * @param file_path - Optional custom config file path
65
+ * @returns Config value as string or default value
66
+ */
67
+ export function get_config_value(
68
+ section_name: string,
69
+ key: string,
70
+ default_value: string,
71
+ file_path?: string,
72
+ ): string {
73
+ const section = read_config_section(section_name, file_path);
74
+ // Optional chaining on section and section[key]
75
+ // If section is undefined, or key is undefined, fall back to default
76
+ if (!section || section[key] === undefined) {
77
+ return default_value;
78
+ }
79
+ return section[key].trim() || default_value;
80
+ }
81
+
82
+ /**
83
+ * Gets a boolean config value from a section
84
+ * @param section_name - Name of the section
85
+ * @param key - Key name within the section
86
+ * @param default_value - Default boolean value if key is not found
87
+ * @param file_path - Optional custom config file path
88
+ * @returns Config value as boolean
89
+ */
90
+ export function get_config_boolean(
91
+ section_name: string,
92
+ key: string,
93
+ default_value: boolean,
94
+ file_path?: string,
95
+ ): boolean {
96
+ const section = read_config_section(section_name, file_path);
97
+
98
+ if (!section || section[key] === undefined) {
99
+ return default_value;
100
+ }
101
+
102
+ const value = section[key].trim().toLowerCase();
103
+ return value !== "false" && value !== "0" && value !== "";
104
+ }
105
+
106
+ /**
107
+ * Gets a number config value from a section
108
+ * @param section_name - Name of the section
109
+ * @param key - Key name within the section
110
+ * @param default_value - Default number value if key is not found or invalid
111
+ * @param file_path - Optional custom config file path
112
+ * @returns Config value as number
113
+ */
114
+ export function get_config_number(
115
+ section_name: string,
116
+ key: string,
117
+ default_value: number,
118
+ file_path?: string,
119
+ ): number {
120
+ const section = read_config_section(section_name, file_path);
121
+
122
+ if (!section || section[key] === undefined) {
123
+ return default_value;
124
+ }
125
+
126
+ const value = section[key].trim();
127
+
128
+ if (!value) {
129
+ return default_value;
130
+ }
131
+
132
+ const parsed = parseFloat(value);
133
+ return isNaN(parsed) ? default_value : parsed;
134
+ }
135
+
136
+ /**
137
+ * Gets a comma-separated list config value from a section
138
+ * @param section_name - Name of the section
139
+ * @param key - Key name within the section
140
+ * @param default_value - Default array value if key is not found
141
+ * @param file_path - Optional custom config file path
142
+ * @returns Config value as array of strings
143
+ */
144
+ export function get_config_array(
145
+ section_name: string,
146
+ key: string,
147
+ default_value: string[],
148
+ file_path?: string,
149
+ ): string[] {
150
+ const section = read_config_section(section_name, file_path);
151
+
152
+ if (!section || section[key] === undefined) {
153
+ return default_value;
154
+ }
155
+
156
+ const value = section[key].trim();
157
+
158
+ if (!value) {
159
+ return default_value;
160
+ }
161
+
162
+ return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
163
+ }
164
+
@@ -0,0 +1,243 @@
1
+ // file_description: Centralized default configuration for hazo_auth
2
+ // All default values in one place for easy reference and maintenance
3
+ // These defaults are used when hazo_auth_config.ini is missing or incomplete
4
+
5
+ // section: password_requirements
6
+ export const DEFAULT_PASSWORD_REQUIREMENTS = {
7
+ minimum_length: 8,
8
+ require_uppercase: false,
9
+ require_lowercase: false,
10
+ require_number: false,
11
+ require_special: false,
12
+ } as const;
13
+
14
+ // section: user_fields
15
+ export const DEFAULT_USER_FIELDS = {
16
+ show_name_field: true,
17
+ show_email_field: true,
18
+ show_password_field: true,
19
+ } as const;
20
+
21
+ // section: profile_picture
22
+ export const DEFAULT_PROFILE_PICTURE = {
23
+ allow_photo_upload: true,
24
+ max_photo_size: 5242880, // 5MB in bytes
25
+ user_photo_default: true,
26
+ user_photo_default_priority1: "gravatar" as const,
27
+ user_photo_default_priority2: "library" as const,
28
+ library_photo_path: "/profile_pictures/library",
29
+ } as const;
30
+
31
+ // section: ui_sizes
32
+ export const DEFAULT_UI_SIZES = {
33
+ gravatar_size: 200,
34
+ profile_picture_size: 128,
35
+ tooltip_icon_size_default: 16,
36
+ tooltip_icon_size_small: 14,
37
+ library_photo_grid_columns: 4,
38
+ library_photo_preview_size: 80,
39
+ image_compression_max_dimension: 800,
40
+ upload_file_hard_limit_bytes: 10485760, // 10MB
41
+ } as const;
42
+
43
+ // section: file_types
44
+ export const DEFAULT_FILE_TYPES = {
45
+ allowed_image_extensions: [".jpg", ".jpeg", ".png", ".gif", ".webp"],
46
+ allowed_image_mime_types: ["image/jpeg", "image/png", "image/gif", "image/webp"],
47
+ } as const;
48
+
49
+ // section: messages
50
+ export const DEFAULT_MESSAGES = {
51
+ photo_upload_disabled_message: "Photo upload is currently disabled. Contact your administrator.",
52
+ gravatar_setup_message: "To use Gravatar, create a free account at gravatar.com with the same email address you use here.",
53
+ gravatar_no_account_message: "No Gravatar account found for your email. Using library photo instead.",
54
+ library_tooltip_message: "Choose from our library of profile pictures",
55
+ } as const;
56
+
57
+ // section: already_logged_in
58
+ export const DEFAULT_ALREADY_LOGGED_IN = {
59
+ message: "You are already logged in",
60
+ showLogoutButton: true,
61
+ showReturnHomeButton: true,
62
+ returnHomeButtonLabel: "Return Home",
63
+ returnHomePath: "/",
64
+ } as const;
65
+
66
+ // section: login
67
+ export const DEFAULT_LOGIN = {
68
+ redirectRoute: undefined as string | undefined,
69
+ successMessage: "Successfully logged in",
70
+ forgotPasswordPath: "/hazo_auth/forgot_password",
71
+ forgotPasswordLabel: "Forgot password?",
72
+ createAccountPath: "/hazo_auth/register",
73
+ createAccountLabel: "Create account",
74
+ } as const;
75
+
76
+ // section: register
77
+ export const DEFAULT_REGISTER = {
78
+ redirectRoute: undefined as string | undefined,
79
+ successMessage: "Registration successful! Please check your email to verify your account.",
80
+ loginPath: "/hazo_auth/login",
81
+ loginLabel: "Already have an account? Sign in",
82
+ requireEmailVerification: true,
83
+ } as const;
84
+
85
+ // section: forgot_password
86
+ export const DEFAULT_FORGOT_PASSWORD = {
87
+ successMessage: "If an account with that email exists, a password reset link has been sent.",
88
+ loginPath: "/hazo_auth/login",
89
+ loginLabel: "Back to login",
90
+ } as const;
91
+
92
+ // section: reset_password
93
+ export const DEFAULT_RESET_PASSWORD = {
94
+ successMessage: "Password reset successfully. You can now log in with your new password.",
95
+ loginPath: "/hazo_auth/login",
96
+ redirectDelay: 2, // seconds
97
+ } as const;
98
+
99
+ // section: email_verification
100
+ export const DEFAULT_EMAIL_VERIFICATION = {
101
+ successMessage: "Email verified successfully! Redirecting to login...",
102
+ errorMessage: "Email verification failed. The link may have expired.",
103
+ loginPath: "/hazo_auth/login",
104
+ redirectDelay: 5, // seconds
105
+ } as const;
106
+
107
+ // section: my_settings
108
+ export const DEFAULT_MY_SETTINGS = {
109
+ showNameField: true,
110
+ showEmailField: true,
111
+ showPasswordField: true,
112
+ showProfilePicture: true,
113
+ } as const;
114
+
115
+ // section: user_management
116
+ export const DEFAULT_USER_MANAGEMENT = {
117
+ enableUserManagement: true,
118
+ enableRoleManagement: true,
119
+ enablePermissionManagement: true,
120
+ } as const;
121
+
122
+ // section: auth_utility
123
+ export const DEFAULT_AUTH_UTILITY = {
124
+ sessionCookieName: "hazo_session",
125
+ sessionDuration: 86400, // 24 hours in seconds
126
+ requireEmailVerification: true,
127
+ } as const;
128
+
129
+ // section: ui_shell
130
+ export const DEFAULT_UI_SHELL = {
131
+ layout_mode: "standalone" as "standalone" | "test_sidebar",
132
+ image_src: "/globe.svg",
133
+ image_width: 400,
134
+ image_height: 400,
135
+ show_visual_panel: true,
136
+ } as const;
137
+
138
+ // section: profile_pic_menu
139
+ export const DEFAULT_PROFILE_PIC_MENU = {
140
+ show_single_button: false,
141
+ sign_up_label: "Sign Up",
142
+ sign_in_label: "Sign In",
143
+ register_path: "/hazo_auth/register",
144
+ login_path: "/hazo_auth/login",
145
+ settings_path: "/hazo_auth/my_settings",
146
+ logout_path: "/api/hazo_auth/logout",
147
+ } as const;
148
+
149
+ // section: api_paths
150
+ export const DEFAULT_API_PATHS = {
151
+ apiBasePath: "/api/hazo_auth",
152
+ } as const;
153
+
154
+ // section: oauth
155
+ export const DEFAULT_OAUTH = {
156
+ /** Enable Google OAuth login (requires HAZO_AUTH_GOOGLE_CLIENT_ID and HAZO_AUTH_GOOGLE_CLIENT_SECRET env vars) */
157
+ enable_google: true,
158
+ /** Enable traditional email/password login */
159
+ enable_email_password: true,
160
+ /** Auto-link Google login to existing unverified email/password accounts and mark as verified */
161
+ auto_link_unverified_accounts: true,
162
+ /** Text displayed on the Google sign-in button */
163
+ google_button_text: "Continue with Google",
164
+ /** Text displayed on the divider between OAuth and email/password form */
165
+ oauth_divider_text: "or continue with email",
166
+ } as const;
167
+
168
+ // section: multi_tenancy
169
+ export const DEFAULT_MULTI_TENANCY = {
170
+ /** Enable multi-tenancy support (default: false) */
171
+ enable_multi_tenancy: false,
172
+ /** Cache TTL in minutes for org lookups (default: 15) */
173
+ org_cache_ttl_minutes: 15,
174
+ /** Maximum entries in org cache (default: 1000) */
175
+ org_cache_max_entries: 1000,
176
+ /** Default user limit per organization (0 = unlimited) */
177
+ default_user_limit: 0,
178
+ } as const;
179
+
180
+ // section: dev_lock
181
+ export const DEFAULT_DEV_LOCK = {
182
+ /** Enable the development lock screen (also requires HAZO_AUTH_DEV_LOCK_ENABLED env var) */
183
+ enable: false,
184
+ /** Session duration in days */
185
+ session_duration_days: 7,
186
+ /** Background color (default: black) */
187
+ background_color: "#000000",
188
+ /** Logo image path (default: /logo.png in public folder) */
189
+ logo_path: "/logo.png",
190
+ /** Logo width in pixels */
191
+ logo_width: 120,
192
+ /** Logo height in pixels */
193
+ logo_height: 120,
194
+ /** Application name displayed below logo */
195
+ application_name: "",
196
+ /** Limited access text displayed with lock icon */
197
+ limited_access_text: "Limited Access",
198
+ /** Password input placeholder text */
199
+ password_placeholder: "Enter access password",
200
+ /** Submit button text */
201
+ submit_button_text: "Unlock",
202
+ /** Error message for incorrect password */
203
+ error_message: "Incorrect password",
204
+ /** Text color for labels (default: white) */
205
+ text_color: "#ffffff",
206
+ /** Accent color for button (default: blue) */
207
+ accent_color: "#3b82f6",
208
+ } as const;
209
+
210
+ // section: combined_defaults
211
+ /**
212
+ * All default configuration values combined in one object
213
+ * This makes it easy to see all defaults at a glance and export them as needed
214
+ */
215
+ export const HAZO_AUTH_DEFAULTS = {
216
+ passwordRequirements: DEFAULT_PASSWORD_REQUIREMENTS,
217
+ userFields: DEFAULT_USER_FIELDS,
218
+ profilePicture: DEFAULT_PROFILE_PICTURE,
219
+ uiSizes: DEFAULT_UI_SIZES,
220
+ fileTypes: DEFAULT_FILE_TYPES,
221
+ messages: DEFAULT_MESSAGES,
222
+ alreadyLoggedIn: DEFAULT_ALREADY_LOGGED_IN,
223
+ login: DEFAULT_LOGIN,
224
+ register: DEFAULT_REGISTER,
225
+ forgotPassword: DEFAULT_FORGOT_PASSWORD,
226
+ resetPassword: DEFAULT_RESET_PASSWORD,
227
+ emailVerification: DEFAULT_EMAIL_VERIFICATION,
228
+ mySettings: DEFAULT_MY_SETTINGS,
229
+ userManagement: DEFAULT_USER_MANAGEMENT,
230
+ authUtility: DEFAULT_AUTH_UTILITY,
231
+ uiShell: DEFAULT_UI_SHELL,
232
+ profilePicMenu: DEFAULT_PROFILE_PIC_MENU,
233
+ apiPaths: DEFAULT_API_PATHS,
234
+ oauth: DEFAULT_OAUTH,
235
+ devLock: DEFAULT_DEV_LOCK,
236
+ multiTenancy: DEFAULT_MULTI_TENANCY,
237
+ } as const;
238
+
239
+ // section: types
240
+ /**
241
+ * Type representing the complete default configuration structure
242
+ */
243
+ export type HazoAuthDefaults = typeof HAZO_AUTH_DEFAULTS;