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
|
@@ -8,7 +8,7 @@ const GoogleProvider = (GoogleProviderImport as any).default || GoogleProviderIm
|
|
|
8
8
|
import FacebookProviderImport from "next-auth/providers/facebook";
|
|
9
9
|
const FacebookProvider = (FacebookProviderImport as any).default || FacebookProviderImport;
|
|
10
10
|
import { get_oauth_config } from "../oauth_config.server.js";
|
|
11
|
-
import { handle_google_oauth_login
|
|
11
|
+
import { handle_google_oauth_login } from "../services/oauth_service.js";
|
|
12
12
|
import { get_hazo_connect_instance } from "../hazo_connect_instance.server.js";
|
|
13
13
|
import { create_app_logger } from "../app_logger.js";
|
|
14
14
|
|
|
@@ -37,13 +37,6 @@ export type NextAuthCallbackProfile = {
|
|
|
37
37
|
email_verified?: boolean;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
export type FacebookCallbackProfile = {
|
|
41
|
-
id?: string;
|
|
42
|
-
name?: string;
|
|
43
|
-
email?: string;
|
|
44
|
-
picture?: { data?: { url: string } } | string;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
40
|
// section: config
|
|
48
41
|
/**
|
|
49
42
|
* Gets NextAuth.js configuration with enabled OAuth providers
|
|
@@ -76,17 +69,12 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
76
69
|
}
|
|
77
70
|
}
|
|
78
71
|
|
|
79
|
-
// Add Facebook provider if enabled
|
|
80
|
-
if (oauth_config.
|
|
72
|
+
// Add Facebook provider if enabled
|
|
73
|
+
if (oauth_config.enable_facebook_oauth && oauth_config.facebook_app_id) {
|
|
81
74
|
providers.push(
|
|
82
75
|
FacebookProvider({
|
|
83
|
-
clientId: oauth_config.
|
|
84
|
-
clientSecret: oauth_config.
|
|
85
|
-
authorization: {
|
|
86
|
-
params: {
|
|
87
|
-
scope: "email,public_profile",
|
|
88
|
-
},
|
|
89
|
-
},
|
|
76
|
+
clientId: oauth_config.facebook_app_id,
|
|
77
|
+
clientSecret: oauth_config.facebook_app_secret,
|
|
90
78
|
})
|
|
91
79
|
);
|
|
92
80
|
}
|
|
@@ -109,10 +97,10 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
109
97
|
|
|
110
98
|
// Always redirect to our custom callback after sign-in to set hazo_auth cookies
|
|
111
99
|
// The callbackUrl from signIn() comes through as `url`
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
100
|
+
if (
|
|
101
|
+
url.includes("/api/hazo_auth/oauth/google/callback") ||
|
|
102
|
+
url.includes("/api/hazo_auth/oauth/facebook/callback")
|
|
103
|
+
) {
|
|
116
104
|
return url;
|
|
117
105
|
}
|
|
118
106
|
|
|
@@ -125,6 +113,9 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
125
113
|
}
|
|
126
114
|
|
|
127
115
|
// Default: redirect to our custom OAuth callback to set cookies
|
|
116
|
+
if (url.includes("facebook")) {
|
|
117
|
+
return `${baseUrl}/api/hazo_auth/oauth/facebook/callback`;
|
|
118
|
+
}
|
|
128
119
|
return `${baseUrl}/api/hazo_auth/oauth/google/callback`;
|
|
129
120
|
},
|
|
130
121
|
/**
|
|
@@ -192,48 +183,27 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
192
183
|
|
|
193
184
|
if (account?.provider === "facebook" && profile) {
|
|
194
185
|
try {
|
|
195
|
-
const fbProfile = profile as
|
|
186
|
+
const fbProfile = profile as NextAuthCallbackProfile;
|
|
196
187
|
const hazoConnect = get_hazo_connect_instance();
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
// Resolve profile picture URL from Facebook's nested structure
|
|
200
|
-
let fb_picture_url: string | undefined;
|
|
201
|
-
if (fbProfile.picture) {
|
|
202
|
-
if (typeof fbProfile.picture === "string") {
|
|
203
|
-
fb_picture_url = fbProfile.picture;
|
|
204
|
-
} else if (fbProfile.picture?.data?.url) {
|
|
205
|
-
fb_picture_url = fbProfile.picture.data.url;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (!fb_picture_url && user.image) {
|
|
209
|
-
fb_picture_url = user.image ?? undefined;
|
|
210
|
-
}
|
|
188
|
+
const { handle_facebook_oauth_login } = await import("../services/oauth_service");
|
|
211
189
|
|
|
212
190
|
logger.info("nextauth_facebook_signin_attempt", {
|
|
213
191
|
email: user.email,
|
|
214
|
-
facebook_id:
|
|
215
|
-
name: user.name,
|
|
192
|
+
facebook_id: account.providerAccountId,
|
|
216
193
|
});
|
|
217
194
|
|
|
218
|
-
const result = await handle_facebook_oauth_login(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
);
|
|
195
|
+
const result = await handle_facebook_oauth_login(hazoConnect, {
|
|
196
|
+
facebook_id: account.providerAccountId,
|
|
197
|
+
email: user.email || fbProfile.email || "",
|
|
198
|
+
name: user.name || fbProfile.name || undefined,
|
|
199
|
+
profile_picture_url: user.image || undefined,
|
|
200
|
+
// Facebook's email_verified is not exposed in the profile; default to false
|
|
201
|
+
// for safety — the user will be auto-verified if email matches a verified hazo user.
|
|
202
|
+
email_verified: false,
|
|
203
|
+
});
|
|
228
204
|
|
|
229
205
|
if (!result.success) {
|
|
230
|
-
logger.error("nextauth_facebook_signin_failed", {
|
|
231
|
-
email: user.email,
|
|
232
|
-
error: result.error,
|
|
233
|
-
});
|
|
234
|
-
if (result.error === "link_blocked_unverified") {
|
|
235
|
-
return `/hazo_auth/login?error=link_blocked_unverified`;
|
|
236
|
-
}
|
|
206
|
+
logger.error("nextauth_facebook_signin_failed", { email: user.email, error: result.error });
|
|
237
207
|
return false;
|
|
238
208
|
}
|
|
239
209
|
|
|
@@ -244,16 +214,10 @@ export function get_nextauth_config(): AuthOptions {
|
|
|
244
214
|
was_linked: result.was_linked,
|
|
245
215
|
});
|
|
246
216
|
|
|
247
|
-
// Store user_id in account for the JWT callback to pick up
|
|
248
217
|
(account as Record<string, unknown>).hazo_user_id = result.user_id;
|
|
249
|
-
|
|
250
218
|
return true;
|
|
251
|
-
} catch (
|
|
252
|
-
|
|
253
|
-
logger.error("nextauth_facebook_signin_exception", {
|
|
254
|
-
email: user.email,
|
|
255
|
-
error: errorMessage,
|
|
256
|
-
});
|
|
219
|
+
} catch (err) {
|
|
220
|
+
logger.error("nextauth_facebook_signin_exception", { error: String(err) });
|
|
257
221
|
return false;
|
|
258
222
|
}
|
|
259
223
|
}
|
|
@@ -321,9 +285,5 @@ export function has_oauth_providers(): boolean {
|
|
|
321
285
|
if (has_google_credentials) return true;
|
|
322
286
|
}
|
|
323
287
|
|
|
324
|
-
if (oauth_config.enable_facebook && oauth_config.facebook_client_id && oauth_config.facebook_client_secret) {
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
288
|
return false;
|
|
329
289
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
PermissionError,
|
|
11
11
|
type TenantAuthOptions,
|
|
12
12
|
type TenantAuthResult,
|
|
13
|
-
type
|
|
13
|
+
type TenantOrganization,
|
|
14
14
|
type HazoAuthUser,
|
|
15
15
|
type ScopeDetails,
|
|
16
16
|
type ScopeAccessInfo,
|
|
@@ -27,19 +27,19 @@ export type AuthenticatedTenantAuth = {
|
|
|
27
27
|
permissions: string[];
|
|
28
28
|
permission_ok: boolean;
|
|
29
29
|
missing_permissions?: string[];
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
organization: TenantOrganization | null;
|
|
31
|
+
organization_id: string | null;
|
|
32
32
|
user_scopes: ScopeDetails[];
|
|
33
33
|
scope_ok?: boolean;
|
|
34
34
|
scope_access_via?: ScopeAccessInfo;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* Authenticated branch with guaranteed non-null
|
|
38
|
+
* Authenticated branch with guaranteed non-null organization
|
|
39
39
|
*/
|
|
40
|
-
export type
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
export type AuthenticatedTenantAuthWithOrg = AuthenticatedTenantAuth & {
|
|
41
|
+
organization: TenantOrganization;
|
|
42
|
+
organization_id: string;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -48,8 +48,8 @@ export type AuthenticatedTenantAuthWithSelectedScope = AuthenticatedTenantAuth &
|
|
|
48
48
|
*/
|
|
49
49
|
export type WithAuthOptions = TenantAuthOptions & {
|
|
50
50
|
/**
|
|
51
|
-
* If true, requires
|
|
52
|
-
* Narrows auth type to
|
|
51
|
+
* If true, requires organization context (403 if missing)
|
|
52
|
+
* Narrows auth type to AuthenticatedTenantAuthWithOrg
|
|
53
53
|
*/
|
|
54
54
|
require_tenant?: boolean;
|
|
55
55
|
};
|
|
@@ -75,7 +75,7 @@ type AuthenticatedHandler<TParams> = (
|
|
|
75
75
|
*/
|
|
76
76
|
type AuthenticatedTenantHandler<TParams> = (
|
|
77
77
|
request: NextRequest,
|
|
78
|
-
auth:
|
|
78
|
+
auth: AuthenticatedTenantAuthWithOrg,
|
|
79
79
|
params: TParams,
|
|
80
80
|
) => Promise<NextResponse> | NextResponse;
|
|
81
81
|
|
|
@@ -138,7 +138,7 @@ async function resolve_params<TParams>(
|
|
|
138
138
|
*
|
|
139
139
|
* - Calls `hazo_get_tenant_auth` and returns 401 if not authenticated
|
|
140
140
|
* - Returns 403 if `required_permissions` are specified and not satisfied
|
|
141
|
-
* - Returns 403 if `require_tenant: true` and no
|
|
141
|
+
* - Returns 403 if `require_tenant: true` and no organization context
|
|
142
142
|
* - Resolves `await context.params` (Next.js 15 pattern)
|
|
143
143
|
* - Catches HazoAuthError, PermissionError, and unexpected errors
|
|
144
144
|
*
|
|
@@ -161,8 +161,8 @@ async function resolve_params<TParams>(
|
|
|
161
161
|
* // With tenant requirement
|
|
162
162
|
* export const GET = withAuth<{ id: string }>(
|
|
163
163
|
* async (request, auth, { id }) => {
|
|
164
|
-
* // auth.
|
|
165
|
-
* const data = await getData(auth.
|
|
164
|
+
* // auth.organization is guaranteed non-null
|
|
165
|
+
* const data = await getData(auth.organization.id, id);
|
|
166
166
|
* return NextResponse.json(data);
|
|
167
167
|
* },
|
|
168
168
|
* { require_tenant: true }
|
|
@@ -227,10 +227,10 @@ export function withAuth<TParams = Record<string, never>>(
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
// Check tenant requirement
|
|
230
|
-
if (options.require_tenant && !auth.
|
|
230
|
+
if (options.require_tenant && !auth.organization) {
|
|
231
231
|
return NextResponse.json(
|
|
232
232
|
{
|
|
233
|
-
error: "
|
|
233
|
+
error: "Organization context required",
|
|
234
234
|
code: "TENANT_REQUIRED",
|
|
235
235
|
},
|
|
236
236
|
{ status: 403 },
|
|
@@ -177,6 +177,14 @@ export const DEFAULT_OAUTH = {
|
|
|
177
177
|
skip_invitation_check: false,
|
|
178
178
|
/** Redirect when skip_invitation_check=true and user has no scope */
|
|
179
179
|
no_scope_redirect: "/",
|
|
180
|
+
/** Enable Facebook OAuth login (requires HAZO_AUTH_FACEBOOK_APP_ID and HAZO_AUTH_FACEBOOK_APP_SECRET env vars) */
|
|
181
|
+
enable_facebook_oauth: false,
|
|
182
|
+
/** Facebook App ID — set via env var HAZO_AUTH_FACEBOOK_APP_ID or config */
|
|
183
|
+
facebook_app_id: "",
|
|
184
|
+
/** Facebook App Secret — set via env var HAZO_AUTH_FACEBOOK_APP_SECRET or config */
|
|
185
|
+
facebook_app_secret: "",
|
|
186
|
+
/** Text displayed on the Facebook sign-in button */
|
|
187
|
+
facebook_button_text: "Continue with Facebook",
|
|
180
188
|
} as const;
|
|
181
189
|
|
|
182
190
|
// section: navbar
|
|
@@ -27,10 +27,10 @@ export const BASE_COOKIE_NAMES = {
|
|
|
27
27
|
USER_ID: "hazo_auth_user_id",
|
|
28
28
|
USER_EMAIL: "hazo_auth_user_email",
|
|
29
29
|
SESSION: "hazo_auth_session",
|
|
30
|
-
SESSION_KIND: "hazo_auth_session_kind", // v6.1: marks OTP-issued sessions so /me can apply sliding expiry
|
|
31
30
|
DEV_LOCK: "hazo_auth_dev_lock",
|
|
32
31
|
SCOPE_ID: "hazo_auth_scope_id", // v5.2: Tenant context cookie for multi-tenancy
|
|
33
32
|
ANON_ID: "hazo_auth_anon_id", // v5.2: Stable opaque per-visitor ID for anonymous flows (e.g. hazo_feedback)
|
|
33
|
+
SESSION_KIND: "hazo_auth_session_kind", // v5.4: Sign-in method identifier (e.g. "otp", "google", "password")
|
|
34
34
|
} as const;
|
|
35
35
|
|
|
36
36
|
// section: main_function
|
|
@@ -4,6 +4,12 @@ import "server-only";
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
7
|
+
import { get_config_value } from "./config/config_loader.server.js";
|
|
8
|
+
|
|
9
|
+
// Default image path - consuming apps should either:
|
|
10
|
+
// 1. Configure their own image_src in hazo_auth_config.ini
|
|
11
|
+
// 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
|
|
12
|
+
const DEFAULT_VERIFY_EMAIL_IMAGE_PATH = "/hazo_auth/images/verify_email_default.jpg";
|
|
7
13
|
|
|
8
14
|
// section: types
|
|
9
15
|
export type EmailVerificationConfig = {
|
|
@@ -12,6 +18,9 @@ export type EmailVerificationConfig = {
|
|
|
12
18
|
showReturnHomeButton: boolean;
|
|
13
19
|
returnHomeButtonLabel: string;
|
|
14
20
|
returnHomePath: string;
|
|
21
|
+
imageSrc: string;
|
|
22
|
+
imageAlt: string;
|
|
23
|
+
imageBackgroundColor: string;
|
|
15
24
|
};
|
|
16
25
|
|
|
17
26
|
// section: helpers
|
|
@@ -21,15 +30,40 @@ export type EmailVerificationConfig = {
|
|
|
21
30
|
* @returns Email verification configuration options
|
|
22
31
|
*/
|
|
23
32
|
export function get_email_verification_config(): EmailVerificationConfig {
|
|
33
|
+
const section = "hazo_auth__email_verification_layout";
|
|
34
|
+
|
|
24
35
|
// Get shared already logged in config
|
|
25
36
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
26
37
|
|
|
38
|
+
// Read image configuration
|
|
39
|
+
// If not set in config, falls back to default path-based image
|
|
40
|
+
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
41
|
+
const imageSrc = get_config_value(
|
|
42
|
+
section,
|
|
43
|
+
"image_src",
|
|
44
|
+
DEFAULT_VERIFY_EMAIL_IMAGE_PATH
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const imageAlt = get_config_value(
|
|
48
|
+
section,
|
|
49
|
+
"image_alt",
|
|
50
|
+
"Email verification illustration"
|
|
51
|
+
);
|
|
52
|
+
const imageBackgroundColor = get_config_value(
|
|
53
|
+
section,
|
|
54
|
+
"image_background_color",
|
|
55
|
+
"#f1f5f9"
|
|
56
|
+
);
|
|
57
|
+
|
|
27
58
|
return {
|
|
28
59
|
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
29
60
|
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
30
61
|
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
31
62
|
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
32
63
|
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
64
|
+
imageSrc,
|
|
65
|
+
imageAlt,
|
|
66
|
+
imageBackgroundColor,
|
|
33
67
|
};
|
|
34
68
|
}
|
|
35
69
|
|
|
@@ -4,6 +4,12 @@ import "server-only";
|
|
|
4
4
|
|
|
5
5
|
// section: imports
|
|
6
6
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
7
|
+
import { get_config_value } from "./config/config_loader.server.js";
|
|
8
|
+
|
|
9
|
+
// Default image path - consuming apps should either:
|
|
10
|
+
// 1. Configure their own image_src in hazo_auth_config.ini
|
|
11
|
+
// 2. Copy the default images from node_modules/hazo_auth/public/hazo_auth/images/ to their public folder
|
|
12
|
+
const DEFAULT_FORGOT_PASSWORD_IMAGE_PATH = "/hazo_auth/images/forgot_password_default.jpg";
|
|
7
13
|
|
|
8
14
|
// section: types
|
|
9
15
|
export type ForgotPasswordConfig = {
|
|
@@ -12,6 +18,9 @@ export type ForgotPasswordConfig = {
|
|
|
12
18
|
showReturnHomeButton: boolean;
|
|
13
19
|
returnHomeButtonLabel: string;
|
|
14
20
|
returnHomePath: string;
|
|
21
|
+
imageSrc: string;
|
|
22
|
+
imageAlt: string;
|
|
23
|
+
imageBackgroundColor: string;
|
|
15
24
|
};
|
|
16
25
|
|
|
17
26
|
// section: helpers
|
|
@@ -21,15 +30,40 @@ export type ForgotPasswordConfig = {
|
|
|
21
30
|
* @returns Forgot password configuration options
|
|
22
31
|
*/
|
|
23
32
|
export function get_forgot_password_config(): ForgotPasswordConfig {
|
|
33
|
+
const section = "hazo_auth__forgot_password_layout";
|
|
34
|
+
|
|
24
35
|
// Get shared already logged in config
|
|
25
36
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
26
37
|
|
|
38
|
+
// Read image configuration
|
|
39
|
+
// If not set in config, falls back to default path-based image
|
|
40
|
+
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
41
|
+
const imageSrc = get_config_value(
|
|
42
|
+
section,
|
|
43
|
+
"image_src",
|
|
44
|
+
DEFAULT_FORGOT_PASSWORD_IMAGE_PATH
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const imageAlt = get_config_value(
|
|
48
|
+
section,
|
|
49
|
+
"image_alt",
|
|
50
|
+
"Password recovery illustration"
|
|
51
|
+
);
|
|
52
|
+
const imageBackgroundColor = get_config_value(
|
|
53
|
+
section,
|
|
54
|
+
"image_background_color",
|
|
55
|
+
"#f1f5f9"
|
|
56
|
+
);
|
|
57
|
+
|
|
27
58
|
return {
|
|
28
59
|
alreadyLoggedInMessage: alreadyLoggedInConfig.message,
|
|
29
60
|
showLogoutButton: alreadyLoggedInConfig.showLogoutButton,
|
|
30
61
|
showReturnHomeButton: alreadyLoggedInConfig.showReturnHomeButton,
|
|
31
62
|
returnHomeButtonLabel: alreadyLoggedInConfig.returnHomeButtonLabel,
|
|
32
63
|
returnHomePath: alreadyLoggedInConfig.returnHomePath,
|
|
64
|
+
imageSrc,
|
|
65
|
+
imageAlt,
|
|
66
|
+
imageBackgroundColor,
|
|
33
67
|
};
|
|
34
68
|
}
|
|
35
69
|
|
|
@@ -7,6 +7,9 @@ import { get_config_value, get_config_value_allow_empty } from "./config/config_
|
|
|
7
7
|
import { get_already_logged_in_config } from "./already_logged_in_config.server.js";
|
|
8
8
|
import { get_oauth_config, type OAuthConfig } from "./oauth_config.server.js";
|
|
9
9
|
|
|
10
|
+
// Assets served via the package's own API route — no manual copy needed.
|
|
11
|
+
const DEFAULT_LOGIN_IMAGE_PATH = "/api/hazo_auth/assets/login_default.jpg";
|
|
12
|
+
|
|
10
13
|
// section: types
|
|
11
14
|
export type LoginConfig = {
|
|
12
15
|
redirectRoute?: string;
|
|
@@ -21,14 +24,11 @@ export type LoginConfig = {
|
|
|
21
24
|
createAccountPath: string;
|
|
22
25
|
createAccountLabel: string;
|
|
23
26
|
showCreateAccountLink: boolean;
|
|
27
|
+
imageSrc: string;
|
|
28
|
+
imageAlt: string;
|
|
29
|
+
imageBackgroundColor: string;
|
|
24
30
|
/** OAuth configuration */
|
|
25
31
|
oauth: OAuthConfig;
|
|
26
|
-
/** Whether the OTP sign-in link is shown below the login form */
|
|
27
|
-
otpSigninEnabled: boolean;
|
|
28
|
-
/** Label for the OTP sign-in link */
|
|
29
|
-
otpSigninLabel: string;
|
|
30
|
-
/** href for the OTP sign-in link */
|
|
31
|
-
otpSigninHref: string;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
// section: helpers
|
|
@@ -69,14 +69,29 @@ export function get_login_config(): LoginConfig {
|
|
|
69
69
|
// Get shared already logged in config
|
|
70
70
|
const alreadyLoggedInConfig = get_already_logged_in_config();
|
|
71
71
|
|
|
72
|
+
// Read image configuration
|
|
73
|
+
// If not set in config, falls back to default path-based image
|
|
74
|
+
// Consuming apps should copy images to public/hazo_auth/images/ or configure their own image_src
|
|
75
|
+
const imageSrc = get_config_value(
|
|
76
|
+
section,
|
|
77
|
+
"image_src",
|
|
78
|
+
DEFAULT_LOGIN_IMAGE_PATH
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const imageAlt = get_config_value(
|
|
82
|
+
section,
|
|
83
|
+
"image_alt",
|
|
84
|
+
"Secure login illustration"
|
|
85
|
+
);
|
|
86
|
+
const imageBackgroundColor = get_config_value(
|
|
87
|
+
section,
|
|
88
|
+
"image_background_color",
|
|
89
|
+
"#f1f5f9"
|
|
90
|
+
);
|
|
91
|
+
|
|
72
92
|
// Get OAuth configuration
|
|
73
93
|
const oauth = get_oauth_config();
|
|
74
94
|
|
|
75
|
-
// OTP sign-in link
|
|
76
|
-
const otpSigninEnabled = get_config_value(section, "otp_signin_enabled", "false") === "true";
|
|
77
|
-
const otpSigninLabel = get_config_value(section, "otp_signin_label", "Sign in with email code");
|
|
78
|
-
const otpSigninHref = get_config_value(section, "otp_signin_href", "/hazo_auth/otp");
|
|
79
|
-
|
|
80
95
|
return {
|
|
81
96
|
redirectRoute,
|
|
82
97
|
successMessage,
|
|
@@ -90,10 +105,10 @@ export function get_login_config(): LoginConfig {
|
|
|
90
105
|
createAccountPath,
|
|
91
106
|
createAccountLabel,
|
|
92
107
|
showCreateAccountLink,
|
|
108
|
+
imageSrc,
|
|
109
|
+
imageAlt,
|
|
110
|
+
imageBackgroundColor,
|
|
93
111
|
oauth,
|
|
94
|
-
otpSigninEnabled,
|
|
95
|
-
otpSigninLabel,
|
|
96
|
-
otpSigninHref,
|
|
97
112
|
};
|
|
98
113
|
}
|
|
99
114
|
|
|
@@ -34,6 +34,7 @@ export type MySettingsConfig = {
|
|
|
34
34
|
user_photo_default_priority2?: "library" | "gravatar";
|
|
35
35
|
library_photo_path: string;
|
|
36
36
|
};
|
|
37
|
+
heading?: string;
|
|
37
38
|
subHeading?: string;
|
|
38
39
|
profilePhotoLabel?: string;
|
|
39
40
|
profilePhotoRecommendation?: string;
|
|
@@ -94,6 +95,7 @@ export function get_my_settings_config(): MySettingsConfig {
|
|
|
94
95
|
const fileTypes = get_file_types_config();
|
|
95
96
|
|
|
96
97
|
// Read optional labels with defaults
|
|
98
|
+
const heading = get_config_value(section, "heading", "Account Settings");
|
|
97
99
|
const subHeading = get_config_value(section, "sub_heading", "Manage your profile, password, and email preferences.");
|
|
98
100
|
const profilePhotoLabel = get_config_value(section, "profile_photo_label", "Profile Photo");
|
|
99
101
|
const profilePhotoRecommendation = get_config_value(section, "profile_photo_recommendation", "Recommended size: 200x200px. JPG, PNG.");
|
|
@@ -113,6 +115,7 @@ export function get_my_settings_config(): MySettingsConfig {
|
|
|
113
115
|
userFields,
|
|
114
116
|
passwordRequirements,
|
|
115
117
|
profilePicture,
|
|
118
|
+
heading,
|
|
116
119
|
subHeading,
|
|
117
120
|
profilePhotoLabel,
|
|
118
121
|
profilePhotoRecommendation,
|
|
@@ -10,20 +10,12 @@ import { DEFAULT_OAUTH } from "./config/default_config.js";
|
|
|
10
10
|
export type OAuthConfig = {
|
|
11
11
|
/** Enable Google OAuth login */
|
|
12
12
|
enable_google: boolean;
|
|
13
|
-
/** Enable Facebook OAuth login */
|
|
14
|
-
enable_facebook: boolean;
|
|
15
13
|
/** Enable traditional email/password login */
|
|
16
14
|
enable_email_password: boolean;
|
|
17
15
|
/** Auto-link Google login to existing unverified email/password accounts */
|
|
18
16
|
auto_link_unverified_accounts: boolean;
|
|
19
|
-
/** Auto-link Google login to existing unverified email/password accounts (per-provider override) */
|
|
20
|
-
auto_link_unverified_accounts_google: boolean;
|
|
21
|
-
/** Auto-link Facebook login to existing unverified email/password accounts */
|
|
22
|
-
auto_link_unverified_accounts_facebook: boolean;
|
|
23
17
|
/** Text displayed on the Google sign-in button */
|
|
24
18
|
google_button_text: string;
|
|
25
|
-
/** Text displayed on the Facebook sign-in button */
|
|
26
|
-
facebook_button_text: string;
|
|
27
19
|
/** Text displayed on the divider between OAuth and email/password form */
|
|
28
20
|
oauth_divider_text: string;
|
|
29
21
|
/** NextAuth signIn page path */
|
|
@@ -38,10 +30,14 @@ export type OAuthConfig = {
|
|
|
38
30
|
skip_invitation_check: boolean;
|
|
39
31
|
/** Redirect when skip_invitation_check=true and user has no scope */
|
|
40
32
|
no_scope_redirect: string;
|
|
41
|
-
/** Facebook
|
|
42
|
-
|
|
43
|
-
/** Facebook App
|
|
44
|
-
|
|
33
|
+
/** Enable Facebook OAuth login */
|
|
34
|
+
enable_facebook_oauth: boolean;
|
|
35
|
+
/** Facebook App ID (env: HAZO_AUTH_FACEBOOK_APP_ID overrides config) */
|
|
36
|
+
facebook_app_id: string;
|
|
37
|
+
/** Facebook App Secret (env: HAZO_AUTH_FACEBOOK_APP_SECRET overrides config) */
|
|
38
|
+
facebook_app_secret: string;
|
|
39
|
+
/** Text displayed on the Facebook sign-in button */
|
|
40
|
+
facebook_button_text: string;
|
|
45
41
|
};
|
|
46
42
|
|
|
47
43
|
// section: constants
|
|
@@ -60,51 +56,24 @@ export function get_oauth_config(): OAuthConfig {
|
|
|
60
56
|
DEFAULT_OAUTH.enable_google
|
|
61
57
|
);
|
|
62
58
|
|
|
63
|
-
const enable_facebook = get_config_boolean(
|
|
64
|
-
SECTION_NAME,
|
|
65
|
-
"enable_facebook",
|
|
66
|
-
false
|
|
67
|
-
);
|
|
68
|
-
|
|
69
59
|
const enable_email_password = get_config_boolean(
|
|
70
60
|
SECTION_NAME,
|
|
71
61
|
"enable_email_password",
|
|
72
62
|
DEFAULT_OAUTH.enable_email_password
|
|
73
63
|
);
|
|
74
64
|
|
|
75
|
-
// Generic key (backward compat)
|
|
76
65
|
const auto_link_unverified_accounts = get_config_boolean(
|
|
77
66
|
SECTION_NAME,
|
|
78
67
|
"auto_link_unverified_accounts",
|
|
79
68
|
DEFAULT_OAUTH.auto_link_unverified_accounts
|
|
80
69
|
);
|
|
81
70
|
|
|
82
|
-
// Per-provider Google key (falls back to generic)
|
|
83
|
-
const auto_link_unverified_accounts_google = get_config_boolean(
|
|
84
|
-
SECTION_NAME,
|
|
85
|
-
"auto_link_unverified_accounts_google",
|
|
86
|
-
auto_link_unverified_accounts
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
// Per-provider Facebook key (defaults to false — don't auto-link Facebook unverified)
|
|
90
|
-
const auto_link_unverified_accounts_facebook = get_config_boolean(
|
|
91
|
-
SECTION_NAME,
|
|
92
|
-
"auto_link_unverified_accounts_facebook",
|
|
93
|
-
false
|
|
94
|
-
);
|
|
95
|
-
|
|
96
71
|
const google_button_text = get_config_value(
|
|
97
72
|
SECTION_NAME,
|
|
98
73
|
"google_button_text",
|
|
99
74
|
DEFAULT_OAUTH.google_button_text
|
|
100
75
|
);
|
|
101
76
|
|
|
102
|
-
const facebook_button_text = get_config_value(
|
|
103
|
-
SECTION_NAME,
|
|
104
|
-
"facebook_button_text",
|
|
105
|
-
"Continue with Facebook"
|
|
106
|
-
);
|
|
107
|
-
|
|
108
77
|
const oauth_divider_text = get_config_value(
|
|
109
78
|
SECTION_NAME,
|
|
110
79
|
"oauth_divider_text",
|
|
@@ -147,18 +116,31 @@ export function get_oauth_config(): OAuthConfig {
|
|
|
147
116
|
DEFAULT_OAUTH.no_scope_redirect
|
|
148
117
|
);
|
|
149
118
|
|
|
150
|
-
const
|
|
151
|
-
|
|
119
|
+
const enable_facebook_oauth = get_config_boolean(
|
|
120
|
+
SECTION_NAME,
|
|
121
|
+
"enable_facebook_oauth",
|
|
122
|
+
false
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const facebook_app_id =
|
|
126
|
+
process.env.HAZO_AUTH_FACEBOOK_APP_ID ||
|
|
127
|
+
get_config_value(SECTION_NAME, "facebook_app_id", "");
|
|
128
|
+
|
|
129
|
+
const facebook_app_secret =
|
|
130
|
+
process.env.HAZO_AUTH_FACEBOOK_APP_SECRET ||
|
|
131
|
+
get_config_value(SECTION_NAME, "facebook_app_secret", "");
|
|
132
|
+
|
|
133
|
+
const facebook_button_text = get_config_value(
|
|
134
|
+
SECTION_NAME,
|
|
135
|
+
"facebook_button_text",
|
|
136
|
+
"Continue with Facebook"
|
|
137
|
+
);
|
|
152
138
|
|
|
153
139
|
return {
|
|
154
140
|
enable_google,
|
|
155
|
-
enable_facebook,
|
|
156
141
|
enable_email_password,
|
|
157
142
|
auto_link_unverified_accounts,
|
|
158
|
-
auto_link_unverified_accounts_google,
|
|
159
|
-
auto_link_unverified_accounts_facebook,
|
|
160
143
|
google_button_text,
|
|
161
|
-
facebook_button_text,
|
|
162
144
|
oauth_divider_text,
|
|
163
145
|
sign_in_page,
|
|
164
146
|
error_page,
|
|
@@ -166,8 +148,10 @@ export function get_oauth_config(): OAuthConfig {
|
|
|
166
148
|
default_redirect,
|
|
167
149
|
skip_invitation_check,
|
|
168
150
|
no_scope_redirect,
|
|
169
|
-
|
|
170
|
-
|
|
151
|
+
enable_facebook_oauth,
|
|
152
|
+
facebook_app_id,
|
|
153
|
+
facebook_app_secret,
|
|
154
|
+
facebook_button_text,
|
|
171
155
|
};
|
|
172
156
|
}
|
|
173
157
|
|
|
@@ -190,13 +174,3 @@ export function is_email_password_enabled(): boolean {
|
|
|
190
174
|
DEFAULT_OAUTH.enable_email_password
|
|
191
175
|
);
|
|
192
176
|
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Helper to check if Facebook OAuth is enabled and credentials are present
|
|
196
|
-
* @returns true if Facebook OAuth is enabled and env vars are set
|
|
197
|
-
*/
|
|
198
|
-
export function is_facebook_oauth_enabled(): boolean {
|
|
199
|
-
const enabled = get_config_boolean(SECTION_NAME, "enable_facebook", false);
|
|
200
|
-
if (!enabled) return false;
|
|
201
|
-
return !!(process.env.HAZO_AUTH_FACEBOOK_APP_ID && process.env.HAZO_AUTH_FACEBOOK_APP_SECRET);
|
|
202
|
-
}
|