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,264 @@
|
|
|
1
|
+
// file_description: service for batch retrieval of basic user profile information for chat applications and similar use cases
|
|
2
|
+
// Includes LRU caching with configurable TTL for performance optimization
|
|
3
|
+
// section: imports
|
|
4
|
+
import type { HazoConnectAdapter } from "hazo_connect";
|
|
5
|
+
import { createCrudService } from "hazo_connect/server";
|
|
6
|
+
import { differenceInDays } from "date-fns";
|
|
7
|
+
import { create_app_logger } from "../app_logger";
|
|
8
|
+
import { sanitize_error_for_user } from "../utils/error_sanitizer";
|
|
9
|
+
import { get_user_profiles_cache } from "./user_profiles_cache";
|
|
10
|
+
import { get_user_profiles_cache_config } from "../user_profiles_config.server";
|
|
11
|
+
|
|
12
|
+
// section: types
|
|
13
|
+
/**
|
|
14
|
+
* Basic user profile information returned by get_profiles
|
|
15
|
+
* Contains resolved profile picture URL, email, name, and account age
|
|
16
|
+
*/
|
|
17
|
+
export type UserProfileInfo = {
|
|
18
|
+
user_id: string;
|
|
19
|
+
profile_picture_url: string | null;
|
|
20
|
+
email: string;
|
|
21
|
+
name: string | null;
|
|
22
|
+
days_since_created: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Result type for get_profiles function
|
|
27
|
+
* Includes found profiles and list of IDs that were not found
|
|
28
|
+
*/
|
|
29
|
+
export type GetProfilesResult = {
|
|
30
|
+
success: boolean;
|
|
31
|
+
profiles: UserProfileInfo[];
|
|
32
|
+
not_found_ids: string[];
|
|
33
|
+
error?: string;
|
|
34
|
+
cache_stats?: {
|
|
35
|
+
hits: number;
|
|
36
|
+
misses: number;
|
|
37
|
+
cache_enabled: boolean;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// section: helpers
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Fetches profiles from database for given user IDs
|
|
45
|
+
* @param adapter - The hazo_connect adapter instance
|
|
46
|
+
* @param user_ids - Array of user IDs to fetch
|
|
47
|
+
* @returns Object with profiles and not found IDs
|
|
48
|
+
*/
|
|
49
|
+
async function fetch_profiles_from_db(
|
|
50
|
+
adapter: HazoConnectAdapter,
|
|
51
|
+
user_ids: string[],
|
|
52
|
+
): Promise<{ profiles: UserProfileInfo[]; not_found_ids: string[] }> {
|
|
53
|
+
const users_service = createCrudService(adapter, "hazo_users");
|
|
54
|
+
|
|
55
|
+
// Query users by IDs using the 'in' filter
|
|
56
|
+
// PostgREST supports 'in' filter syntax: id=in.(id1,id2,id3)
|
|
57
|
+
const users = await users_service.findBy({
|
|
58
|
+
id: `in.(${user_ids.join(",")})`,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Handle case where no users are found
|
|
62
|
+
if (!Array.isArray(users)) {
|
|
63
|
+
return {
|
|
64
|
+
profiles: [],
|
|
65
|
+
not_found_ids: user_ids,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Build set of found user IDs for quick lookup
|
|
70
|
+
const found_user_ids = new Set(users.map((user) => user.id as string));
|
|
71
|
+
|
|
72
|
+
// Determine which user IDs were not found
|
|
73
|
+
const not_found_ids = user_ids.filter((id) => !found_user_ids.has(id));
|
|
74
|
+
|
|
75
|
+
// Transform database records to UserProfileInfo
|
|
76
|
+
const now = new Date();
|
|
77
|
+
const profiles: UserProfileInfo[] = users.map((user) => {
|
|
78
|
+
const created_at = user.created_at as string;
|
|
79
|
+
const created_date = new Date(created_at);
|
|
80
|
+
const days_since_created = differenceInDays(now, created_date);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
user_id: user.id as string,
|
|
84
|
+
profile_picture_url: (user.profile_picture_url as string) || null,
|
|
85
|
+
email: user.email_address as string,
|
|
86
|
+
name: (user.name as string) || null,
|
|
87
|
+
days_since_created,
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return { profiles, not_found_ids };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Retrieves basic profile information for multiple users in a single batch call
|
|
96
|
+
* Useful for chat applications and similar use cases where basic user info is needed
|
|
97
|
+
* Uses LRU cache with configurable TTL for performance (default: 5 minutes)
|
|
98
|
+
* @param adapter - The hazo_connect adapter instance
|
|
99
|
+
* @param user_ids - Array of user IDs to retrieve profiles for
|
|
100
|
+
* @returns GetProfilesResult with found profiles and list of not found IDs
|
|
101
|
+
*/
|
|
102
|
+
export async function hazo_get_user_profiles(
|
|
103
|
+
adapter: HazoConnectAdapter,
|
|
104
|
+
user_ids: string[],
|
|
105
|
+
): Promise<GetProfilesResult> {
|
|
106
|
+
const logger = create_app_logger();
|
|
107
|
+
const config = get_user_profiles_cache_config();
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
// Handle empty input
|
|
111
|
+
if (!user_ids || user_ids.length === 0) {
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
profiles: [],
|
|
115
|
+
not_found_ids: [],
|
|
116
|
+
cache_stats: {
|
|
117
|
+
hits: 0,
|
|
118
|
+
misses: 0,
|
|
119
|
+
cache_enabled: config.cache_enabled,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Remove duplicates from input
|
|
125
|
+
const unique_user_ids = [...new Set(user_ids)];
|
|
126
|
+
|
|
127
|
+
// Initialize variables for cache tracking
|
|
128
|
+
let cache_hits = 0;
|
|
129
|
+
let cache_misses = 0;
|
|
130
|
+
let all_profiles: UserProfileInfo[] = [];
|
|
131
|
+
let all_not_found_ids: string[] = [];
|
|
132
|
+
|
|
133
|
+
if (config.cache_enabled) {
|
|
134
|
+
// Get cache instance with config settings
|
|
135
|
+
const cache = get_user_profiles_cache(
|
|
136
|
+
config.cache_max_entries,
|
|
137
|
+
config.cache_ttl_minutes,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
// Check cache first
|
|
141
|
+
const { cached, missing_ids } = cache.get_many(unique_user_ids);
|
|
142
|
+
cache_hits = cached.length;
|
|
143
|
+
cache_misses = missing_ids.length;
|
|
144
|
+
|
|
145
|
+
// If all profiles were cached, return immediately
|
|
146
|
+
if (missing_ids.length === 0) {
|
|
147
|
+
logger.info("hazo_get_user_profiles_cache_hit_all", {
|
|
148
|
+
filename: "user_profiles_service.ts",
|
|
149
|
+
line_number: 130,
|
|
150
|
+
message: "All profiles served from cache",
|
|
151
|
+
requested_count: unique_user_ids.length,
|
|
152
|
+
cache_hits,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
success: true,
|
|
157
|
+
profiles: cached,
|
|
158
|
+
not_found_ids: [],
|
|
159
|
+
cache_stats: {
|
|
160
|
+
hits: cache_hits,
|
|
161
|
+
misses: 0,
|
|
162
|
+
cache_enabled: true,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Fetch missing profiles from database
|
|
168
|
+
const db_result = await fetch_profiles_from_db(adapter, missing_ids);
|
|
169
|
+
|
|
170
|
+
// Cache the newly fetched profiles
|
|
171
|
+
if (db_result.profiles.length > 0) {
|
|
172
|
+
cache.set_many(db_result.profiles);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Combine cached and freshly fetched profiles
|
|
176
|
+
all_profiles = [...cached, ...db_result.profiles];
|
|
177
|
+
all_not_found_ids = db_result.not_found_ids;
|
|
178
|
+
} else {
|
|
179
|
+
// Cache disabled - fetch all from database
|
|
180
|
+
cache_misses = unique_user_ids.length;
|
|
181
|
+
const db_result = await fetch_profiles_from_db(adapter, unique_user_ids);
|
|
182
|
+
all_profiles = db_result.profiles;
|
|
183
|
+
all_not_found_ids = db_result.not_found_ids;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Log successful retrieval
|
|
187
|
+
logger.info("hazo_get_user_profiles_success", {
|
|
188
|
+
filename: "user_profiles_service.ts",
|
|
189
|
+
line_number: 170,
|
|
190
|
+
message: "Successfully retrieved user profiles",
|
|
191
|
+
requested_count: unique_user_ids.length,
|
|
192
|
+
found_count: all_profiles.length,
|
|
193
|
+
not_found_count: all_not_found_ids.length,
|
|
194
|
+
cache_hits,
|
|
195
|
+
cache_misses,
|
|
196
|
+
cache_enabled: config.cache_enabled,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
success: true,
|
|
201
|
+
profiles: all_profiles,
|
|
202
|
+
not_found_ids: all_not_found_ids,
|
|
203
|
+
cache_stats: {
|
|
204
|
+
hits: cache_hits,
|
|
205
|
+
misses: cache_misses,
|
|
206
|
+
cache_enabled: config.cache_enabled,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
} catch (error) {
|
|
210
|
+
const user_friendly_error = sanitize_error_for_user(error, {
|
|
211
|
+
logToConsole: true,
|
|
212
|
+
logToLogger: true,
|
|
213
|
+
logger,
|
|
214
|
+
context: {
|
|
215
|
+
filename: "user_profiles_service.ts",
|
|
216
|
+
line_number: 195,
|
|
217
|
+
operation: "hazo_get_user_profiles",
|
|
218
|
+
user_ids_count: user_ids?.length || 0,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
success: false,
|
|
224
|
+
profiles: [],
|
|
225
|
+
not_found_ids: [],
|
|
226
|
+
error: user_friendly_error,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Invalidates cache for specific user IDs
|
|
233
|
+
* Call this after user profile updates to ensure fresh data on next fetch
|
|
234
|
+
* @param user_ids - Array of user IDs to invalidate from cache
|
|
235
|
+
*/
|
|
236
|
+
export function invalidate_user_profiles_cache(user_ids: string[]): void {
|
|
237
|
+
const config = get_user_profiles_cache_config();
|
|
238
|
+
if (!config.cache_enabled) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const cache = get_user_profiles_cache(
|
|
243
|
+
config.cache_max_entries,
|
|
244
|
+
config.cache_ttl_minutes,
|
|
245
|
+
);
|
|
246
|
+
cache.invalidate_users(user_ids);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Invalidates the entire user profiles cache
|
|
251
|
+
* Use sparingly - prefer invalidating specific users when possible
|
|
252
|
+
*/
|
|
253
|
+
export function invalidate_all_user_profiles_cache(): void {
|
|
254
|
+
const config = get_user_profiles_cache_config();
|
|
255
|
+
if (!config.cache_enabled) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const cache = get_user_profiles_cache(
|
|
260
|
+
config.cache_max_entries,
|
|
261
|
+
config.cache_ttl_minutes,
|
|
262
|
+
);
|
|
263
|
+
cache.invalidate_all();
|
|
264
|
+
}
|