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,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.js";
8
+ import { sanitize_error_for_user } from "../utils/error_sanitizer.js";
9
+ import { get_user_profiles_cache } from "./user_profiles_cache.js";
10
+ import { get_user_profiles_cache_config } from "../user_profiles_config.server.js";
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
+ }