hazo_auth 7.0.1 → 7.0.2
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 +73 -330
- package/SETUP_CHECKLIST.md +28 -248
- package/cli-src/cli/generate.ts +1 -10
- package/cli-src/cli/validate.ts +0 -4
- package/cli-src/lib/auth/auth_types.ts +12 -21
- package/cli-src/lib/auth/hazo_get_tenant_auth.server.ts +24 -25
- package/cli-src/lib/auth/index.ts +2 -2
- package/cli-src/lib/auth/nextauth_config.ts +27 -67
- package/cli-src/lib/auth/with_auth.server.ts +15 -15
- package/cli-src/lib/config/default_config.ts +8 -0
- package/cli-src/lib/cookies_config.server.ts +1 -1
- package/cli-src/lib/email_verification_config.server.ts +34 -0
- package/cli-src/lib/forgot_password_config.server.ts +34 -0
- package/cli-src/lib/login_config.server.ts +29 -14
- package/cli-src/lib/my_settings_config.server.ts +3 -0
- package/cli-src/lib/oauth_config.server.ts +31 -57
- package/cli-src/lib/register_config.server.ts +35 -11
- package/cli-src/lib/reset_password_config.server.ts +31 -0
- package/cli-src/lib/services/email_template_manifest.ts +0 -17
- package/cli-src/lib/services/index.ts +2 -8
- package/cli-src/lib/services/oauth_service.ts +74 -128
- package/cli-src/lib/services/otp_service.ts +7 -2
- package/cli-src/lib/services/session_token_service.ts +0 -2
- package/config/hazo_auth_config.example.ini +41 -76
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +1 -10
- package/dist/cli/validate.d.ts.map +1 -1
- package/dist/cli/validate.js +0 -4
- package/dist/client.d.ts +0 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +0 -1
- package/dist/components/layouts/create_firm/index.d.ts +8 -4
- package/dist/components/layouts/create_firm/index.d.ts.map +1 -1
- package/dist/components/layouts/create_firm/index.js +3 -3
- package/dist/components/layouts/email_verification/index.d.ts +5 -4
- package/dist/components/layouts/email_verification/index.d.ts.map +1 -1
- package/dist/components/layouts/email_verification/index.js +4 -4
- package/dist/components/layouts/forgot_password/index.d.ts +5 -4
- package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
- package/dist/components/layouts/forgot_password/index.js +2 -2
- package/dist/components/layouts/login/index.d.ts +13 -19
- package/dist/components/layouts/login/index.d.ts.map +1 -1
- package/dist/components/layouts/login/index.js +8 -11
- package/dist/components/layouts/otp/index.d.ts +5 -1
- package/dist/components/layouts/otp/index.d.ts.map +1 -1
- package/dist/components/layouts/otp/index.js +2 -2
- package/dist/components/layouts/register/index.d.ts +11 -11
- package/dist/components/layouts/register/index.d.ts.map +1 -1
- package/dist/components/layouts/register/index.js +6 -7
- package/dist/components/layouts/reset_password/index.d.ts +5 -4
- package/dist/components/layouts/reset_password/index.d.ts.map +1 -1
- package/dist/components/layouts/reset_password/index.js +5 -5
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts +5 -3
- package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/already_logged_in_guard.js +2 -2
- package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts +2 -6
- package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/facebook_sign_in_button.js +11 -13
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +3 -8
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts +6 -3
- package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/two_column_auth_layout.js +5 -8
- package/dist/components/layouts/shared/index.d.ts +2 -0
- package/dist/components/layouts/shared/index.d.ts.map +1 -1
- package/dist/components/layouts/shared/index.js +1 -0
- package/dist/components/layouts/user_management/index.d.ts.map +1 -1
- package/dist/components/layouts/user_management/index.js +39 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.d.ts +12 -13
- package/dist/lib/auth/auth_types.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.js +0 -8
- package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts +7 -8
- package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_tenant_auth.server.js +22 -23
- package/dist/lib/auth/index.d.ts +2 -2
- package/dist/lib/auth/index.d.ts.map +1 -1
- package/dist/lib/auth/nextauth_config.d.ts +0 -10
- package/dist/lib/auth/nextauth_config.d.ts.map +1 -1
- package/dist/lib/auth/nextauth_config.js +23 -52
- package/dist/lib/auth/with_auth.server.d.ts +13 -13
- package/dist/lib/auth/with_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/with_auth.server.js +2 -2
- package/dist/lib/config/default_config.d.ts +16 -0
- package/dist/lib/config/default_config.d.ts.map +1 -1
- package/dist/lib/config/default_config.js +8 -0
- package/dist/lib/cookies_config.server.d.ts +1 -1
- package/dist/lib/cookies_config.server.js +1 -1
- package/dist/lib/email_verification_config.server.d.ts +3 -0
- package/dist/lib/email_verification_config.server.d.ts.map +1 -1
- package/dist/lib/email_verification_config.server.js +15 -0
- package/dist/lib/forgot_password_config.server.d.ts +3 -0
- package/dist/lib/forgot_password_config.server.d.ts.map +1 -1
- package/dist/lib/forgot_password_config.server.js +15 -0
- package/dist/lib/login_config.server.d.ts +3 -6
- package/dist/lib/login_config.server.d.ts.map +1 -1
- package/dist/lib/login_config.server.js +11 -7
- package/dist/lib/my_settings_config.server.d.ts +1 -0
- package/dist/lib/my_settings_config.server.d.ts.map +1 -1
- package/dist/lib/my_settings_config.server.js +2 -0
- package/dist/lib/oauth_config.server.d.ts +8 -17
- package/dist/lib/oauth_config.server.d.ts.map +1 -1
- package/dist/lib/oauth_config.server.js +10 -25
- package/dist/lib/register_config.server.d.ts +5 -2
- package/dist/lib/register_config.server.d.ts.map +1 -1
- package/dist/lib/register_config.server.js +15 -4
- package/dist/lib/reset_password_config.server.d.ts +3 -0
- package/dist/lib/reset_password_config.server.d.ts.map +1 -1
- package/dist/lib/reset_password_config.server.js +13 -0
- package/dist/lib/services/email_template_manifest.d.ts.map +1 -1
- package/dist/lib/services/email_template_manifest.js +0 -17
- package/dist/lib/services/index.d.ts +0 -2
- package/dist/lib/services/index.d.ts.map +1 -1
- package/dist/lib/services/index.js +0 -1
- package/dist/lib/services/oauth_service.d.ts +11 -22
- package/dist/lib/services/oauth_service.d.ts.map +1 -1
- package/dist/lib/services/oauth_service.js +63 -96
- package/dist/lib/services/otp_service.d.ts +1 -1
- package/dist/lib/services/otp_service.d.ts.map +1 -1
- package/dist/lib/services/otp_service.js +6 -1
- package/dist/lib/services/session_token_service.d.ts +0 -2
- package/dist/lib/services/session_token_service.d.ts.map +1 -1
- package/dist/lib/services/session_token_service.js +0 -2
- package/dist/page_components/create_firm.d.ts +1 -13
- package/dist/page_components/create_firm.d.ts.map +1 -1
- package/dist/page_components/create_firm.js +6 -10
- package/dist/page_components/forgot_password.d.ts +4 -1
- package/dist/page_components/forgot_password.d.ts.map +1 -1
- package/dist/page_components/forgot_password.js +6 -2
- package/dist/page_components/login.d.ts +4 -1
- package/dist/page_components/login.d.ts.map +1 -1
- package/dist/page_components/login.js +6 -2
- package/dist/page_components/register.d.ts +4 -1
- package/dist/page_components/register.d.ts.map +1 -1
- package/dist/page_components/register.js +6 -2
- package/dist/page_components/reset_password.d.ts +4 -1
- package/dist/page_components/reset_password.d.ts.map +1 -1
- package/dist/page_components/reset_password.js +6 -2
- package/dist/page_components/verify_email.d.ts +4 -1
- package/dist/page_components/verify_email.d.ts.map +1 -1
- package/dist/page_components/verify_email.js +6 -2
- package/dist/server/routes/assets.d.ts +8 -0
- package/dist/server/routes/assets.d.ts.map +1 -0
- package/dist/server/routes/assets.js +38 -0
- package/dist/server/routes/consent_me.d.ts +4 -0
- package/dist/server/routes/consent_me.d.ts.map +1 -0
- package/dist/server/routes/consent_me.js +15 -0
- package/dist/server/routes/index.d.ts +6 -4
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +9 -5
- package/dist/server/routes/me.d.ts.map +1 -1
- package/dist/server/routes/me.js +1 -43
- package/dist/server/routes/oauth_facebook_callback.d.ts +1 -1
- package/dist/server/routes/oauth_facebook_callback.d.ts.map +1 -1
- package/dist/server/routes/oauth_facebook_callback.js +8 -1
- package/dist/server/routes/oauth_google_callback.js +1 -1
- package/dist/server/routes/otp/verify.js +2 -2
- package/dist/server/routes/strings_defaults.d.ts +4 -0
- package/dist/server/routes/strings_defaults.d.ts.map +1 -0
- package/dist/server/routes/strings_defaults.js +7 -0
- package/dist/server/routes/user_management_users.d.ts +11 -0
- package/dist/server/routes/user_management_users.d.ts.map +1 -1
- package/dist/server/routes/user_management_users.js +50 -0
- package/dist/server-lib.d.ts +0 -3
- package/dist/server-lib.d.ts.map +1 -1
- package/dist/server-lib.js +0 -2
- package/dist/server_pages/forgot_password.d.ts +18 -14
- package/dist/server_pages/forgot_password.d.ts.map +1 -1
- package/dist/server_pages/forgot_password.js +14 -12
- package/dist/server_pages/forgot_password_client_wrapper.d.ts +8 -7
- package/dist/server_pages/forgot_password_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/forgot_password_client_wrapper.js +2 -2
- package/dist/server_pages/index.d.ts +2 -0
- package/dist/server_pages/index.d.ts.map +1 -1
- package/dist/server_pages/index.js +1 -0
- package/dist/server_pages/login.d.ts +22 -23
- package/dist/server_pages/login.d.ts.map +1 -1
- package/dist/server_pages/login.js +27 -14
- package/dist/server_pages/login_client_wrapper.d.ts +9 -10
- package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/login_client_wrapper.js +2 -2
- package/dist/server_pages/my_settings.d.ts +1 -3
- package/dist/server_pages/my_settings.d.ts.map +1 -1
- package/dist/server_pages/my_settings.js +2 -9
- package/dist/server_pages/register.d.ts +17 -20
- package/dist/server_pages/register.d.ts.map +1 -1
- package/dist/server_pages/register.js +20 -15
- package/dist/server_pages/register_client_wrapper.d.ts +8 -10
- package/dist/server_pages/register_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/register_client_wrapper.js +2 -2
- package/dist/server_pages/reset_password.d.ts +16 -11
- package/dist/server_pages/reset_password.d.ts.map +1 -1
- package/dist/server_pages/reset_password.js +14 -10
- package/dist/server_pages/reset_password_client_wrapper.d.ts +8 -7
- package/dist/server_pages/reset_password_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/reset_password_client_wrapper.js +2 -2
- package/dist/server_pages/verify_email.d.ts +18 -12
- package/dist/server_pages/verify_email.d.ts.map +1 -1
- package/dist/server_pages/verify_email.js +13 -11
- package/dist/server_pages/verify_email_client_wrapper.d.ts +8 -7
- package/dist/server_pages/verify_email_client_wrapper.d.ts.map +1 -1
- package/dist/server_pages/verify_email_client_wrapper.js +2 -2
- package/dist/themes/index.d.ts +0 -1
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +1 -1
- package/package.json +26 -40
- package/dist/themes/preset_indigo_sunset.d.ts +0 -3
- package/dist/themes/preset_indigo_sunset.d.ts.map +0 -1
- package/dist/themes/preset_indigo_sunset.js +0 -20
|
@@ -168,33 +168,23 @@ export async function handle_google_oauth_login(adapter, data) {
|
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
|
-
* Handles Facebook OAuth login
|
|
172
|
-
*
|
|
173
|
-
* 2. Check if user exists with email -> link Facebook account (respects auto_link_unverified)
|
|
174
|
-
* 3. Create new user with Facebook data (email_verified always false — never trust Facebook)
|
|
175
|
-
*
|
|
176
|
-
* @param adapter - The hazo_connect adapter instance
|
|
177
|
-
* @param data - Facebook OAuth user data
|
|
178
|
-
* @param opts - Options (auto_link_unverified: whether to link unverified accounts)
|
|
179
|
-
* @returns OAuth login result with user_id and status flags
|
|
171
|
+
* Handles Facebook OAuth login: find-by-facebook_id → find-by-email+link → create new.
|
|
172
|
+
* Mirrors handle_google_oauth_login exactly. Uses auto_link_unverified_accounts gate.
|
|
180
173
|
*/
|
|
181
|
-
export async function handle_facebook_oauth_login(adapter, data
|
|
174
|
+
export async function handle_facebook_oauth_login(adapter, data) {
|
|
182
175
|
const logger = create_app_logger();
|
|
183
176
|
try {
|
|
184
|
-
const { facebook_id, email, name, profile_picture_url } = data;
|
|
177
|
+
const { facebook_id, email, name, profile_picture_url, email_verified } = data;
|
|
178
|
+
const oauth_config = get_oauth_config();
|
|
185
179
|
const users_service = createCrudService(adapter, "hazo_users");
|
|
186
180
|
const now = new Date().toISOString();
|
|
187
|
-
// Step 1:
|
|
188
|
-
const
|
|
189
|
-
if (Array.isArray(
|
|
190
|
-
const user =
|
|
191
|
-
await users_service.updateById(user.id, {
|
|
192
|
-
|
|
193
|
-
changed_at: now,
|
|
194
|
-
});
|
|
195
|
-
logger.info("oauth_service_facebook_login_existing_facebook_user", {
|
|
181
|
+
// Step 1: existing user with this facebook_id
|
|
182
|
+
const users_by_fb_id = await users_service.findBy({ facebook_id });
|
|
183
|
+
if (Array.isArray(users_by_fb_id) && users_by_fb_id.length > 0) {
|
|
184
|
+
const user = users_by_fb_id[0];
|
|
185
|
+
await users_service.updateById(user.id, { last_logon: now, changed_at: now });
|
|
186
|
+
logger.info("oauth_service_facebook_login_existing_fb_user", {
|
|
196
187
|
filename: "oauth_service.ts",
|
|
197
|
-
line_number: get_line_number(),
|
|
198
188
|
user_id: user.id,
|
|
199
189
|
email: user.email_address,
|
|
200
190
|
});
|
|
@@ -207,91 +197,76 @@ export async function handle_facebook_oauth_login(adapter, data, opts) {
|
|
|
207
197
|
name: user.name,
|
|
208
198
|
};
|
|
209
199
|
}
|
|
210
|
-
// Step 2:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
if (!user_email_verified) {
|
|
217
|
-
if (!(opts === null || opts === void 0 ? void 0 : opts.auto_link_unverified)) {
|
|
218
|
-
return {
|
|
219
|
-
success: false,
|
|
220
|
-
error: "link_blocked_unverified",
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
// auto_link_unverified=true: link but do NOT change email_verified status
|
|
224
|
-
}
|
|
225
|
-
// Link Facebook account to existing user
|
|
226
|
-
const current_auth_providers = user.auth_providers || "email";
|
|
227
|
-
const new_auth_providers = current_auth_providers.includes("facebook")
|
|
228
|
-
? current_auth_providers
|
|
229
|
-
: `${current_auth_providers},facebook`;
|
|
230
|
-
const update_data = {
|
|
231
|
-
facebook_id,
|
|
232
|
-
auth_providers: new_auth_providers,
|
|
233
|
-
last_logon: now,
|
|
234
|
-
changed_at: now,
|
|
235
|
-
};
|
|
236
|
-
// Update name if not set and Facebook provides one
|
|
237
|
-
if (!user.name && name) {
|
|
238
|
-
update_data.name = name;
|
|
239
|
-
}
|
|
240
|
-
// Update profile picture if not set and Facebook provides one
|
|
241
|
-
if (!user.profile_picture_url && profile_picture_url) {
|
|
242
|
-
update_data.profile_picture_url = profile_picture_url;
|
|
243
|
-
update_data.profile_source = "custom";
|
|
244
|
-
}
|
|
245
|
-
await users_service.updateById(user.id, update_data);
|
|
246
|
-
logger.info("oauth_service_facebook_linked_to_existing", {
|
|
247
|
-
filename: "oauth_service.ts",
|
|
248
|
-
line_number: get_line_number(),
|
|
249
|
-
user_id: user.id,
|
|
250
|
-
email,
|
|
251
|
-
was_unverified: !user_email_verified,
|
|
252
|
-
});
|
|
200
|
+
// Step 2: existing user with matching email
|
|
201
|
+
const users_by_email = await users_service.findBy({ email_address: email });
|
|
202
|
+
if (Array.isArray(users_by_email) && users_by_email.length > 0) {
|
|
203
|
+
const user = users_by_email[0];
|
|
204
|
+
const user_email_verified = user.email_verified;
|
|
205
|
+
if (!user_email_verified && !oauth_config.auto_link_unverified_accounts) {
|
|
253
206
|
return {
|
|
254
|
-
success:
|
|
255
|
-
|
|
256
|
-
is_new_user: false,
|
|
257
|
-
was_linked: true,
|
|
258
|
-
email: user.email_address,
|
|
259
|
-
name: update_data.name || user.name,
|
|
207
|
+
success: false,
|
|
208
|
+
error: "An account with this email exists but is not verified. Please verify your email first.",
|
|
260
209
|
};
|
|
261
210
|
}
|
|
211
|
+
const current_auth_providers = user.auth_providers || "email";
|
|
212
|
+
const new_auth_providers = current_auth_providers.includes("facebook")
|
|
213
|
+
? current_auth_providers
|
|
214
|
+
: `${current_auth_providers},facebook`;
|
|
215
|
+
const update_data = {
|
|
216
|
+
facebook_id,
|
|
217
|
+
auth_providers: new_auth_providers,
|
|
218
|
+
last_logon: now,
|
|
219
|
+
changed_at: now,
|
|
220
|
+
};
|
|
221
|
+
if (!user_email_verified && email_verified) {
|
|
222
|
+
update_data.email_verified = true;
|
|
223
|
+
}
|
|
224
|
+
if (!user.name && name)
|
|
225
|
+
update_data.name = name;
|
|
226
|
+
if (!user.profile_picture_url && profile_picture_url) {
|
|
227
|
+
update_data.profile_picture_url = profile_picture_url;
|
|
228
|
+
update_data.profile_source = "custom";
|
|
229
|
+
}
|
|
230
|
+
await users_service.updateById(user.id, update_data);
|
|
231
|
+
logger.info("oauth_service_facebook_linked_to_existing", {
|
|
232
|
+
filename: "oauth_service.ts",
|
|
233
|
+
user_id: user.id,
|
|
234
|
+
email,
|
|
235
|
+
was_unverified: !user_email_verified,
|
|
236
|
+
});
|
|
237
|
+
return {
|
|
238
|
+
success: true,
|
|
239
|
+
user_id: user.id,
|
|
240
|
+
is_new_user: false,
|
|
241
|
+
was_linked: true,
|
|
242
|
+
email: user.email_address,
|
|
243
|
+
name: user.name,
|
|
244
|
+
};
|
|
262
245
|
}
|
|
263
|
-
// Step 3:
|
|
246
|
+
// Step 3: create new user
|
|
264
247
|
const user_id = randomUUID();
|
|
265
248
|
const insert_data = {
|
|
266
249
|
id: user_id,
|
|
267
250
|
email_address: email,
|
|
268
|
-
password_hash: "", // Empty string for Facebook-only users
|
|
269
|
-
email_verified: false, // Never trust Facebook's email_verified claim
|
|
270
|
-
status: "ACTIVE",
|
|
271
|
-
login_attempts: 0,
|
|
272
251
|
facebook_id,
|
|
273
252
|
auth_providers: "facebook",
|
|
253
|
+
email_verified: email_verified,
|
|
254
|
+
last_logon: now,
|
|
274
255
|
created_at: now,
|
|
275
256
|
changed_at: now,
|
|
276
|
-
last_logon: now,
|
|
277
257
|
};
|
|
278
|
-
if (name)
|
|
258
|
+
if (name)
|
|
279
259
|
insert_data.name = name;
|
|
280
|
-
}
|
|
281
260
|
if (profile_picture_url) {
|
|
282
261
|
insert_data.profile_picture_url = profile_picture_url;
|
|
283
262
|
insert_data.profile_source = "custom";
|
|
284
263
|
}
|
|
285
|
-
const
|
|
286
|
-
if (!Array.isArray(
|
|
287
|
-
return {
|
|
288
|
-
success: false,
|
|
289
|
-
error: "Failed to create user account",
|
|
290
|
-
};
|
|
264
|
+
const inserted = await users_service.insert(insert_data);
|
|
265
|
+
if (!Array.isArray(inserted) || inserted.length === 0) {
|
|
266
|
+
return { success: false, error: "Failed to create user account" };
|
|
291
267
|
}
|
|
292
268
|
logger.info("oauth_service_facebook_new_user_created", {
|
|
293
269
|
filename: "oauth_service.ts",
|
|
294
|
-
line_number: get_line_number(),
|
|
295
270
|
user_id,
|
|
296
271
|
email,
|
|
297
272
|
});
|
|
@@ -300,7 +275,7 @@ export async function handle_facebook_oauth_login(adapter, data, opts) {
|
|
|
300
275
|
user_id,
|
|
301
276
|
is_new_user: true,
|
|
302
277
|
was_linked: false,
|
|
303
|
-
email
|
|
278
|
+
email,
|
|
304
279
|
name,
|
|
305
280
|
};
|
|
306
281
|
}
|
|
@@ -309,17 +284,9 @@ export async function handle_facebook_oauth_login(adapter, data, opts) {
|
|
|
309
284
|
logToConsole: true,
|
|
310
285
|
logToLogger: true,
|
|
311
286
|
logger,
|
|
312
|
-
context: {
|
|
313
|
-
filename: "oauth_service.ts",
|
|
314
|
-
line_number: get_line_number(),
|
|
315
|
-
email: data.email,
|
|
316
|
-
operation: "handle_facebook_oauth_login",
|
|
317
|
-
},
|
|
287
|
+
context: { filename: "oauth_service.ts", email: data.email, operation: "handle_facebook_oauth_login" },
|
|
318
288
|
});
|
|
319
|
-
return {
|
|
320
|
-
success: false,
|
|
321
|
-
error: user_friendly_error,
|
|
322
|
-
};
|
|
289
|
+
return { success: false, error: user_friendly_error };
|
|
323
290
|
}
|
|
324
291
|
}
|
|
325
292
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otp_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/otp_service.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AAUrB;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEjE;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMtF;AAID,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,cAAc,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,CAAC;AAItE;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,qBAAqB,CAAC,
|
|
1
|
+
{"version":3,"file":"otp_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/otp_service.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AAUrB;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEjE;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMtF;AAID,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,cAAc,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,CAAC;AAItE;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAmHjC;AAID,MAAM,MAAM,oBAAoB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,oBAAoB,GAAG,SAAS,CAAA;CAAE,CAAC;AAE3D,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAsHhC"}
|
|
@@ -111,6 +111,11 @@ export async function request_email_otp(args) {
|
|
|
111
111
|
expires_at,
|
|
112
112
|
attempt_count: 0,
|
|
113
113
|
requester_ip: ip,
|
|
114
|
+
// Explicitly pass created_at in JS ISO format ("2024-01-01T00:00:00.000Z") rather
|
|
115
|
+
// than relying on SQLite's DEFAULT (datetime('now') = "2024-01-01 00:00:00").
|
|
116
|
+
// The space-separated SQLite format compares as less-than the T-separated JS ISO
|
|
117
|
+
// threshold used in rate-limit WHERE clauses, causing the counter to always read 0.
|
|
118
|
+
created_at: new Date().toISOString(),
|
|
114
119
|
});
|
|
115
120
|
// 7. Dispatch email — fire-and-forget; errors are logged but do not surface to caller
|
|
116
121
|
try {
|
|
@@ -155,7 +160,7 @@ export async function verify_email_otp(args) {
|
|
|
155
160
|
// 2. Check expiry
|
|
156
161
|
const expires_at_ms = Date.parse(String(row.expires_at));
|
|
157
162
|
if (Number.isNaN(expires_at_ms) || expires_at_ms < Date.now()) {
|
|
158
|
-
return { ok: false, error: "
|
|
163
|
+
return { ok: false, error: "expired" };
|
|
159
164
|
}
|
|
160
165
|
// 3. argon2 verify
|
|
161
166
|
const is_valid = await verify_otp_code(String(row.otp_hash), code);
|
|
@@ -16,8 +16,6 @@ export type ValidateSessionTokenResult = {
|
|
|
16
16
|
* Token includes user_id, email, issued at time, and expiration
|
|
17
17
|
* @param user_id - User ID
|
|
18
18
|
* @param email - User email address
|
|
19
|
-
* @param managed_by_user_id - Optional: ID of the managing user (for impersonation)
|
|
20
|
-
* @param ttl_seconds - Optional: token lifetime in seconds (default: 30 days). Use 604800 for 7-day OTP sessions.
|
|
21
19
|
* @returns JWT token string
|
|
22
20
|
*/
|
|
23
21
|
export declare function create_session_token(user_id: string, email: string, managed_by_user_id?: string, ttl_seconds?: number): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session_token_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/session_token_service.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAuCF
|
|
1
|
+
{"version":3,"file":"session_token_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/session_token_service.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAuCF;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,kBAAkB,CAAC,EAAE,MAAM,EAC3B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CA4CjB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,0BAA0B,CAAC,CAkDrC"}
|
|
@@ -41,8 +41,6 @@ function get_session_token_expiry_seconds() {
|
|
|
41
41
|
* Token includes user_id, email, issued at time, and expiration
|
|
42
42
|
* @param user_id - User ID
|
|
43
43
|
* @param email - User email address
|
|
44
|
-
* @param managed_by_user_id - Optional: ID of the managing user (for impersonation)
|
|
45
|
-
* @param ttl_seconds - Optional: token lifetime in seconds (default: 30 days). Use 604800 for 7-day OTP sessions.
|
|
46
44
|
* @returns JWT token string
|
|
47
45
|
*/
|
|
48
46
|
export async function create_session_token(user_id, email, managed_by_user_id, ttl_seconds) {
|
|
@@ -2,19 +2,7 @@ import "server-only";
|
|
|
2
2
|
export type CreateFirmPageProps = {
|
|
3
3
|
/** Disable the navbar wrapper */
|
|
4
4
|
disableNavbar?: boolean;
|
|
5
|
-
/**
|
|
6
|
-
* Optional theme that controls visual appearance and layout mode.
|
|
7
|
-
* When `theme.layout` is `"split"`, activates the two-column split layout
|
|
8
|
-
* with the brand panel on the left.
|
|
9
|
-
*/
|
|
10
|
-
theme?: import("../theme/theme_types").HazoAuthTheme;
|
|
11
|
-
/** Override the page heading. Falls back to HazoAuthStringsProvider → DEFAULT_STRINGS. */
|
|
12
|
-
title?: string;
|
|
13
|
-
/** Override the page subtitle. Falls back to HazoAuthStringsProvider → DEFAULT_STRINGS. */
|
|
14
|
-
subtitle?: string;
|
|
15
|
-
/** Override the submit button label. Falls back to HazoAuthStringsProvider → DEFAULT_STRINGS. */
|
|
16
|
-
ctaText?: string;
|
|
17
5
|
};
|
|
18
|
-
export default function CreateFirmPage({ disableNavbar
|
|
6
|
+
export default function CreateFirmPage({ disableNavbar }?: CreateFirmPageProps): import("react/jsx-runtime").JSX.Element;
|
|
19
7
|
export { CreateFirmPage };
|
|
20
8
|
//# sourceMappingURL=create_firm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create_firm.d.ts","sourceRoot":"","sources":["../../src/page_components/create_firm.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"create_firm.d.ts","sourceRoot":"","sources":["../../src/page_components/create_firm.tsx"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAQrB,MAAM,MAAM,mBAAmB,GAAG;IAChC,iCAAiC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAsDF,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,aAAa,EAAE,GAAE,mBAAwB,2CAsBjF;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -6,28 +6,24 @@ import "server-only";
|
|
|
6
6
|
import CreateFirmLayout from "../components/layouts/create_firm/index.js";
|
|
7
7
|
import { AuthPageShell } from "../components/layouts/shared/components/auth_page_shell.js";
|
|
8
8
|
import { get_config_value } from "../lib/config/config_loader.server.js";
|
|
9
|
-
import { DEFAULT_STRINGS, readStrings } from "../strings.js";
|
|
10
9
|
// section: config_loader
|
|
11
10
|
function get_create_firm_config() {
|
|
12
11
|
return {
|
|
12
|
+
image_src: get_config_value("hazo_auth__create_firm", "image_src", "/hazo_auth/images/new_firm_default.jpg"),
|
|
13
|
+
heading: get_config_value("hazo_auth__create_firm", "heading", "Create Your Firm"),
|
|
14
|
+
sub_heading: get_config_value("hazo_auth__create_firm", "sub_heading", "Set up your organisation to get started"),
|
|
13
15
|
firm_name_label: get_config_value("hazo_auth__create_firm", "firm_name_label", "Firm Name"),
|
|
14
16
|
org_structure_label: get_config_value("hazo_auth__create_firm", "org_structure_label", "Organisation Structure"),
|
|
15
17
|
org_structure_default: get_config_value("hazo_auth__create_firm", "org_structure_default", "Headquarters"),
|
|
18
|
+
submit_button_label: get_config_value("hazo_auth__create_firm", "submit_button_label", "Create Firm"),
|
|
16
19
|
success_message: get_config_value("hazo_auth__create_firm", "success_message", "Your firm has been created successfully!"),
|
|
17
20
|
redirect_route: get_config_value("hazo_auth__create_firm", "redirect_route", "/"),
|
|
18
21
|
};
|
|
19
22
|
}
|
|
20
23
|
// section: component
|
|
21
|
-
export default function CreateFirmPage({ disableNavbar
|
|
22
|
-
var _a, _b, _c;
|
|
23
|
-
// Resolve strings: prop > HazoAuthStringsProvider > DEFAULT_STRINGS
|
|
24
|
-
const strings = readStrings();
|
|
25
|
-
const cf_strings = strings.create_firm;
|
|
26
|
-
const resolved_title = (_a = title !== null && title !== void 0 ? title : cf_strings.title) !== null && _a !== void 0 ? _a : DEFAULT_STRINGS.create_firm.title;
|
|
27
|
-
const resolved_subtitle = (_b = subtitle !== null && subtitle !== void 0 ? subtitle : cf_strings.subtitle) !== null && _b !== void 0 ? _b : DEFAULT_STRINGS.create_firm.subtitle;
|
|
28
|
-
const resolved_cta = (_c = ctaText !== null && ctaText !== void 0 ? ctaText : cf_strings.ctaText) !== null && _c !== void 0 ? _c : DEFAULT_STRINGS.create_firm.ctaText;
|
|
24
|
+
export default function CreateFirmPage({ disableNavbar } = {}) {
|
|
29
25
|
const config = get_create_firm_config();
|
|
30
|
-
const layoutContent = (_jsx(CreateFirmLayout, { heading:
|
|
26
|
+
const layoutContent = (_jsx(CreateFirmLayout, { image_src: config.image_src, heading: config.heading, sub_heading: config.sub_heading, firm_name_label: config.firm_name_label, org_structure_label: config.org_structure_label, default_org_structure: config.org_structure_default, submit_button_label: config.submit_button_label, success_message: config.success_message, redirect_route: config.redirect_route }));
|
|
31
27
|
if (disableNavbar) {
|
|
32
28
|
return layoutContent;
|
|
33
29
|
}
|
|
@@ -4,6 +4,9 @@ export type ForgotPasswordPageProps = {
|
|
|
4
4
|
showReturnHomeButton?: boolean;
|
|
5
5
|
returnHomeButtonLabel?: string;
|
|
6
6
|
returnHomePath?: string;
|
|
7
|
+
imageSrc?: string;
|
|
8
|
+
imageAlt?: string;
|
|
9
|
+
imageBackgroundColor?: string;
|
|
7
10
|
};
|
|
8
11
|
/**
|
|
9
12
|
* Zero-config forgot password page component
|
|
@@ -11,6 +14,6 @@ export type ForgotPasswordPageProps = {
|
|
|
11
14
|
* @param props - Optional configuration overrides
|
|
12
15
|
* @returns Forgot password page component
|
|
13
16
|
*/
|
|
14
|
-
export declare function ForgotPasswordPage({ alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, }?: ForgotPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function ForgotPasswordPage({ alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, imageSrc, imageAlt, imageBackgroundColor, }?: ForgotPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
15
18
|
export default ForgotPasswordPage;
|
|
16
19
|
//# sourceMappingURL=forgot_password.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forgot_password.d.ts","sourceRoot":"","sources":["../../src/page_components/forgot_password.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"forgot_password.d.ts","sourceRoot":"","sources":["../../src/page_components/forgot_password.tsx"],"names":[],"mappings":"AA+BA,MAAM,MAAM,uBAAuB,GAAG;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,uBAA4B,2CAmC9B;AAED,eAAe,kBAAkB,CAAC"}
|
|
@@ -21,6 +21,10 @@ import { useEffect, useState } from "react";
|
|
|
21
21
|
import forgot_password_layout from "../components/layouts/forgot_password/index.js";
|
|
22
22
|
import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
|
|
23
23
|
import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
|
|
24
|
+
// section: constants
|
|
25
|
+
const DEFAULT_IMAGE_SRC = "/hazo_auth/images/forgot_password_default.jpg";
|
|
26
|
+
const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
|
|
27
|
+
const DEFAULT_IMAGE_BG = "#f1f5f9";
|
|
24
28
|
// section: component
|
|
25
29
|
/**
|
|
26
30
|
* Zero-config forgot password page component
|
|
@@ -28,7 +32,7 @@ import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
|
|
|
28
32
|
* @param props - Optional configuration overrides
|
|
29
33
|
* @returns Forgot password page component
|
|
30
34
|
*/
|
|
31
|
-
export function ForgotPasswordPage({ alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", } = {}) {
|
|
35
|
+
export function ForgotPasswordPage({ alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
|
|
32
36
|
const [dataClient, setDataClient] = useState(null);
|
|
33
37
|
useEffect(() => {
|
|
34
38
|
// Initialize hazo_connect on client side
|
|
@@ -41,6 +45,6 @@ export function ForgotPasswordPage({ alreadyLoggedInMessage = "You are already l
|
|
|
41
45
|
return (_jsx("div", { className: "cls_forgot_password_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
|
|
42
46
|
}
|
|
43
47
|
const ForgotPasswordLayout = forgot_password_layout;
|
|
44
|
-
return (_jsx(ForgotPasswordLayout, { data_client: dataClient, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath }));
|
|
48
|
+
return (_jsx(ForgotPasswordLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, data_client: dataClient, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath }));
|
|
45
49
|
}
|
|
46
50
|
export default ForgotPasswordPage;
|
|
@@ -15,6 +15,9 @@ export type LoginPageProps = {
|
|
|
15
15
|
createAccountPath?: string;
|
|
16
16
|
createAccountLabel?: string;
|
|
17
17
|
urlOnLogon?: string;
|
|
18
|
+
imageSrc?: string;
|
|
19
|
+
imageAlt?: string;
|
|
20
|
+
imageBackgroundColor?: string;
|
|
18
21
|
};
|
|
19
22
|
/**
|
|
20
23
|
* Zero-config login page component
|
|
@@ -22,6 +25,6 @@ export type LoginPageProps = {
|
|
|
22
25
|
* @param props - Optional configuration overrides
|
|
23
26
|
* @returns Login page component
|
|
24
27
|
*/
|
|
25
|
-
export declare function LoginPage({ redirectRoute, successMessage, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, forgotPasswordPath, forgotPasswordLabel, createAccountPath, createAccountLabel, urlOnLogon, }?: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export declare function LoginPage({ redirectRoute, successMessage, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, forgotPasswordPath, forgotPasswordLabel, createAccountPath, createAccountLabel, urlOnLogon, imageSrc, imageAlt, imageBackgroundColor, }?: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
26
29
|
export default LoginPage;
|
|
27
30
|
//# sourceMappingURL=login.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/page_components/login.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/page_components/login.tsx"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,aAAa,EACb,cAAyC,EACzC,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,kBAAiD,EACjD,mBAAwC,EACxC,iBAAyC,EACzC,kBAAqC,EACrC,UAAU,EACV,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,cAAmB,2CA0CrB;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -21,6 +21,10 @@ import { useEffect, useState } from "react";
|
|
|
21
21
|
import login_layout from "../components/layouts/login/index.js";
|
|
22
22
|
import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
|
|
23
23
|
import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
|
|
24
|
+
// section: constants
|
|
25
|
+
const DEFAULT_IMAGE_SRC = "/hazo_auth/images/login_default.jpg";
|
|
26
|
+
const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
|
|
27
|
+
const DEFAULT_IMAGE_BG = "#f1f5f9";
|
|
24
28
|
// section: component
|
|
25
29
|
/**
|
|
26
30
|
* Zero-config login page component
|
|
@@ -28,7 +32,7 @@ import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
|
|
|
28
32
|
* @param props - Optional configuration overrides
|
|
29
33
|
* @returns Login page component
|
|
30
34
|
*/
|
|
31
|
-
export function LoginPage({ redirectRoute, successMessage = "Successfully logged in", alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", forgotPasswordPath = "/hazo_auth/forgot_password", forgotPasswordLabel = "Forgot password?", createAccountPath = "/hazo_auth/register", createAccountLabel = "Create account", urlOnLogon, } = {}) {
|
|
35
|
+
export function LoginPage({ redirectRoute, successMessage = "Successfully logged in", alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", forgotPasswordPath = "/hazo_auth/forgot_password", forgotPasswordLabel = "Forgot password?", createAccountPath = "/hazo_auth/register", createAccountLabel = "Create account", urlOnLogon, imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
|
|
32
36
|
const [dataClient, setDataClient] = useState(null);
|
|
33
37
|
useEffect(() => {
|
|
34
38
|
// Initialize hazo_connect on client side
|
|
@@ -41,6 +45,6 @@ export function LoginPage({ redirectRoute, successMessage = "Successfully logged
|
|
|
41
45
|
return (_jsx("div", { className: "cls_login_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
|
|
42
46
|
}
|
|
43
47
|
const LoginLayout = login_layout;
|
|
44
|
-
return (_jsx(LoginLayout, { data_client: dataClient, redirectRoute: redirectRoute, successMessage: successMessage, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, forgot_password_path: forgotPasswordPath, forgot_password_label: forgotPasswordLabel, create_account_path: createAccountPath, create_account_label: createAccountLabel, urlOnLogon: urlOnLogon }));
|
|
48
|
+
return (_jsx(LoginLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, data_client: dataClient, redirectRoute: redirectRoute, successMessage: successMessage, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, forgot_password_path: forgotPasswordPath, forgot_password_label: forgotPasswordLabel, create_account_path: createAccountPath, create_account_label: createAccountLabel, urlOnLogon: urlOnLogon }));
|
|
45
49
|
}
|
|
46
50
|
export default LoginPage;
|
|
@@ -10,6 +10,9 @@ export type RegisterPageProps = {
|
|
|
10
10
|
signInPath?: string;
|
|
11
11
|
signInLabel?: string;
|
|
12
12
|
urlOnLogon?: string;
|
|
13
|
+
imageSrc?: string;
|
|
14
|
+
imageAlt?: string;
|
|
15
|
+
imageBackgroundColor?: string;
|
|
13
16
|
};
|
|
14
17
|
/**
|
|
15
18
|
* Zero-config register page component
|
|
@@ -17,6 +20,6 @@ export type RegisterPageProps = {
|
|
|
17
20
|
* @param props - Optional configuration overrides
|
|
18
21
|
* @returns Register page component
|
|
19
22
|
*/
|
|
20
|
-
export declare function RegisterPage({ showNameField, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, urlOnLogon, }?: RegisterPageProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare function RegisterPage({ showNameField, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, urlOnLogon, imageSrc, imageAlt, imageBackgroundColor, }?: RegisterPageProps): import("react/jsx-runtime").JSX.Element;
|
|
21
24
|
export default RegisterPage;
|
|
22
25
|
//# sourceMappingURL=register.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/page_components/register.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0DAA0D,CAAC;
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/page_components/register.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0DAA0D,CAAC;AAgB7G,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,4BAA4B,CAAC;IACpD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,aAAoB,EACpB,oBAAoD,EACpD,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,UAA+B,EAC/B,WAAuB,EACvB,UAAU,EACV,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,iBAAsB,2CAwCxB;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -21,6 +21,10 @@ import { useEffect, useState } from "react";
|
|
|
21
21
|
import register_layout from "../components/layouts/register/index.js";
|
|
22
22
|
import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
|
|
23
23
|
import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
|
|
24
|
+
// section: constants
|
|
25
|
+
const DEFAULT_IMAGE_SRC = "/hazo_auth/images/register_default.jpg";
|
|
26
|
+
const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
|
|
27
|
+
const DEFAULT_IMAGE_BG = "#e2e8f0";
|
|
24
28
|
const DEFAULT_PASSWORD_REQUIREMENTS = {
|
|
25
29
|
minimum_length: 8,
|
|
26
30
|
require_uppercase: true,
|
|
@@ -35,7 +39,7 @@ const DEFAULT_PASSWORD_REQUIREMENTS = {
|
|
|
35
39
|
* @param props - Optional configuration overrides
|
|
36
40
|
* @returns Register page component
|
|
37
41
|
*/
|
|
38
|
-
export function RegisterPage({ showNameField = true, passwordRequirements = DEFAULT_PASSWORD_REQUIREMENTS, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", signInPath = "/hazo_auth/login", signInLabel = "Sign in", urlOnLogon, } = {}) {
|
|
42
|
+
export function RegisterPage({ showNameField = true, passwordRequirements = DEFAULT_PASSWORD_REQUIREMENTS, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", signInPath = "/hazo_auth/login", signInLabel = "Sign in", urlOnLogon, imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
|
|
39
43
|
const [dataClient, setDataClient] = useState(null);
|
|
40
44
|
useEffect(() => {
|
|
41
45
|
// Initialize hazo_connect on client side
|
|
@@ -48,6 +52,6 @@ export function RegisterPage({ showNameField = true, passwordRequirements = DEFA
|
|
|
48
52
|
return (_jsx("div", { className: "cls_register_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
|
|
49
53
|
}
|
|
50
54
|
const RegisterLayout = register_layout;
|
|
51
|
-
return (_jsx(RegisterLayout, { password_requirements: passwordRequirements, show_name_field: showNameField, data_client: dataClient, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, signInPath: signInPath, signInLabel: signInLabel, urlOnLogon: urlOnLogon }));
|
|
55
|
+
return (_jsx(RegisterLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, password_requirements: passwordRequirements, show_name_field: showNameField, data_client: dataClient, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, signInPath: signInPath, signInLabel: signInLabel, urlOnLogon: urlOnLogon }));
|
|
52
56
|
}
|
|
53
57
|
export default RegisterPage;
|
|
@@ -10,6 +10,9 @@ export type ResetPasswordPageProps = {
|
|
|
10
10
|
showReturnHomeButton?: boolean;
|
|
11
11
|
returnHomeButtonLabel?: string;
|
|
12
12
|
returnHomePath?: string;
|
|
13
|
+
imageSrc?: string;
|
|
14
|
+
imageAlt?: string;
|
|
15
|
+
imageBackgroundColor?: string;
|
|
13
16
|
};
|
|
14
17
|
/**
|
|
15
18
|
* Zero-config reset password page component
|
|
@@ -17,6 +20,6 @@ export type ResetPasswordPageProps = {
|
|
|
17
20
|
* @param props - Optional configuration overrides
|
|
18
21
|
* @returns Reset password page component
|
|
19
22
|
*/
|
|
20
|
-
export declare function ResetPasswordPage({ errorMessage, successMessage, loginPath, forgotPasswordPath, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, }?: ResetPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare function ResetPasswordPage({ errorMessage, successMessage, loginPath, forgotPasswordPath, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, imageSrc, imageAlt, imageBackgroundColor, }?: ResetPasswordPageProps): import("react/jsx-runtime").JSX.Element;
|
|
21
24
|
export default ResetPasswordPage;
|
|
22
25
|
//# sourceMappingURL=reset_password.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reset_password.d.ts","sourceRoot":"","sources":["../../src/page_components/reset_password.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0DAA0D,CAAC;
|
|
1
|
+
{"version":3,"file":"reset_password.d.ts","sourceRoot":"","sources":["../../src/page_components/reset_password.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0DAA0D,CAAC;AAgB7G,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,4BAA4B,CAAC;IACpD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,YAAmE,EACnE,cAAwF,EACxF,SAA8B,EAC9B,kBAAiD,EACjD,oBAAoD,EACpD,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,sBAA2B,2CAsC7B;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -21,6 +21,10 @@ import { useEffect, useState } from "react";
|
|
|
21
21
|
import reset_password_layout from "../components/layouts/reset_password/index.js";
|
|
22
22
|
import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
|
|
23
23
|
import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
|
|
24
|
+
// section: constants
|
|
25
|
+
const DEFAULT_IMAGE_SRC = "/hazo_auth/images/reset_password_default.jpg";
|
|
26
|
+
const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
|
|
27
|
+
const DEFAULT_IMAGE_BG = "#f1f5f9";
|
|
24
28
|
const DEFAULT_PASSWORD_REQUIREMENTS = {
|
|
25
29
|
minimum_length: 8,
|
|
26
30
|
require_uppercase: true,
|
|
@@ -35,7 +39,7 @@ const DEFAULT_PASSWORD_REQUIREMENTS = {
|
|
|
35
39
|
* @param props - Optional configuration overrides
|
|
36
40
|
* @returns Reset password page component
|
|
37
41
|
*/
|
|
38
|
-
export function ResetPasswordPage({ errorMessage = "Your password reset link has expired or is invalid", successMessage = "Password reset successful! You can now log in with your new password.", loginPath = "/hazo_auth/login", forgotPasswordPath = "/hazo_auth/forgot_password", passwordRequirements = DEFAULT_PASSWORD_REQUIREMENTS, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", } = {}) {
|
|
42
|
+
export function ResetPasswordPage({ errorMessage = "Your password reset link has expired or is invalid", successMessage = "Password reset successful! You can now log in with your new password.", loginPath = "/hazo_auth/login", forgotPasswordPath = "/hazo_auth/forgot_password", passwordRequirements = DEFAULT_PASSWORD_REQUIREMENTS, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
|
|
39
43
|
const [dataClient, setDataClient] = useState(null);
|
|
40
44
|
useEffect(() => {
|
|
41
45
|
// Initialize hazo_connect on client side
|
|
@@ -48,6 +52,6 @@ export function ResetPasswordPage({ errorMessage = "Your password reset link has
|
|
|
48
52
|
return (_jsx("div", { className: "cls_reset_password_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
|
|
49
53
|
}
|
|
50
54
|
const ResetPasswordLayout = reset_password_layout;
|
|
51
|
-
return (_jsx(ResetPasswordLayout, { data_client: dataClient, errorMessage: errorMessage, successMessage: successMessage, password_requirements: passwordRequirements, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath }));
|
|
55
|
+
return (_jsx(ResetPasswordLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, data_client: dataClient, errorMessage: errorMessage, successMessage: successMessage, password_requirements: passwordRequirements, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath }));
|
|
52
56
|
}
|
|
53
57
|
export default ResetPasswordPage;
|
|
@@ -6,6 +6,9 @@ export type VerifyEmailPageProps = {
|
|
|
6
6
|
returnHomePath?: string;
|
|
7
7
|
redirectDelay?: number;
|
|
8
8
|
loginPath?: string;
|
|
9
|
+
imageSrc?: string;
|
|
10
|
+
imageAlt?: string;
|
|
11
|
+
imageBackgroundColor?: string;
|
|
9
12
|
};
|
|
10
13
|
/**
|
|
11
14
|
* Zero-config verify email page component
|
|
@@ -13,6 +16,6 @@ export type VerifyEmailPageProps = {
|
|
|
13
16
|
* @param props - Optional configuration overrides
|
|
14
17
|
* @returns Verify email page component
|
|
15
18
|
*/
|
|
16
|
-
export declare function VerifyEmailPage({ alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, redirectDelay, loginPath, }?: VerifyEmailPageProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function VerifyEmailPage({ alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, redirectDelay, loginPath, imageSrc, imageAlt, imageBackgroundColor, }?: VerifyEmailPageProps): import("react/jsx-runtime").JSX.Element;
|
|
17
20
|
export default VerifyEmailPage;
|
|
18
21
|
//# sourceMappingURL=verify_email.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify_email.d.ts","sourceRoot":"","sources":["../../src/page_components/verify_email.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify_email.d.ts","sourceRoot":"","sources":["../../src/page_components/verify_email.tsx"],"names":[],"mappings":"AA+BA,MAAM,MAAM,oBAAoB,GAAG;IACjC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,aAAoB,EACpB,SAA8B,EAC9B,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,oBAAyB,2CAqC3B;AAED,eAAe,eAAe,CAAC"}
|