hazo_auth 4.1.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.
- package/README.md +230 -0
- package/SETUP_CHECKLIST.md +202 -0
- package/bin/hazo_auth.mjs +35 -0
- package/cli-src/assets/images/forgot_password_default.jpg +0 -0
- package/cli-src/assets/images/login_default.jpg +0 -0
- package/cli-src/assets/images/register_default.jpg +0 -0
- package/cli-src/assets/images/reset_password_default.jpg +0 -0
- package/cli-src/assets/images/verify_email_default.jpg +0 -0
- package/cli-src/cli/generate.ts +276 -0
- package/cli-src/cli/index.ts +207 -0
- package/cli-src/cli/init.ts +254 -0
- package/cli-src/cli/init_users.ts +376 -0
- package/cli-src/cli/validate.ts +581 -0
- package/cli-src/lib/already_logged_in_config.server.ts +46 -0
- package/cli-src/lib/app_logger.ts +24 -0
- package/cli-src/lib/auth/auth_cache.ts +220 -0
- package/cli-src/lib/auth/auth_rate_limiter.ts +121 -0
- package/cli-src/lib/auth/auth_types.ts +110 -0
- package/cli-src/lib/auth/auth_utils.server.ts +196 -0
- package/cli-src/lib/auth/hazo_get_auth.server.ts +512 -0
- package/cli-src/lib/auth/index.ts +23 -0
- package/cli-src/lib/auth/nextauth_config.ts +227 -0
- package/cli-src/lib/auth/scope_cache.ts +233 -0
- package/cli-src/lib/auth/server_auth.ts +88 -0
- package/cli-src/lib/auth/session_token_validator.edge.ts +91 -0
- package/cli-src/lib/auth_utility_config.server.ts +136 -0
- package/cli-src/lib/config/config_loader.server.ts +164 -0
- package/cli-src/lib/config/default_config.ts +199 -0
- package/cli-src/lib/email_verification_config.server.ts +63 -0
- package/cli-src/lib/file_types_config.server.ts +25 -0
- package/cli-src/lib/forgot_password_config.server.ts +63 -0
- package/cli-src/lib/hazo_connect_instance.server.ts +101 -0
- package/cli-src/lib/hazo_connect_setup.server.ts +194 -0
- package/cli-src/lib/hazo_connect_setup.ts +54 -0
- package/cli-src/lib/index.ts +46 -0
- package/cli-src/lib/login_config.server.ts +106 -0
- package/cli-src/lib/messages_config.server.ts +45 -0
- package/cli-src/lib/migrations/apply_migration.ts +105 -0
- package/cli-src/lib/my_settings_config.server.ts +135 -0
- package/cli-src/lib/oauth_config.server.ts +87 -0
- package/cli-src/lib/password_requirements_config.server.ts +40 -0
- package/cli-src/lib/profile_pic_menu_config.server.ts +138 -0
- package/cli-src/lib/profile_picture_config.server.ts +56 -0
- package/cli-src/lib/register_config.server.ts +101 -0
- package/cli-src/lib/reset_password_config.server.ts +103 -0
- package/cli-src/lib/scope_hierarchy_config.server.ts +151 -0
- package/cli-src/lib/services/email_service.ts +587 -0
- package/cli-src/lib/services/email_verification_service.ts +270 -0
- package/cli-src/lib/services/index.ts +16 -0
- package/cli-src/lib/services/login_service.ts +150 -0
- package/cli-src/lib/services/oauth_service.ts +494 -0
- package/cli-src/lib/services/password_change_service.ts +154 -0
- package/cli-src/lib/services/password_reset_service.ts +418 -0
- package/cli-src/lib/services/profile_picture_remove_service.ts +120 -0
- package/cli-src/lib/services/profile_picture_service.ts +451 -0
- package/cli-src/lib/services/profile_picture_source_mapper.ts +62 -0
- package/cli-src/lib/services/registration_service.ts +185 -0
- package/cli-src/lib/services/scope_labels_service.ts +348 -0
- package/cli-src/lib/services/scope_service.ts +778 -0
- package/cli-src/lib/services/session_token_service.ts +177 -0
- package/cli-src/lib/services/token_service.ts +240 -0
- package/cli-src/lib/services/user_profiles_cache.ts +189 -0
- package/cli-src/lib/services/user_profiles_service.ts +264 -0
- package/cli-src/lib/services/user_scope_service.ts +554 -0
- package/cli-src/lib/services/user_update_service.ts +141 -0
- package/cli-src/lib/ui_shell_config.server.ts +73 -0
- package/cli-src/lib/ui_sizes_config.server.ts +37 -0
- package/cli-src/lib/user_fields_config.server.ts +31 -0
- package/cli-src/lib/user_management_config.server.ts +39 -0
- package/cli-src/lib/user_profiles_config.server.ts +55 -0
- package/cli-src/lib/utils/api_route_helpers.ts +60 -0
- package/cli-src/lib/utils/error_sanitizer.ts +75 -0
- package/cli-src/lib/utils/password_validator.ts +65 -0
- package/cli-src/lib/utils.ts +11 -0
- package/cli-src/server/logging/logger_service.ts +56 -0
- package/dist/app/api/hazo_auth/forgot_password/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/forgot_password/route.js +15 -0
- package/dist/app/api/hazo_auth/logout/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/logout/route.js +31 -0
- package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/me/route.js +10 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/init_users.d.ts +17 -0
- package/dist/cli/init_users.d.ts.map +1 -0
- package/dist/cli/init_users.js +307 -0
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts +2 -0
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts.map +1 -1
- package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.js +8 -0
- package/dist/components/layouts/forgot_password/index.d.ts +7 -1
- package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
- package/dist/components/layouts/forgot_password/index.js +7 -2
- package/dist/components/layouts/login/index.d.ts +13 -1
- package/dist/components/layouts/login/index.d.ts.map +1 -1
- package/dist/components/layouts/login/index.js +11 -2
- package/dist/components/layouts/my_settings/components/connected_accounts_section.d.ts +17 -0
- package/dist/components/layouts/my_settings/components/connected_accounts_section.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/connected_accounts_section.js +17 -0
- package/dist/components/layouts/my_settings/components/set_password_section.d.ts +26 -0
- package/dist/components/layouts/my_settings/components/set_password_section.d.ts.map +1 -0
- package/dist/components/layouts/my_settings/components/set_password_section.js +127 -0
- package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts +3 -0
- package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts.map +1 -1
- package/dist/components/layouts/my_settings/hooks/use_my_settings.js +9 -0
- package/dist/components/layouts/my_settings/index.d.ts.map +1 -1
- package/dist/components/layouts/my_settings/index.js +4 -2
- package/dist/components/layouts/shared/components/google_icon.d.ts +12 -0
- package/dist/components/layouts/shared/components/google_icon.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/google_icon.js +9 -0
- package/dist/components/layouts/shared/components/google_sign_in_button.d.ts +21 -0
- package/dist/components/layouts/shared/components/google_sign_in_button.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/google_sign_in_button.js +50 -0
- package/dist/components/layouts/shared/components/oauth_divider.d.ts +13 -0
- package/dist/components/layouts/shared/components/oauth_divider.d.ts.map +1 -0
- package/dist/components/layouts/shared/components/oauth_divider.js +13 -0
- package/dist/components/layouts/shared/config/layout_customization.d.ts +2 -7
- package/dist/components/layouts/shared/config/layout_customization.d.ts.map +1 -1
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +3 -0
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -1
- package/dist/components/layouts/shared/hooks/use_auth_status.js +4 -0
- package/dist/components/layouts/shared/index.d.ts +5 -0
- package/dist/components/layouts/shared/index.d.ts.map +1 -1
- package/dist/components/layouts/shared/index.js +3 -0
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/lib/auth/nextauth_config.d.ts +34 -0
- package/dist/lib/auth/nextauth_config.d.ts.map +1 -0
- package/dist/lib/auth/nextauth_config.js +171 -0
- package/dist/lib/config/default_config.d.ts +24 -0
- package/dist/lib/config/default_config.d.ts.map +1 -1
- package/dist/lib/config/default_config.js +14 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/login_config.server.d.ts +3 -0
- package/dist/lib/login_config.server.d.ts.map +1 -1
- package/dist/lib/login_config.server.js +4 -0
- package/dist/lib/oauth_config.server.d.ts +29 -0
- package/dist/lib/oauth_config.server.d.ts.map +1 -0
- package/dist/lib/oauth_config.server.js +40 -0
- package/dist/lib/services/login_service.d.ts.map +1 -1
- package/dist/lib/services/login_service.js +16 -1
- package/dist/lib/services/oauth_service.d.ts +88 -0
- package/dist/lib/services/oauth_service.d.ts.map +1 -0
- package/dist/lib/services/oauth_service.js +376 -0
- package/dist/lib/services/password_reset_service.d.ts +2 -0
- package/dist/lib/services/password_reset_service.d.ts.map +1 -1
- package/dist/lib/services/password_reset_service.js +10 -0
- package/dist/lib/services/registration_service.d.ts.map +1 -1
- package/dist/lib/services/registration_service.js +1 -0
- package/dist/lib/utils/password_validator.d.ts +19 -0
- package/dist/lib/utils/password_validator.d.ts.map +1 -0
- package/dist/lib/utils/password_validator.js +36 -0
- package/dist/server_pages/login.d.ts.map +1 -1
- package/dist/server_pages/login.js +6 -1
- package/dist/server_pages/login_client_wrapper.d.ts +5 -2
- package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/login_client_wrapper.js +2 -2
- package/package.json +6 -2
|
@@ -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";
|
|
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";
|
|
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,199 @@
|
|
|
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: combined_defaults
|
|
169
|
+
/**
|
|
170
|
+
* All default configuration values combined in one object
|
|
171
|
+
* This makes it easy to see all defaults at a glance and export them as needed
|
|
172
|
+
*/
|
|
173
|
+
export const HAZO_AUTH_DEFAULTS = {
|
|
174
|
+
passwordRequirements: DEFAULT_PASSWORD_REQUIREMENTS,
|
|
175
|
+
userFields: DEFAULT_USER_FIELDS,
|
|
176
|
+
profilePicture: DEFAULT_PROFILE_PICTURE,
|
|
177
|
+
uiSizes: DEFAULT_UI_SIZES,
|
|
178
|
+
fileTypes: DEFAULT_FILE_TYPES,
|
|
179
|
+
messages: DEFAULT_MESSAGES,
|
|
180
|
+
alreadyLoggedIn: DEFAULT_ALREADY_LOGGED_IN,
|
|
181
|
+
login: DEFAULT_LOGIN,
|
|
182
|
+
register: DEFAULT_REGISTER,
|
|
183
|
+
forgotPassword: DEFAULT_FORGOT_PASSWORD,
|
|
184
|
+
resetPassword: DEFAULT_RESET_PASSWORD,
|
|
185
|
+
emailVerification: DEFAULT_EMAIL_VERIFICATION,
|
|
186
|
+
mySettings: DEFAULT_MY_SETTINGS,
|
|
187
|
+
userManagement: DEFAULT_USER_MANAGEMENT,
|
|
188
|
+
authUtility: DEFAULT_AUTH_UTILITY,
|
|
189
|
+
uiShell: DEFAULT_UI_SHELL,
|
|
190
|
+
profilePicMenu: DEFAULT_PROFILE_PIC_MENU,
|
|
191
|
+
apiPaths: DEFAULT_API_PATHS,
|
|
192
|
+
oauth: DEFAULT_OAUTH,
|
|
193
|
+
} as const;
|
|
194
|
+
|
|
195
|
+
// section: types
|
|
196
|
+
/**
|
|
197
|
+
* Type representing the complete default configuration structure
|
|
198
|
+
*/
|
|
199
|
+
export type HazoAuthDefaults = typeof HAZO_AUTH_DEFAULTS;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// file_description: server-only helper to read email verification layout configuration from hazo_auth_config.ini
|
|
2
|
+
// section: imports
|
|
3
|
+
import { get_already_logged_in_config } from "./already_logged_in_config.server";
|
|
4
|
+
import { get_config_value } from "./config/config_loader.server";
|
|
5
|
+
import verifyEmailDefaultImage from "../assets/images/verify_email_default.jpg";
|
|
6
|
+
|
|
7
|
+
// section: types
|
|
8
|
+
import type { StaticImageData } from "next/image";
|
|
9
|
+
|
|
10
|
+
export type EmailVerificationConfig = {
|
|
11
|
+
alreadyLoggedInMessage: string;
|
|
12
|
+
showLogoutButton: boolean;
|
|
13
|
+
showReturnHomeButton: boolean;
|
|
14
|
+
returnHomeButtonLabel: string;
|
|
15
|
+
returnHomePath: string;
|
|
16
|
+
imageSrc: string | StaticImageData;
|
|
17
|
+
imageAlt: string;
|
|
18
|
+
imageBackgroundColor: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// section: helpers
|
|
22
|
+
/**
|
|
23
|
+
* Reads email verification layout configuration from hazo_auth_config.ini file
|
|
24
|
+
* Falls back to defaults if hazo_auth_config.ini is not found or section is missing
|
|
25
|
+
* @returns Email verification configuration options
|
|
26
|
+
*/
|
|
27
|
+
export function get_email_verification_config(): EmailVerificationConfig {
|
|
28
|
+
const section = "hazo_auth__email_verification_layout";
|
|
29
|
+
|
|
30
|
+
// Get shared already logged in config
|
|
31
|
+
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
32
|
+
|
|
33
|
+
// Read image configuration
|
|
34
|
+
// If not set in config, falls back to default image from assets
|
|
35
|
+
const imageSrc = get_config_value(
|
|
36
|
+
section,
|
|
37
|
+
"image_src",
|
|
38
|
+
"" // Empty string means not set in config
|
|
39
|
+
) || verifyEmailDefaultImage;
|
|
40
|
+
|
|
41
|
+
const imageAlt = get_config_value(
|
|
42
|
+
section,
|
|
43
|
+
"image_alt",
|
|
44
|
+
"Email verification illustration"
|
|
45
|
+
);
|
|
46
|
+
const imageBackgroundColor = get_config_value(
|
|
47
|
+
section,
|
|
48
|
+
"image_background_color",
|
|
49
|
+
"#f1f5f9"
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
54
|
+
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
55
|
+
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
56
|
+
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
57
|
+
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
58
|
+
imageSrc,
|
|
59
|
+
imageAlt,
|
|
60
|
+
imageBackgroundColor,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// file_description: server-only helper to read file type configuration from hazo_auth_config.ini
|
|
2
|
+
// section: imports
|
|
3
|
+
import { get_config_array } from "./config/config_loader.server";
|
|
4
|
+
|
|
5
|
+
// section: types
|
|
6
|
+
export type FileTypesConfig = {
|
|
7
|
+
allowed_image_extensions: string[];
|
|
8
|
+
allowed_image_mime_types: string[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// section: helpers
|
|
12
|
+
/**
|
|
13
|
+
* Reads file type configuration from hazo_auth_config.ini file
|
|
14
|
+
* Falls back to defaults if hazo_auth_config.ini is not found or section is missing
|
|
15
|
+
* @returns File types configuration options
|
|
16
|
+
*/
|
|
17
|
+
export function get_file_types_config(): FileTypesConfig {
|
|
18
|
+
const section = "hazo_auth__file_types";
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
allowed_image_extensions: get_config_array(section, "allowed_image_extensions", ["jpg", "jpeg", "png"]),
|
|
22
|
+
allowed_image_mime_types: get_config_array(section, "allowed_image_mime_types", ["image/jpeg", "image/jpg", "image/png"]),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// file_description: server-only helper to read forgot password layout configuration from hazo_auth_config.ini
|
|
2
|
+
// section: imports
|
|
3
|
+
import { get_already_logged_in_config } from "./already_logged_in_config.server";
|
|
4
|
+
import { get_config_value } from "./config/config_loader.server";
|
|
5
|
+
import forgotPasswordDefaultImage from "../assets/images/forgot_password_default.jpg";
|
|
6
|
+
|
|
7
|
+
// section: types
|
|
8
|
+
import type { StaticImageData } from "next/image";
|
|
9
|
+
|
|
10
|
+
export type ForgotPasswordConfig = {
|
|
11
|
+
alreadyLoggedInMessage: string;
|
|
12
|
+
showLogoutButton: boolean;
|
|
13
|
+
showReturnHomeButton: boolean;
|
|
14
|
+
returnHomeButtonLabel: string;
|
|
15
|
+
returnHomePath: string;
|
|
16
|
+
imageSrc: string | StaticImageData;
|
|
17
|
+
imageAlt: string;
|
|
18
|
+
imageBackgroundColor: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// section: helpers
|
|
22
|
+
/**
|
|
23
|
+
* Reads forgot password layout configuration from hazo_auth_config.ini file
|
|
24
|
+
* Falls back to defaults if hazo_auth_config.ini is not found or section is missing
|
|
25
|
+
* @returns Forgot password configuration options
|
|
26
|
+
*/
|
|
27
|
+
export function get_forgot_password_config(): ForgotPasswordConfig {
|
|
28
|
+
const section = "hazo_auth__forgot_password_layout";
|
|
29
|
+
|
|
30
|
+
// Get shared already logged in config
|
|
31
|
+
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
32
|
+
|
|
33
|
+
// Read image configuration
|
|
34
|
+
// If not set in config, falls back to default image from assets
|
|
35
|
+
const imageSrc = get_config_value(
|
|
36
|
+
section,
|
|
37
|
+
"image_src",
|
|
38
|
+
"" // Empty string means not set in config
|
|
39
|
+
) || forgotPasswordDefaultImage;
|
|
40
|
+
|
|
41
|
+
const imageAlt = get_config_value(
|
|
42
|
+
section,
|
|
43
|
+
"image_alt",
|
|
44
|
+
"Password recovery illustration"
|
|
45
|
+
);
|
|
46
|
+
const imageBackgroundColor = get_config_value(
|
|
47
|
+
section,
|
|
48
|
+
"image_background_color",
|
|
49
|
+
"#f1f5f9"
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
54
|
+
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
55
|
+
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
56
|
+
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
57
|
+
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
58
|
+
imageSrc,
|
|
59
|
+
imageAlt,
|
|
60
|
+
imageBackgroundColor,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|