hazo_auth 7.0.1 → 8.0.1
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 +96 -319
- package/SETUP_CHECKLIST.md +59 -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 +15 -21
- package/cli-src/lib/auth/hazo_get_auth.server.ts +19 -0
- 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/legal/legal_docs_config.server.ts +61 -0
- package/cli-src/lib/legal/legal_docs_reader.server.ts +36 -0
- package/cli-src/lib/legal/legal_docs_service.ts +196 -0
- package/cli-src/lib/legal/legal_docs_types.ts +31 -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/registration_service.ts +16 -1
- 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 +1 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -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/index.d.ts +1 -0
- package/dist/components/layouts/index.d.ts.map +1 -1
- package/dist/components/layouts/index.js +2 -0
- package/dist/components/layouts/legal/index.d.ts +5 -0
- package/dist/components/layouts/legal/index.d.ts.map +1 -0
- package/dist/components/layouts/legal/index.js +4 -0
- package/dist/components/layouts/legal/legal_acceptance_gate.d.ts +7 -0
- package/dist/components/layouts/legal/legal_acceptance_gate.d.ts.map +1 -0
- package/dist/components/layouts/legal/legal_acceptance_gate.js +84 -0
- package/dist/components/layouts/legal/legal_doc_checkbox_list.d.ts +9 -0
- package/dist/components/layouts/legal/legal_doc_checkbox_list.d.ts.map +1 -0
- package/dist/components/layouts/legal/legal_doc_checkbox_list.js +11 -0
- package/dist/components/layouts/legal/legal_doc_combined_view.d.ts +9 -0
- package/dist/components/layouts/legal/legal_doc_combined_view.d.ts.map +1 -0
- package/dist/components/layouts/legal/legal_doc_combined_view.js +11 -0
- package/dist/components/layouts/legal/legal_doc_drawer.d.ts +8 -0
- package/dist/components/layouts/legal/legal_doc_drawer.d.ts.map +1 -0
- package/dist/components/layouts/legal/legal_doc_drawer.js +55 -0
- 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/hooks/use_register_form.d.ts +5 -1
- package/dist/components/layouts/register/hooks/use_register_form.d.ts.map +1 -1
- package/dist/components/layouts/register/hooks/use_register_form.js +25 -10
- 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 +26 -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 +84 -9
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/input-otp.d.ts +2 -2
- package/dist/components/ui/sheet.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.d.ts +14 -13
- package/dist/lib/auth/auth_types.d.ts.map +1 -1
- package/dist/lib/auth/auth_types.js +0 -10
- package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_auth.server.js +19 -0
- 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/legal/legal_docs_config.server.d.ts +22 -0
- package/dist/lib/legal/legal_docs_config.server.d.ts.map +1 -0
- package/dist/lib/legal/legal_docs_config.server.js +52 -0
- package/dist/lib/legal/legal_docs_reader.server.d.ts +15 -0
- package/dist/lib/legal/legal_docs_reader.server.d.ts.map +1 -0
- package/dist/lib/legal/legal_docs_reader.server.js +24 -0
- package/dist/lib/legal/legal_docs_service.d.ts +49 -0
- package/dist/lib/legal/legal_docs_service.d.ts.map +1 -0
- package/dist/lib/legal/legal_docs_service.js +140 -0
- package/dist/lib/legal/legal_docs_types.d.ts +25 -0
- package/dist/lib/legal/legal_docs_types.d.ts.map +1 -0
- package/dist/lib/legal/legal_docs_types.js +2 -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/registration_service.d.ts +5 -0
- package/dist/lib/services/registration_service.d.ts.map +1 -1
- package/dist/lib/services/registration_service.js +6 -0
- 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/index.d.ts +0 -5
- package/dist/page_components/index.d.ts.map +1 -1
- package/dist/page_components/index.js +0 -5
- 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 +9 -4
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +13 -5
- package/dist/server/routes/legal_docs_accept.d.ts +3 -0
- package/dist/server/routes/legal_docs_accept.d.ts.map +1 -0
- package/dist/server/routes/legal_docs_accept.js +43 -0
- package/dist/server/routes/legal_docs_get.d.ts +3 -0
- package/dist/server/routes/legal_docs_get.d.ts.map +1 -0
- package/dist/server/routes/legal_docs_get.js +49 -0
- package/dist/server/routes/legal_docs_publish.d.ts +3 -0
- package/dist/server/routes/legal_docs_publish.d.ts.map +1 -0
- package/dist/server/routes/legal_docs_publish.js +35 -0
- 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/register.d.ts.map +1 -1
- package/dist/server/routes/register.js +26 -0
- 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 +94 -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/strings.d.ts +2 -0
- package/dist/strings.d.ts.map +1 -0
- package/dist/strings.js +3 -0
- 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 +30 -61
- 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
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
import "server-only";
|
|
4
4
|
// section: imports
|
|
5
5
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
6
|
+
import { get_config_value } from "./config/config_loader.server.js";
|
|
7
|
+
// Default image path - consuming apps should either:
|
|
8
|
+
// 1. Configure their own image_src in hazo_auth_config.ini
|
|
9
|
+
// 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
|
|
10
|
+
const DEFAULT_VERIFY_EMAIL_IMAGE_PATH = "/hazo_auth/images/verify_email_default.jpg";
|
|
6
11
|
// section: helpers
|
|
7
12
|
/**
|
|
8
13
|
* Reads email verification layout configuration from hazo_auth_config.ini file
|
|
@@ -10,13 +15,23 @@ import { get_already_logged_in_config } from "./already_logged_in_config.server.
|
|
|
10
15
|
* @returns Email verification configuration options
|
|
11
16
|
*/
|
|
12
17
|
export function get_email_verification_config() {
|
|
18
|
+
const section = "hazo_auth__email_verification_layout";
|
|
13
19
|
// Get shared already logged in config
|
|
14
20
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
21
|
+
// Read image configuration
|
|
22
|
+
// If not set in config, falls back to default path-based image
|
|
23
|
+
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
24
|
+
const imageSrc = get_config_value(section, "image_src", DEFAULT_VERIFY_EMAIL_IMAGE_PATH);
|
|
25
|
+
const imageAlt = get_config_value(section, "image_alt", "Email verification illustration");
|
|
26
|
+
const imageBackgroundColor = get_config_value(section, "image_background_color", "#f1f5f9");
|
|
15
27
|
return {
|
|
16
28
|
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
17
29
|
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
18
30
|
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
19
31
|
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
20
32
|
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
33
|
+
imageSrc,
|
|
34
|
+
imageAlt,
|
|
35
|
+
imageBackgroundColor,
|
|
21
36
|
};
|
|
22
37
|
}
|
|
@@ -5,6 +5,9 @@ export type ForgotPasswordConfig = {
|
|
|
5
5
|
showReturnHomeButton: boolean;
|
|
6
6
|
returnHomeButtonLabel: string;
|
|
7
7
|
returnHomePath: string;
|
|
8
|
+
imageSrc: string;
|
|
9
|
+
imageAlt: string;
|
|
10
|
+
imageBackgroundColor: string;
|
|
8
11
|
};
|
|
9
12
|
/**
|
|
10
13
|
* Reads forgot password layout configuration from hazo_auth_config.ini file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forgot_password_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/forgot_password_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"forgot_password_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/forgot_password_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAYrB,MAAM,MAAM,oBAAoB,GAAG;IACjC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,oBAAoB,CAoCjE"}
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
import "server-only";
|
|
4
4
|
// section: imports
|
|
5
5
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
6
|
+
import { get_config_value } from "./config/config_loader.server.js";
|
|
7
|
+
// Default image path - consuming apps should either:
|
|
8
|
+
// 1. Configure their own image_src in hazo_auth_config.ini
|
|
9
|
+
// 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
|
|
10
|
+
const DEFAULT_FORGOT_PASSWORD_IMAGE_PATH = "/hazo_auth/images/forgot_password_default.jpg";
|
|
6
11
|
// section: helpers
|
|
7
12
|
/**
|
|
8
13
|
* Reads forgot password layout configuration from hazo_auth_config.ini file
|
|
@@ -10,13 +15,23 @@ import { get_already_logged_in_config } from "./already_logged_in_config.server.
|
|
|
10
15
|
* @returns Forgot password configuration options
|
|
11
16
|
*/
|
|
12
17
|
export function get_forgot_password_config() {
|
|
18
|
+
const section = "hazo_auth__forgot_password_layout";
|
|
13
19
|
// Get shared already logged in config
|
|
14
20
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
21
|
+
// Read image configuration
|
|
22
|
+
// If not set in config, falls back to default path-based image
|
|
23
|
+
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
24
|
+
const imageSrc = get_config_value(section, "image_src", DEFAULT_FORGOT_PASSWORD_IMAGE_PATH);
|
|
25
|
+
const imageAlt = get_config_value(section, "image_alt", "Password recovery illustration");
|
|
26
|
+
const imageBackgroundColor = get_config_value(section, "image_background_color", "#f1f5f9");
|
|
15
27
|
return {
|
|
16
28
|
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
17
29
|
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
18
30
|
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
19
31
|
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
20
32
|
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
33
|
+
imageSrc,
|
|
34
|
+
imageAlt,
|
|
35
|
+
imageBackgroundColor,
|
|
21
36
|
};
|
|
22
37
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import type { LegalDocsConfig } from './legal_docs_types';
|
|
3
|
+
/**
|
|
4
|
+
* Reads legal docs configuration from hazo_auth_config.ini.
|
|
5
|
+
* Returns an empty docs array if the section is absent (legal docs disabled).
|
|
6
|
+
*
|
|
7
|
+
* Expected INI shape:
|
|
8
|
+
* [hazo_auth__legal_docs]
|
|
9
|
+
* display_mode = separate ; or: combined
|
|
10
|
+
* doc_1_key = terms
|
|
11
|
+
* doc_1_title = Terms of Service
|
|
12
|
+
* doc_1_path = legal/terms.md
|
|
13
|
+
* doc_2_key = privacy
|
|
14
|
+
* doc_2_title = Privacy Policy
|
|
15
|
+
* doc_2_path = legal/privacy.md
|
|
16
|
+
*/
|
|
17
|
+
export declare function get_legal_docs_config(): LegalDocsConfig;
|
|
18
|
+
/**
|
|
19
|
+
* Call this in tests to clear the cache between runs.
|
|
20
|
+
*/
|
|
21
|
+
export declare function _reset_legal_docs_config_cache(): void;
|
|
22
|
+
//# sourceMappingURL=legal_docs_config.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legal_docs_config.server.d.ts","sourceRoot":"","sources":["../../../src/lib/legal/legal_docs_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAIrB,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAW1E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAsBvD;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// file_description: server-only helper to read legal docs configuration from hazo_auth_config.ini
|
|
2
|
+
// section: server-only-guard
|
|
3
|
+
import 'server-only';
|
|
4
|
+
// section: imports
|
|
5
|
+
import { read_config_section } from '../config/config_loader.server.js';
|
|
6
|
+
// section: constants
|
|
7
|
+
const SECTION_NAME = 'hazo_auth__legal_docs';
|
|
8
|
+
// section: cache
|
|
9
|
+
// Cached after first load — INI changes require server restart anyway
|
|
10
|
+
let _cached = null;
|
|
11
|
+
// section: exports
|
|
12
|
+
/**
|
|
13
|
+
* Reads legal docs configuration from hazo_auth_config.ini.
|
|
14
|
+
* Returns an empty docs array if the section is absent (legal docs disabled).
|
|
15
|
+
*
|
|
16
|
+
* Expected INI shape:
|
|
17
|
+
* [hazo_auth__legal_docs]
|
|
18
|
+
* display_mode = separate ; or: combined
|
|
19
|
+
* doc_1_key = terms
|
|
20
|
+
* doc_1_title = Terms of Service
|
|
21
|
+
* doc_1_path = legal/terms.md
|
|
22
|
+
* doc_2_key = privacy
|
|
23
|
+
* doc_2_title = Privacy Policy
|
|
24
|
+
* doc_2_path = legal/privacy.md
|
|
25
|
+
*/
|
|
26
|
+
export function get_legal_docs_config() {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
if (_cached)
|
|
29
|
+
return _cached;
|
|
30
|
+
const section = (_a = read_config_section(SECTION_NAME)) !== null && _a !== void 0 ? _a : {};
|
|
31
|
+
const docs = [];
|
|
32
|
+
let i = 1;
|
|
33
|
+
while (section[`doc_${i}_key`]) {
|
|
34
|
+
docs.push({
|
|
35
|
+
key: section[`doc_${i}_key`],
|
|
36
|
+
title: (_b = section[`doc_${i}_title`]) !== null && _b !== void 0 ? _b : section[`doc_${i}_key`],
|
|
37
|
+
path: section[`doc_${i}_path`],
|
|
38
|
+
});
|
|
39
|
+
i++;
|
|
40
|
+
}
|
|
41
|
+
_cached = {
|
|
42
|
+
docs,
|
|
43
|
+
display_mode: section['display_mode'] === 'combined' ? 'combined' : 'separate',
|
|
44
|
+
};
|
|
45
|
+
return _cached;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Call this in tests to clear the cache between runs.
|
|
49
|
+
*/
|
|
50
|
+
export function _reset_legal_docs_config_cache() {
|
|
51
|
+
_cached = null;
|
|
52
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
export interface ReadDocResult {
|
|
3
|
+
content: string;
|
|
4
|
+
hash: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Reads a legal document from the filesystem and returns its text content
|
|
8
|
+
* together with a deterministic SHA-256 hash of that content.
|
|
9
|
+
*
|
|
10
|
+
* @param doc_path - Absolute path, or a path relative to process.cwd().
|
|
11
|
+
* @returns { content, hash } where hash is formatted as "sha256:<hex>".
|
|
12
|
+
* @throws If the file cannot be read.
|
|
13
|
+
*/
|
|
14
|
+
export declare function read_legal_doc(doc_path: string): ReadDocResult;
|
|
15
|
+
//# sourceMappingURL=legal_docs_reader.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legal_docs_reader.server.d.ts","sourceRoot":"","sources":["../../../src/lib/legal/legal_docs_reader.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AASrB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAS9D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// file_description: server-only utility that reads a legal document from disk and returns its content + SHA-256 hash
|
|
2
|
+
// section: server-only-guard
|
|
3
|
+
import 'server-only';
|
|
4
|
+
// section: imports
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { createHash } from 'crypto';
|
|
8
|
+
// section: exports
|
|
9
|
+
/**
|
|
10
|
+
* Reads a legal document from the filesystem and returns its text content
|
|
11
|
+
* together with a deterministic SHA-256 hash of that content.
|
|
12
|
+
*
|
|
13
|
+
* @param doc_path - Absolute path, or a path relative to process.cwd().
|
|
14
|
+
* @returns { content, hash } where hash is formatted as "sha256:<hex>".
|
|
15
|
+
* @throws If the file cannot be read.
|
|
16
|
+
*/
|
|
17
|
+
export function read_legal_doc(doc_path) {
|
|
18
|
+
const abs_path = path.isAbsolute(doc_path)
|
|
19
|
+
? doc_path
|
|
20
|
+
: path.join(process.cwd(), doc_path);
|
|
21
|
+
const content = fs.readFileSync(abs_path, 'utf-8');
|
|
22
|
+
const hex = createHash('sha256').update(content).digest('hex');
|
|
23
|
+
return { content, hash: `sha256:${hex}` };
|
|
24
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write legal acceptance records. Call from:
|
|
3
|
+
* - registration_service (bundled with register POST, pre-session)
|
|
4
|
+
* - legal_docs_accept route (authenticated, post-login)
|
|
5
|
+
*
|
|
6
|
+
* Inserts one row per doc into hazo_legal_acceptances (audit history) and
|
|
7
|
+
* merges the result into the denormalised hazo_users.legal_acceptance JSONB
|
|
8
|
+
* column for fast "has this user accepted the current version?" queries.
|
|
9
|
+
*/
|
|
10
|
+
export declare function write_legal_acceptance(adapter: any, user_id: string, accepted: Record<string, {
|
|
11
|
+
hash: string;
|
|
12
|
+
}>, ip: string | null, user_agent: string | null): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Publish a doc version as the new required version (admin action).
|
|
15
|
+
* Upserts hazo_legal_doc_versions keyed on doc_key.
|
|
16
|
+
*/
|
|
17
|
+
export declare function publish_doc_version(adapter: any, doc_key: string, required_hash: string, published_by_user_id: string): Promise<{
|
|
18
|
+
published_at: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Return required version info keyed by doc_key.
|
|
22
|
+
*/
|
|
23
|
+
export declare function get_required_versions(adapter: any, doc_keys: string[]): Promise<Record<string, {
|
|
24
|
+
required_hash: string;
|
|
25
|
+
published_at: string;
|
|
26
|
+
}>>;
|
|
27
|
+
/**
|
|
28
|
+
* Return acceptance history for a user across all doc keys, newest first.
|
|
29
|
+
*/
|
|
30
|
+
export declare function get_user_acceptance_history(adapter: any, user_id: string): Promise<Array<{
|
|
31
|
+
doc_key: string;
|
|
32
|
+
doc_hash: string;
|
|
33
|
+
accepted_at: string;
|
|
34
|
+
ip: string | null;
|
|
35
|
+
user_agent: string | null;
|
|
36
|
+
}>>;
|
|
37
|
+
/**
|
|
38
|
+
* Count how many users have accepted the current required hash for a doc key.
|
|
39
|
+
* Returns { current, total } where current is users on the required_hash and
|
|
40
|
+
* total is all users in the system (including those with no legal_acceptance data).
|
|
41
|
+
*
|
|
42
|
+
* Note: This performs an in-process scan over all users. For large user bases
|
|
43
|
+
* consider a dedicated SQL query in a future optimisation.
|
|
44
|
+
*/
|
|
45
|
+
export declare function get_compliance_count(adapter: any, doc_key: string, required_hash: string): Promise<{
|
|
46
|
+
current: number;
|
|
47
|
+
total: number;
|
|
48
|
+
}>;
|
|
49
|
+
//# sourceMappingURL=legal_docs_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legal_docs_service.d.ts","sourceRoot":"","sources":["../../../src/lib/legal/legal_docs_service.ts"],"names":[],"mappings":"AAaA;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1C,EAAE,EAAE,MAAM,GAAG,IAAI,EACjB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,OAAO,CAAC,IAAI,CAAC,CAwCf;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,CA2BnC;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,GAAG,EACZ,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAoB1E;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,KAAK,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC,CAAC,CAeF;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAkB7C"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// file_description: service functions for the legal document acceptance system
|
|
2
|
+
// section: imports
|
|
3
|
+
import { createCrudService } from 'hazo_connect/server';
|
|
4
|
+
// section: helpers
|
|
5
|
+
function generate_id() {
|
|
6
|
+
return crypto.randomUUID();
|
|
7
|
+
}
|
|
8
|
+
// section: exports
|
|
9
|
+
/**
|
|
10
|
+
* Write legal acceptance records. Call from:
|
|
11
|
+
* - registration_service (bundled with register POST, pre-session)
|
|
12
|
+
* - legal_docs_accept route (authenticated, post-login)
|
|
13
|
+
*
|
|
14
|
+
* Inserts one row per doc into hazo_legal_acceptances (audit history) and
|
|
15
|
+
* merges the result into the denormalised hazo_users.legal_acceptance JSONB
|
|
16
|
+
* column for fast "has this user accepted the current version?" queries.
|
|
17
|
+
*/
|
|
18
|
+
export async function write_legal_acceptance(adapter, user_id, accepted, ip, user_agent) {
|
|
19
|
+
var _a;
|
|
20
|
+
const now = new Date().toISOString();
|
|
21
|
+
// 1. Insert one history row per doc
|
|
22
|
+
const history_service = createCrudService(adapter, 'hazo_legal_acceptances');
|
|
23
|
+
for (const [doc_key, { hash }] of Object.entries(accepted)) {
|
|
24
|
+
await history_service.insert({
|
|
25
|
+
id: generate_id(),
|
|
26
|
+
user_id,
|
|
27
|
+
doc_key,
|
|
28
|
+
doc_hash: hash,
|
|
29
|
+
accepted_at: now,
|
|
30
|
+
ip,
|
|
31
|
+
user_agent,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// 2. Merge into denormalized JSONB on hazo_users
|
|
35
|
+
const users_service = createCrudService(adapter, 'hazo_users');
|
|
36
|
+
const rows = await users_service.findBy({ id: user_id });
|
|
37
|
+
const existing_raw = (_a = rows[0]) === null || _a === void 0 ? void 0 : _a.legal_acceptance;
|
|
38
|
+
let existing = {};
|
|
39
|
+
if (existing_raw) {
|
|
40
|
+
try {
|
|
41
|
+
existing = typeof existing_raw === 'string'
|
|
42
|
+
? JSON.parse(existing_raw)
|
|
43
|
+
: existing_raw;
|
|
44
|
+
}
|
|
45
|
+
catch ( /* corrupt — start fresh */_b) { /* corrupt — start fresh */ }
|
|
46
|
+
}
|
|
47
|
+
const updated = Object.assign({}, existing);
|
|
48
|
+
for (const [doc_key, { hash }] of Object.entries(accepted)) {
|
|
49
|
+
updated[doc_key] = { hash, accepted_at: now, ip, user_agent };
|
|
50
|
+
}
|
|
51
|
+
await users_service.updateById(user_id, {
|
|
52
|
+
legal_acceptance: JSON.stringify(updated),
|
|
53
|
+
changed_at: now,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Publish a doc version as the new required version (admin action).
|
|
58
|
+
* Upserts hazo_legal_doc_versions keyed on doc_key.
|
|
59
|
+
*/
|
|
60
|
+
export async function publish_doc_version(adapter, doc_key, required_hash, published_by_user_id) {
|
|
61
|
+
const now = new Date().toISOString();
|
|
62
|
+
// createCrudService with doc_key as primary key so updateById works correctly
|
|
63
|
+
const versions_service = createCrudService(adapter, 'hazo_legal_doc_versions', {
|
|
64
|
+
primaryKeys: ['doc_key'],
|
|
65
|
+
autoId: false,
|
|
66
|
+
});
|
|
67
|
+
const existing = await versions_service.findBy({ doc_key });
|
|
68
|
+
if (existing.length > 0) {
|
|
69
|
+
await versions_service.updateById(doc_key, {
|
|
70
|
+
required_hash,
|
|
71
|
+
published_at: now,
|
|
72
|
+
published_by_user_id,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
await versions_service.insert({
|
|
77
|
+
doc_key,
|
|
78
|
+
required_hash,
|
|
79
|
+
published_at: now,
|
|
80
|
+
published_by_user_id,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return { published_at: now };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Return required version info keyed by doc_key.
|
|
87
|
+
*/
|
|
88
|
+
export async function get_required_versions(adapter, doc_keys) {
|
|
89
|
+
if (doc_keys.length === 0)
|
|
90
|
+
return {};
|
|
91
|
+
const versions_service = createCrudService(adapter, 'hazo_legal_doc_versions', {
|
|
92
|
+
primaryKeys: ['doc_key'],
|
|
93
|
+
autoId: false,
|
|
94
|
+
});
|
|
95
|
+
const rows = await versions_service.list((qb) => qb.whereIn('doc_key', doc_keys).select(['doc_key', 'required_hash', 'published_at']));
|
|
96
|
+
const result = {};
|
|
97
|
+
for (const row of rows) {
|
|
98
|
+
result[String(row.doc_key)] = {
|
|
99
|
+
required_hash: String(row.required_hash),
|
|
100
|
+
published_at: String(row.published_at),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Return acceptance history for a user across all doc keys, newest first.
|
|
107
|
+
*/
|
|
108
|
+
export async function get_user_acceptance_history(adapter, user_id) {
|
|
109
|
+
const history_service = createCrudService(adapter, 'hazo_legal_acceptances');
|
|
110
|
+
return history_service.list((qb) => qb
|
|
111
|
+
.where('user_id', 'eq', user_id)
|
|
112
|
+
.select(['doc_key', 'doc_hash', 'accepted_at', 'ip', 'user_agent'])
|
|
113
|
+
.order('accepted_at', 'desc'));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Count how many users have accepted the current required hash for a doc key.
|
|
117
|
+
* Returns { current, total } where current is users on the required_hash and
|
|
118
|
+
* total is all users in the system (including those with no legal_acceptance data).
|
|
119
|
+
*
|
|
120
|
+
* Note: This performs an in-process scan over all users. For large user bases
|
|
121
|
+
* consider a dedicated SQL query in a future optimisation.
|
|
122
|
+
*/
|
|
123
|
+
export async function get_compliance_count(adapter, doc_key, required_hash) {
|
|
124
|
+
var _a, _b;
|
|
125
|
+
const users_service = createCrudService(adapter, 'hazo_users');
|
|
126
|
+
const all_users = await users_service.list((qb) => qb.select(['id', 'legal_acceptance']));
|
|
127
|
+
let current = 0;
|
|
128
|
+
for (const user of all_users) {
|
|
129
|
+
let map = {};
|
|
130
|
+
try {
|
|
131
|
+
map = typeof user.legal_acceptance === 'string'
|
|
132
|
+
? JSON.parse(user.legal_acceptance)
|
|
133
|
+
: ((_a = user.legal_acceptance) !== null && _a !== void 0 ? _a : {});
|
|
134
|
+
}
|
|
135
|
+
catch ( /* ignore corrupt rows */_c) { /* ignore corrupt rows */ }
|
|
136
|
+
if (((_b = map[doc_key]) === null || _b === void 0 ? void 0 : _b.hash) === required_hash)
|
|
137
|
+
current++;
|
|
138
|
+
}
|
|
139
|
+
return { current, total: all_users.length };
|
|
140
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface LegalDocConfig {
|
|
2
|
+
key: string;
|
|
3
|
+
title: string;
|
|
4
|
+
path: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LegalDocsConfig {
|
|
7
|
+
docs: LegalDocConfig[];
|
|
8
|
+
display_mode: 'separate' | 'combined';
|
|
9
|
+
}
|
|
10
|
+
export interface LegalDoc {
|
|
11
|
+
key: string;
|
|
12
|
+
title: string;
|
|
13
|
+
content: string;
|
|
14
|
+
hash: string;
|
|
15
|
+
required_hash: string | null;
|
|
16
|
+
required_published_at: string | null;
|
|
17
|
+
}
|
|
18
|
+
export interface LegalAcceptanceRecord {
|
|
19
|
+
hash: string;
|
|
20
|
+
accepted_at: string;
|
|
21
|
+
ip: string | null;
|
|
22
|
+
user_agent: string | null;
|
|
23
|
+
}
|
|
24
|
+
export type LegalAcceptanceMap = Record<string, LegalAcceptanceRecord>;
|
|
25
|
+
//# sourceMappingURL=legal_docs_types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legal_docs_types.d.ts","sourceRoot":"","sources":["../../../src/lib/legal/legal_docs_types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,YAAY,EAAE,UAAU,GAAG,UAAU,CAAC;CACvC;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAGD,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC"}
|
|
@@ -13,14 +13,11 @@ export type LoginConfig = {
|
|
|
13
13
|
createAccountPath: string;
|
|
14
14
|
createAccountLabel: string;
|
|
15
15
|
showCreateAccountLink: boolean;
|
|
16
|
+
imageSrc: string;
|
|
17
|
+
imageAlt: string;
|
|
18
|
+
imageBackgroundColor: string;
|
|
16
19
|
/** OAuth configuration */
|
|
17
20
|
oauth: OAuthConfig;
|
|
18
|
-
/** Whether the OTP sign-in link is shown below the login form */
|
|
19
|
-
otpSigninEnabled: boolean;
|
|
20
|
-
/** Label for the OTP sign-in link */
|
|
21
|
-
otpSigninLabel: string;
|
|
22
|
-
/** href for the OTP sign-in link */
|
|
23
|
-
otpSigninHref: string;
|
|
24
21
|
};
|
|
25
22
|
/**
|
|
26
23
|
* Reads login layout configuration from hazo_auth_config.ini file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/login_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAKrB,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"login_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/login_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAKrB,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAM3E,MAAM,MAAM,WAAW,GAAG;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,0BAA0B;IAC1B,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAyE9C"}
|
|
@@ -5,6 +5,8 @@ import "server-only";
|
|
|
5
5
|
import { get_config_value, get_config_value_allow_empty } from "./config/config_loader.server.js";
|
|
6
6
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
7
7
|
import { get_oauth_config } from "./oauth_config.server.js";
|
|
8
|
+
// Assets served via the package's own API route — no manual copy needed.
|
|
9
|
+
const DEFAULT_LOGIN_IMAGE_PATH = "/api/hazo_auth/assets/login_default.jpg";
|
|
8
10
|
// section: helpers
|
|
9
11
|
/**
|
|
10
12
|
* Reads login layout configuration from hazo_auth_config.ini file
|
|
@@ -26,12 +28,14 @@ export function get_login_config() {
|
|
|
26
28
|
const showCreateAccountLink = get_config_value(section, "show_create_account_link", "true") === "true";
|
|
27
29
|
// Get shared already logged in config
|
|
28
30
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
31
|
+
// Read image configuration
|
|
32
|
+
// If not set in config, falls back to default path-based image
|
|
33
|
+
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
34
|
+
const imageSrc = get_config_value(section, "image_src", DEFAULT_LOGIN_IMAGE_PATH);
|
|
35
|
+
const imageAlt = get_config_value(section, "image_alt", "Secure login illustration");
|
|
36
|
+
const imageBackgroundColor = get_config_value(section, "image_background_color", "#f1f5f9");
|
|
29
37
|
// Get OAuth configuration
|
|
30
38
|
const oauth = get_oauth_config();
|
|
31
|
-
// OTP sign-in link
|
|
32
|
-
const otpSigninEnabled = get_config_value(section, "otp_signin_enabled", "false") === "true";
|
|
33
|
-
const otpSigninLabel = get_config_value(section, "otp_signin_label", "Sign in with email code");
|
|
34
|
-
const otpSigninHref = get_config_value(section, "otp_signin_href", "/hazo_auth/otp");
|
|
35
39
|
return {
|
|
36
40
|
redirectRoute,
|
|
37
41
|
successMessage,
|
|
@@ -45,9 +49,9 @@ export function get_login_config() {
|
|
|
45
49
|
createAccountPath,
|
|
46
50
|
createAccountLabel,
|
|
47
51
|
showCreateAccountLink,
|
|
52
|
+
imageSrc,
|
|
53
|
+
imageAlt,
|
|
54
|
+
imageBackgroundColor,
|
|
48
55
|
oauth,
|
|
49
|
-
otpSigninEnabled,
|
|
50
|
-
otpSigninLabel,
|
|
51
|
-
otpSigninHref,
|
|
52
56
|
};
|
|
53
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"my_settings_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/my_settings_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAYrB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE;QACV,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,mBAAmB,EAAE,OAAO,CAAC;KAC9B,CAAC;IACF,oBAAoB,EAAE;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,cAAc,EAAE,OAAO,CAAC;QACxB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,cAAc,EAAE;QACd,kBAAkB,EAAE,OAAO,CAAC;QAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,4BAA4B,EAAE,UAAU,GAAG,SAAS,CAAC;QACrD,4BAA4B,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;QACtD,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QACR,6BAA6B,EAAE,MAAM,CAAC;QACtC,sBAAsB,EAAE,MAAM,CAAC;QAC/B,2BAA2B,EAAE,MAAM,CAAC;QACpC,uBAAuB,EAAE,MAAM,CAAC;KACjC,CAAC;IACF,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;QAClC,uBAAuB,EAAE,MAAM,CAAC;QAChC,0BAA0B,EAAE,MAAM,CAAC;QACnC,0BAA0B,EAAE,MAAM,CAAC;QACnC,+BAA+B,EAAE,MAAM,CAAC;QACxC,4BAA4B,EAAE,MAAM,CAAC;KACtC,CAAC;IACF,SAAS,EAAE;QACT,wBAAwB,EAAE,MAAM,EAAE,CAAC;QACnC,wBAAwB,EAAE,MAAM,EAAE,CAAC;KACpC,CAAC;CACH,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,
|
|
1
|
+
{"version":3,"file":"my_settings_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/my_settings_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAYrB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE;QACV,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,mBAAmB,EAAE,OAAO,CAAC;KAC9B,CAAC;IACF,oBAAoB,EAAE;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,cAAc,EAAE,OAAO,CAAC;QACxB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,cAAc,EAAE;QACd,kBAAkB,EAAE,OAAO,CAAC;QAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,4BAA4B,EAAE,UAAU,GAAG,SAAS,CAAC;QACrD,4BAA4B,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;QACtD,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QACR,6BAA6B,EAAE,MAAM,CAAC;QACtC,sBAAsB,EAAE,MAAM,CAAC;QAC/B,2BAA2B,EAAE,MAAM,CAAC;QACpC,uBAAuB,EAAE,MAAM,CAAC;KACjC,CAAC;IACF,OAAO,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;QAClC,uBAAuB,EAAE,MAAM,CAAC;QAChC,0BAA0B,EAAE,MAAM,CAAC;QACnC,0BAA0B,EAAE,MAAM,CAAC;QACnC,+BAA+B,EAAE,MAAM,CAAC;QACxC,4BAA4B,EAAE,MAAM,CAAC;KACtC,CAAC;IACF,SAAS,EAAE;QACT,wBAAwB,EAAE,MAAM,EAAE,CAAC;QACnC,wBAAwB,EAAE,MAAM,EAAE,CAAC;KACpC,CAAC;CACH,CAAC;AAGF;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAyDzD"}
|
|
@@ -28,6 +28,7 @@ export function get_my_settings_config() {
|
|
|
28
28
|
const uiSizes = get_ui_sizes_config();
|
|
29
29
|
const fileTypes = get_file_types_config();
|
|
30
30
|
// Read optional labels with defaults
|
|
31
|
+
const heading = get_config_value(section, "heading", "Account Settings");
|
|
31
32
|
const subHeading = get_config_value(section, "sub_heading", "Manage your profile, password, and email preferences.");
|
|
32
33
|
const profilePhotoLabel = get_config_value(section, "profile_photo_label", "Profile Photo");
|
|
33
34
|
const profilePhotoRecommendation = get_config_value(section, "profile_photo_recommendation", "Recommended size: 200x200px. JPG, PNG.");
|
|
@@ -46,6 +47,7 @@ export function get_my_settings_config() {
|
|
|
46
47
|
userFields,
|
|
47
48
|
passwordRequirements,
|
|
48
49
|
profilePicture,
|
|
50
|
+
heading,
|
|
49
51
|
subHeading,
|
|
50
52
|
profilePhotoLabel,
|
|
51
53
|
profilePhotoRecommendation,
|
|
@@ -2,20 +2,12 @@ import "server-only";
|
|
|
2
2
|
export type OAuthConfig = {
|
|
3
3
|
/** Enable Google OAuth login */
|
|
4
4
|
enable_google: boolean;
|
|
5
|
-
/** Enable Facebook OAuth login */
|
|
6
|
-
enable_facebook: boolean;
|
|
7
5
|
/** Enable traditional email/password login */
|
|
8
6
|
enable_email_password: boolean;
|
|
9
7
|
/** Auto-link Google login to existing unverified email/password accounts */
|
|
10
8
|
auto_link_unverified_accounts: boolean;
|
|
11
|
-
/** Auto-link Google login to existing unverified email/password accounts (per-provider override) */
|
|
12
|
-
auto_link_unverified_accounts_google: boolean;
|
|
13
|
-
/** Auto-link Facebook login to existing unverified email/password accounts */
|
|
14
|
-
auto_link_unverified_accounts_facebook: boolean;
|
|
15
9
|
/** Text displayed on the Google sign-in button */
|
|
16
10
|
google_button_text: string;
|
|
17
|
-
/** Text displayed on the Facebook sign-in button */
|
|
18
|
-
facebook_button_text: string;
|
|
19
11
|
/** Text displayed on the divider between OAuth and email/password form */
|
|
20
12
|
oauth_divider_text: string;
|
|
21
13
|
/** NextAuth signIn page path */
|
|
@@ -30,10 +22,14 @@ export type OAuthConfig = {
|
|
|
30
22
|
skip_invitation_check: boolean;
|
|
31
23
|
/** Redirect when skip_invitation_check=true and user has no scope */
|
|
32
24
|
no_scope_redirect: string;
|
|
33
|
-
/** Facebook
|
|
34
|
-
|
|
35
|
-
/** Facebook App
|
|
36
|
-
|
|
25
|
+
/** Enable Facebook OAuth login */
|
|
26
|
+
enable_facebook_oauth: boolean;
|
|
27
|
+
/** Facebook App ID (env: HAZO_AUTH_FACEBOOK_APP_ID overrides config) */
|
|
28
|
+
facebook_app_id: string;
|
|
29
|
+
/** Facebook App Secret (env: HAZO_AUTH_FACEBOOK_APP_SECRET overrides config) */
|
|
30
|
+
facebook_app_secret: string;
|
|
31
|
+
/** Text displayed on the Facebook sign-in button */
|
|
32
|
+
facebook_button_text: string;
|
|
37
33
|
};
|
|
38
34
|
/**
|
|
39
35
|
* Reads OAuth configuration from hazo_auth_config.ini file
|
|
@@ -51,9 +47,4 @@ export declare function is_google_oauth_enabled(): boolean;
|
|
|
51
47
|
* @returns true if email/password login is enabled in config
|
|
52
48
|
*/
|
|
53
49
|
export declare function is_email_password_enabled(): boolean;
|
|
54
|
-
/**
|
|
55
|
-
* Helper to check if Facebook OAuth is enabled and credentials are present
|
|
56
|
-
* @returns true if Facebook OAuth is enabled and env vars are set
|
|
57
|
-
*/
|
|
58
|
-
export declare function is_facebook_oauth_enabled(): boolean;
|
|
59
50
|
//# sourceMappingURL=oauth_config.server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/oauth_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAOrB,MAAM,MAAM,WAAW,GAAG;IACxB,gCAAgC;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,
|
|
1
|
+
{"version":3,"file":"oauth_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/oauth_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAOrB,MAAM,MAAM,WAAW,GAAG;IACxB,gCAAgC;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4EAA4E;IAC5E,6BAA6B,EAAE,OAAO,CAAC;IACvC,kDAAkD;IAClD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,eAAe,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,gBAAgB,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,qEAAqE;IACrE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wEAAwE;IACxE,eAAe,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oDAAoD;IACpD,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAMF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAwG9C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD"}
|