@payez/next-mvp 4.8.0 → 4.8.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/POST-INSTALL.md +408 -408
- package/README.md +859 -859
- package/dist/components/account/MobileNavDrawer.js +18 -18
- package/dist/components/account/UserAvatarMenu.js +1 -1
- package/dist/components/admin/AlertSettingsTab.js +40 -40
- package/dist/components/admin/LoggingSettingsTab.js +28 -28
- package/dist/lib/session-store.js +21 -21
- package/dist/lib/startup-init.js +19 -19
- package/dist/middleware/create-middleware.js +6 -5
- package/dist/pages/login/page.js +28 -28
- package/dist/pages/settings/EnhancedSettingsPage.js +17 -17
- package/dist/vibe/sessions.js +28 -3
- package/package.json +2 -2
- package/scripts/check-publish-eol.mjs +33 -15
- package/src/api/auth-handler.ts +550 -550
- package/src/api/index.ts +17 -17
- package/src/api-handlers/account/change-password.ts +170 -170
- package/src/api-handlers/account/masked-info.ts +46 -46
- package/src/api-handlers/account/profile.ts +99 -99
- package/src/api-handlers/account/recovery/forward.ts +117 -117
- package/src/api-handlers/account/recovery/initiate.ts +59 -59
- package/src/api-handlers/account/recovery/send-code.ts +21 -21
- package/src/api-handlers/account/recovery/verify-code.ts +20 -20
- package/src/api-handlers/account/reset-password.ts +87 -87
- package/src/api-handlers/account/send-code.ts +70 -70
- package/src/api-handlers/account/update-phone.ts +84 -84
- package/src/api-handlers/account/validate-password.ts +139 -139
- package/src/api-handlers/account/verify-email.ts +134 -134
- package/src/api-handlers/account/verify-sms.ts +134 -134
- package/src/api-handlers/admin/analytics.ts +452 -452
- package/src/api-handlers/admin/audit.ts +232 -232
- package/src/api-handlers/admin/index.ts +63 -63
- package/src/api-handlers/admin/redis-sessions.ts +259 -259
- package/src/api-handlers/admin/sessions.ts +327 -327
- package/src/api-handlers/admin/site-logs.ts +388 -388
- package/src/api-handlers/admin/stats.ts +260 -260
- package/src/api-handlers/admin/users.ts +251 -251
- package/src/api-handlers/admin/vibe-data.ts +333 -333
- package/src/api-handlers/anon/preferences.ts +123 -123
- package/src/api-handlers/auth/credential-login-email-code.ts +92 -92
- package/src/api-handlers/auth/credential-login.ts +948 -948
- package/src/api-handlers/auth/jwks.ts +31 -31
- package/src/api-handlers/auth/login.ts +252 -252
- package/src/api-handlers/auth/passkey-signin.ts +116 -116
- package/src/api-handlers/auth/refresh.ts +829 -829
- package/src/api-handlers/auth/signout.ts +201 -201
- package/src/api-handlers/auth/status.ts +23 -23
- package/src/api-handlers/auth/update-session.ts +144 -144
- package/src/api-handlers/auth/validate.ts +45 -45
- package/src/api-handlers/auth/verify-code.ts +116 -116
- package/src/api-handlers/mfa/backup-code-verify.ts +170 -170
- package/src/api-handlers/mfa/backup-codes.ts +42 -42
- package/src/api-handlers/mfa/methods.ts +47 -47
- package/src/api-handlers/mfa/totp-confirm.ts +43 -43
- package/src/api-handlers/mfa/totp-enroll.ts +43 -43
- package/src/api-handlers/mfa/totp-verify.ts +172 -172
- package/src/api-handlers/oauth/resume.ts +182 -182
- package/src/api-handlers/onboarding/send-email-code.ts +18 -18
- package/src/api-handlers/onboarding/set-password.ts +21 -21
- package/src/api-handlers/onboarding/verify-code.ts +20 -20
- package/src/api-handlers/onboarding/verify-welcome-email.ts +17 -17
- package/src/api-handlers/passkeys/list.ts +32 -32
- package/src/api-handlers/passkeys/manage.ts +55 -55
- package/src/api-handlers/passkeys/register-options.ts +43 -43
- package/src/api-handlers/passkeys/register-verify.ts +42 -42
- package/src/api-handlers/session/refresh-viability.ts +56 -56
- package/src/api-handlers/session/viability.ts +238 -238
- package/src/api-handlers/test/force-expire.ts +167 -167
- package/src/auth/auth-decision.ts +292 -292
- package/src/auth/better-auth.ts +1688 -1688
- package/src/auth/idp-oauth.ts +310 -310
- package/src/auth/password-reset-bridge.ts +98 -98
- package/src/auth/route-config.ts +236 -236
- package/src/auth/safe-callback.ts +199 -199
- package/src/auth/session-cookie-clear.ts +30 -30
- package/src/auth/session-reset-link.ts +159 -159
- package/src/auth/session-response-sanitizer.ts +151 -151
- package/src/auth/types/auth-types.ts +555 -555
- package/src/auth/types/index.ts +7 -7
- package/src/auth/unauthenticated-routes.ts +2 -2
- package/src/auth/utils/idp-client.ts +364 -364
- package/src/auth/utils/index.ts +6 -6
- package/src/auth/utils/token-utils.ts +243 -243
- package/src/client/AuthContext.tsx +192 -192
- package/src/client/better-auth-client.ts +70 -70
- package/src/client/fetch-with-auth.ts +47 -47
- package/src/client/fetchWithSession.ts +21 -21
- package/src/client/index.ts +13 -13
- package/src/client/useAnonSession.ts +131 -131
- package/src/components/SessionSync.tsx +138 -138
- package/src/components/SignalRHealthCheck.tsx +131 -131
- package/src/components/account/MobileNavDrawer.tsx +305 -305
- package/src/components/account/UserAvatarMenu.tsx +277 -277
- package/src/components/account/index.ts +13 -13
- package/src/components/admin/AlertSettingsTab.tsx +728 -728
- package/src/components/admin/AnalyticsTab.tsx +703 -703
- package/src/components/admin/DataBrowserTab.tsx +508 -508
- package/src/components/admin/LoggingSettingsTab.tsx +665 -665
- package/src/components/admin/SessionsTab.tsx +421 -421
- package/src/components/admin/StatsTab.tsx +379 -379
- package/src/components/admin/VibeAdminContext.tsx +87 -87
- package/src/components/admin/VibeAdminLayout.tsx +187 -187
- package/src/components/admin/index.ts +59 -59
- package/src/components/auth/CredentialSignInForm.tsx +240 -240
- package/src/components/auth/FederatedAuthSection.tsx +129 -129
- package/src/components/auth/ModeAwareLoginPage.tsx +146 -146
- package/src/components/auth/ModeAwareSignupPage.tsx +200 -200
- package/src/components/auth/PasswordResetBridge.tsx +30 -30
- package/src/components/auth/TraditionalAuthSection.tsx +103 -103
- package/src/components/recovery/CompleteStep.tsx +36 -36
- package/src/components/recovery/InitiateRecoveryStep.tsx +68 -68
- package/src/components/recovery/RequestedStep.tsx +30 -30
- package/src/components/recovery/SelectMethodStep.tsx +73 -73
- package/src/components/recovery/SetPasswordStep.tsx +118 -118
- package/src/components/recovery/VerifyCodeStep.tsx +90 -90
- package/src/components/reserved/ReservedRecoveryWarning.tsx +160 -160
- package/src/components/reserved/ReservedStatusBox.tsx +118 -118
- package/src/components/ui/BetaBadge.tsx +58 -58
- package/src/components/ui/Footer.tsx +93 -93
- package/src/config/env.ts +55 -55
- package/src/config/logger.ts +62 -62
- package/src/config/logging-config.ts +82 -82
- package/src/config/unauthenticated-routes.ts +19 -19
- package/src/config/vibe-log-transport.ts +264 -264
- package/src/edge/internal-api-url.ts +65 -65
- package/src/edge/middleware.ts +42 -42
- package/src/hooks/useAuth.ts +117 -117
- package/src/hooks/useAuthSettings.ts +109 -109
- package/src/hooks/useAvailableProviders.ts +143 -143
- package/src/hooks/usePasswordValidation.ts +127 -127
- package/src/hooks/useProfile.ts +82 -82
- package/src/hooks/usePublicAuthSettings.ts +171 -171
- package/src/hooks/useSessionExpiration.ts +101 -101
- package/src/hooks/useViabilitySession.ts +337 -337
- package/src/index.ts +64 -64
- package/src/lib/anon-session.ts +213 -213
- package/src/lib/api-handler.ts +643 -643
- package/src/lib/app-slug.ts +228 -228
- package/src/lib/authorize-resume.ts +172 -172
- package/src/lib/bearer-fetch.ts +31 -31
- package/src/lib/client-key.ts +88 -88
- package/src/lib/code-step-copy.ts +83 -83
- package/src/lib/credential-sign-in-client.ts +101 -101
- package/src/lib/demo-mode.ts +18 -18
- package/src/lib/device-id.ts +67 -67
- package/src/lib/ensure-fresh-access-token.ts +509 -509
- package/src/lib/geolocation.ts +265 -265
- package/src/lib/idp-client-config.ts +1005 -1005
- package/src/lib/idp-fetch.ts +169 -169
- package/src/lib/idp-url-guard.ts +37 -37
- package/src/lib/internal-api.ts +171 -171
- package/src/lib/jwt-decode-client.ts +45 -45
- package/src/lib/jwt-decode.ts +82 -82
- package/src/lib/lock-window.ts +49 -49
- package/src/lib/login-error-message.ts +41 -41
- package/src/lib/never-in-response.ts +64 -64
- package/src/lib/nextauth-secret.ts +168 -168
- package/src/lib/onboarding-proxy.ts +57 -57
- package/src/lib/password-rules.ts +50 -50
- package/src/lib/rate-limit-service.ts +9 -9
- package/src/lib/redis.ts +105 -105
- package/src/lib/refresh-token-validator.ts +64 -64
- package/src/lib/roles.ts +177 -177
- package/src/lib/safe-error-response.ts +149 -149
- package/src/lib/secret-validation.ts +8 -8
- package/src/lib/session-cookie-shape.ts +185 -185
- package/src/lib/session-store.ts +1092 -1092
- package/src/lib/session.ts +34 -34
- package/src/lib/single-flight.ts +64 -64
- package/src/lib/site-logger.ts +245 -245
- package/src/lib/standardized-client-api.ts +901 -901
- package/src/lib/startup-init.ts +276 -276
- package/src/lib/test-aware-get-token.ts +41 -41
- package/src/lib/token-expiry.ts +40 -40
- package/src/lib/token-lifecycle.ts +546 -546
- package/src/lib/token-log-id.ts +69 -69
- package/src/lib/twofa-rejection.ts +91 -91
- package/src/lib/types/api-responses.ts +336 -336
- package/src/lib/user-agent-parser.ts +252 -252
- package/src/logging/api/admin-analytics.ts +51 -51
- package/src/logging/api/audit-log.ts +53 -53
- package/src/logging/components/AdminAnalyticsLayout.tsx +49 -49
- package/src/logging/components/AuditLogViewer.tsx +125 -125
- package/src/logging/components/ErrorMetricsCard.tsx +98 -98
- package/src/logging/components/HealthMetricsCard.tsx +70 -70
- package/src/logging/hooks/useAdminAnalytics.ts +22 -22
- package/src/logging/hooks/useAuditLog.ts +24 -24
- package/src/logging/hooks/useErrorMetrics.ts +40 -40
- package/src/logging/hooks/useHealthMetrics.ts +44 -44
- package/src/logging/index.ts +18 -18
- package/src/logging/types/analytics.ts +81 -81
- package/src/logging/types/audit.ts +31 -31
- package/src/logging/types/index.ts +3 -3
- package/src/middleware/create-middleware.ts +1139 -1138
- package/src/middleware/rbac-check.ts +279 -279
- package/src/middleware/twofa-presets.ts +224 -224
- package/src/models/DecodedAccessToken.ts +16 -16
- package/src/models/SessionModel.ts +331 -331
- package/src/pages/admin-login/page.tsx +111 -111
- package/src/pages/admin-page-permissions/PagePermissionsAdminPage.tsx +527 -527
- package/src/pages/admin-page-permissions/index.ts +7 -7
- package/src/pages/admin-roles/RolesAdminPage.tsx +533 -533
- package/src/pages/admin-roles/index.ts +9 -9
- package/src/pages/admin-roles/modals.tsx +469 -469
- package/src/pages/client-admin/ClientSiteAdminPage.tsx +382 -382
- package/src/pages/client-admin/index.ts +33 -33
- package/src/pages/coming-soon/page.tsx +83 -83
- package/src/pages/login/page.tsx +338 -338
- package/src/pages/onboarding/index.ts +11 -11
- package/src/pages/onboarding/page.tsx +212 -212
- package/src/pages/profile/EnhancedProfilePage.tsx +514 -514
- package/src/pages/profile/index.ts +9 -9
- package/src/pages/profile/page.tsx +166 -166
- package/src/pages/recovery/page.tsx +267 -267
- package/src/pages/roles/MyRolesPage.tsx +211 -211
- package/src/pages/roles/components.tsx +294 -294
- package/src/pages/roles/index.ts +17 -17
- package/src/pages/security/EnhancedSecurityPage.tsx +660 -660
- package/src/pages/security/index.ts +12 -12
- package/src/pages/security/page.tsx +507 -507
- package/src/pages/settings/EnhancedSettingsPage.tsx +642 -642
- package/src/pages/settings/index.ts +9 -9
- package/src/pages/settings/page.tsx +47 -47
- package/src/pages/showcase/ShowcasePage.tsx +532 -532
- package/src/pages/showcase/index.ts +13 -13
- package/src/pages/test-env/EmergencyLogoutPage.tsx +192 -192
- package/src/pages/test-env/JwtInspectPage.tsx +449 -449
- package/src/pages/test-env/RefreshTokenPage.tsx +178 -178
- package/src/pages/test-env/TestEnvPage.tsx +130 -130
- package/src/pages/test-env/guarded.tsx +81 -81
- package/src/pages/test-env/index.ts +77 -77
- package/src/pages/test-env/redact-credentials.ts +96 -96
- package/src/pages/verify-code/page.tsx +746 -746
- package/src/routes/account/index.ts +31 -31
- package/src/routes/account/masked-info.ts +36 -36
- package/src/routes/account/send-code.ts +39 -39
- package/src/routes/account/update-phone.ts +13 -13
- package/src/routes/account/verify-email.ts +40 -40
- package/src/routes/account/verify-sms.ts +40 -40
- package/src/routes/auth/credential-login-email-code.ts +6 -6
- package/src/routes/auth/credential-login.ts +6 -6
- package/src/routes/auth/index.ts +22 -22
- package/src/routes/auth/logout.ts +111 -111
- package/src/routes/auth/nextauth.ts +45 -45
- package/src/routes/auth/passkey-signin.ts +13 -13
- package/src/routes/auth/refresh.ts +77 -77
- package/src/routes/auth/session-reset.ts +37 -37
- package/src/routes/auth/session.ts +261 -261
- package/src/routes/auth/settings.ts +181 -181
- package/src/routes/auth/viability.ts +519 -519
- package/src/routes/index.ts +17 -17
- package/src/routes/mfa/backup-code-verify.ts +1 -1
- package/src/routes/mfa/backup-codes.ts +10 -10
- package/src/routes/mfa/methods.ts +22 -22
- package/src/routes/mfa/totp-confirm.ts +10 -10
- package/src/routes/mfa/totp-enroll.ts +10 -10
- package/src/routes/mfa/totp-verify.ts +14 -14
- package/src/routes/onboarding/index.ts +15 -15
- package/src/routes/onboarding/send-email-code.ts +2 -2
- package/src/routes/onboarding/set-password.ts +2 -2
- package/src/routes/onboarding/verify-code.ts +2 -2
- package/src/routes/onboarding/verify-welcome-email.ts +2 -2
- package/src/routes/passkeys/list.ts +10 -10
- package/src/routes/passkeys/manage.ts +23 -23
- package/src/routes/passkeys/register-options.ts +10 -10
- package/src/routes/passkeys/register-verify.ts +10 -10
- package/src/routes/session/index.ts +7 -7
- package/src/routes/session/refresh-viability.ts +17 -17
- package/src/server/auth-guard.ts +203 -203
- package/src/server/auth.ts +486 -486
- package/src/server/decode-session.ts +309 -309
- package/src/server/slim-middleware.ts +117 -117
- package/src/server/verified-session-token.ts +103 -103
- package/src/server/with-auth.ts +93 -93
- package/src/services/signalrActivityService.ts +258 -258
- package/src/stores/authStore.ts +1900 -1900
- package/src/templates/instrumentation.ts +60 -60
- package/src/theme/ThemeProvider.tsx +39 -39
- package/src/theme/default.ts +33 -33
- package/src/theme/index.ts +31 -31
- package/src/theme/types.ts +69 -69
- package/src/theme/useTheme.ts +57 -57
- package/src/theme/utils.ts +40 -40
- package/src/types/api.ts +12 -12
- package/src/types/auth.d.ts +23 -23
- package/src/types/auth.ts +48 -48
- package/src/types/logging.ts +11 -11
- package/src/types/recovery.ts +54 -54
- package/src/utils/api.ts +401 -401
- package/src/utils/circuitBreaker.ts +40 -40
- package/src/utils/error-message.ts +108 -108
- package/src/utils/layout/reservedSpace.ts +124 -124
- package/src/utils/logout.ts +30 -30
- package/src/vibe/client.ts +877 -877
- package/src/vibe/enterprise-auth.ts +208 -208
- package/src/vibe/errors.ts +209 -209
- package/src/vibe/generic.ts +339 -339
- package/src/vibe/hooks/index.ts +367 -367
- package/src/vibe/index.ts +133 -133
- package/src/vibe/sessions.ts +925 -899
- package/src/vibe/types.ts +577 -577
package/src/hooks/useProfile.ts
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ⚠️ WARNING: This hook cannot be used directly from the @payez/next-mvp package!
|
|
5
|
-
*
|
|
6
|
-
* @deprecated Import this hook from your local app instead
|
|
7
|
-
*
|
|
8
|
-
* **Why?** This hook depends on useAuth, which requires SessionProvider context that cannot cross package boundaries.
|
|
9
|
-
*
|
|
10
|
-
* **Solution:** Create a local version in your app (e.g., src/hooks/useProfile.ts):
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* // src/hooks/useProfile.ts (YOUR APP)
|
|
15
|
-
* 'use client';
|
|
16
|
-
* import { useQuery } from '@tanstack/react-query';
|
|
17
|
-
* import { useAuth } from './useAuth'; // Your local useAuth
|
|
18
|
-
* import { isApiSuccess } from '@payez/next-mvp/lib/standardized-client-api';
|
|
19
|
-
*
|
|
20
|
-
* export function useProfile() {
|
|
21
|
-
* const { isAuthenticated, apiCall } = useAuth();
|
|
22
|
-
* return useQuery({
|
|
23
|
-
* queryKey: ['account', 'profile'],
|
|
24
|
-
* enabled: isAuthenticated,
|
|
25
|
-
* queryFn: async () => {
|
|
26
|
-
* const result = await apiCall('/api/account/profile', 'GET');
|
|
27
|
-
* if (isApiSuccess(result)) return result.data;
|
|
28
|
-
* throw new Error(result.message);
|
|
29
|
-
* }
|
|
30
|
-
* });
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*
|
|
34
|
-
* @see {@link https://github.com/payez/next-mvp/blob/main/docs/centralized-auth-api-pattern.md#usage-patterns Complete documentation}
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
import { useQuery } from '@tanstack/react-query';
|
|
38
|
-
import { useAuth } from './useAuth';
|
|
39
|
-
import { isApiSuccess, isApiError } from '../lib/standardized-client-api';
|
|
40
|
-
|
|
41
|
-
export type ProfileResponse = {
|
|
42
|
-
email: string;
|
|
43
|
-
user_id?: string;
|
|
44
|
-
first_name?: string;
|
|
45
|
-
last_name?: string;
|
|
46
|
-
full_name?: string;
|
|
47
|
-
phone_number?: string;
|
|
48
|
-
email_confirmed?: boolean;
|
|
49
|
-
phone_confirmed?: boolean;
|
|
50
|
-
two_factor_enabled?: boolean;
|
|
51
|
-
roles?: string[];
|
|
52
|
-
// REMOVED: `contact_information?: Record<string, any>` - the ADMIN DTO's field
|
|
53
|
-
// name (AdminUserProfileResponse), never emitted by /api/account/profile. This
|
|
54
|
-
// permissive declaration is WHY the wrong mapper type-checked for so long: the
|
|
55
|
-
// correct `contact_info` and `address` shapes were already declared right here,
|
|
56
|
-
// and this `Record<string, any>` sat beside them as an off switch, accepting
|
|
57
|
-
// `contact_information.addressLine1` on a path that could never carry data.
|
|
58
|
-
// Found by BAPert (41365) as the residual of my own half-sweep - I deleted the
|
|
59
|
-
// twin of this line from EnhancedProfilePage and left this one standing.
|
|
60
|
-
[key: string]: any;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export function useProfile() {
|
|
64
|
-
const { isAuthenticated, apiCall } = useAuth();
|
|
65
|
-
|
|
66
|
-
return useQuery<ProfileResponse, Error>({
|
|
67
|
-
queryKey: ['account', 'profile'],
|
|
68
|
-
enabled: isAuthenticated,
|
|
69
|
-
queryFn: async () => {
|
|
70
|
-
const result = await apiCall<ProfileResponse>('/api/account/profile', 'GET');
|
|
71
|
-
if (isApiSuccess(result)) {
|
|
72
|
-
return result.data;
|
|
73
|
-
}
|
|
74
|
-
// If API returned standardized error
|
|
75
|
-
if (isApiError(result)) {
|
|
76
|
-
throw new Error(result.message || 'Failed to load profile');
|
|
77
|
-
}
|
|
78
|
-
throw new Error('Failed to load profile');
|
|
79
|
-
},
|
|
80
|
-
staleTime: 5 * 60 * 1000,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ⚠️ WARNING: This hook cannot be used directly from the @payez/next-mvp package!
|
|
5
|
+
*
|
|
6
|
+
* @deprecated Import this hook from your local app instead
|
|
7
|
+
*
|
|
8
|
+
* **Why?** This hook depends on useAuth, which requires SessionProvider context that cannot cross package boundaries.
|
|
9
|
+
*
|
|
10
|
+
* **Solution:** Create a local version in your app (e.g., src/hooks/useProfile.ts):
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // src/hooks/useProfile.ts (YOUR APP)
|
|
15
|
+
* 'use client';
|
|
16
|
+
* import { useQuery } from '@tanstack/react-query';
|
|
17
|
+
* import { useAuth } from './useAuth'; // Your local useAuth
|
|
18
|
+
* import { isApiSuccess } from '@payez/next-mvp/lib/standardized-client-api';
|
|
19
|
+
*
|
|
20
|
+
* export function useProfile() {
|
|
21
|
+
* const { isAuthenticated, apiCall } = useAuth();
|
|
22
|
+
* return useQuery({
|
|
23
|
+
* queryKey: ['account', 'profile'],
|
|
24
|
+
* enabled: isAuthenticated,
|
|
25
|
+
* queryFn: async () => {
|
|
26
|
+
* const result = await apiCall('/api/account/profile', 'GET');
|
|
27
|
+
* if (isApiSuccess(result)) return result.data;
|
|
28
|
+
* throw new Error(result.message);
|
|
29
|
+
* }
|
|
30
|
+
* });
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @see {@link https://github.com/payez/next-mvp/blob/main/docs/centralized-auth-api-pattern.md#usage-patterns Complete documentation}
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import { useQuery } from '@tanstack/react-query';
|
|
38
|
+
import { useAuth } from './useAuth';
|
|
39
|
+
import { isApiSuccess, isApiError } from '../lib/standardized-client-api';
|
|
40
|
+
|
|
41
|
+
export type ProfileResponse = {
|
|
42
|
+
email: string;
|
|
43
|
+
user_id?: string;
|
|
44
|
+
first_name?: string;
|
|
45
|
+
last_name?: string;
|
|
46
|
+
full_name?: string;
|
|
47
|
+
phone_number?: string;
|
|
48
|
+
email_confirmed?: boolean;
|
|
49
|
+
phone_confirmed?: boolean;
|
|
50
|
+
two_factor_enabled?: boolean;
|
|
51
|
+
roles?: string[];
|
|
52
|
+
// REMOVED: `contact_information?: Record<string, any>` - the ADMIN DTO's field
|
|
53
|
+
// name (AdminUserProfileResponse), never emitted by /api/account/profile. This
|
|
54
|
+
// permissive declaration is WHY the wrong mapper type-checked for so long: the
|
|
55
|
+
// correct `contact_info` and `address` shapes were already declared right here,
|
|
56
|
+
// and this `Record<string, any>` sat beside them as an off switch, accepting
|
|
57
|
+
// `contact_information.addressLine1` on a path that could never carry data.
|
|
58
|
+
// Found by BAPert (41365) as the residual of my own half-sweep - I deleted the
|
|
59
|
+
// twin of this line from EnhancedProfilePage and left this one standing.
|
|
60
|
+
[key: string]: any;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export function useProfile() {
|
|
64
|
+
const { isAuthenticated, apiCall } = useAuth();
|
|
65
|
+
|
|
66
|
+
return useQuery<ProfileResponse, Error>({
|
|
67
|
+
queryKey: ['account', 'profile'],
|
|
68
|
+
enabled: isAuthenticated,
|
|
69
|
+
queryFn: async () => {
|
|
70
|
+
const result = await apiCall<ProfileResponse>('/api/account/profile', 'GET');
|
|
71
|
+
if (isApiSuccess(result)) {
|
|
72
|
+
return result.data;
|
|
73
|
+
}
|
|
74
|
+
// If API returned standardized error
|
|
75
|
+
if (isApiError(result)) {
|
|
76
|
+
throw new Error(result.message || 'Failed to load profile');
|
|
77
|
+
}
|
|
78
|
+
throw new Error('Failed to load profile');
|
|
79
|
+
},
|
|
80
|
+
staleTime: 5 * 60 * 1000,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* usePublicAuthSettings Hook
|
|
3
|
-
*
|
|
4
|
-
* Fetches public auth settings for pre-login pages (signup, login).
|
|
5
|
-
* Does NOT require authentication - settings are fetched via API.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
'use client';
|
|
9
|
-
|
|
10
|
-
import { useState, useEffect } from 'react';
|
|
11
|
-
import type { FederatedProvider } from '../types/auth';
|
|
12
|
-
|
|
13
|
-
export interface PublicAuthSettings {
|
|
14
|
-
enabledProviders: FederatedProvider[];
|
|
15
|
-
allowFederatedLogin: boolean;
|
|
16
|
-
require2FA: boolean;
|
|
17
|
-
allowed2FAMethods: string[];
|
|
18
|
-
// OPTIONAL: present only when the IDP states them, never invented.
|
|
19
|
-
// 257255 removed these on the basis that "the config document does not
|
|
20
|
-
// carry them"; the 240447 loader fix has since made the document carry
|
|
21
|
-
// them, so routes/auth/settings.ts reads and returns them again. They stay
|
|
22
|
-
// OPTIONAL because an older IDP build may omit them, and `?? true` would
|
|
23
|
-
// re-create the exact permission claim this card exists to kill.
|
|
24
|
-
// (The @example below already assumed this field - it referenced
|
|
25
|
-
// settings?.allowPublicRegistration while the type had removed it.)
|
|
26
|
-
allowPublicRegistration?: boolean;
|
|
27
|
-
enablePasswordReset?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface UsePublicAuthSettingsResult {
|
|
31
|
-
settings: PublicAuthSettings | null;
|
|
32
|
-
isLoading: boolean;
|
|
33
|
-
error: Error | null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Map provider strings to FederatedProvider type
|
|
37
|
-
const PROVIDER_MAP: Record<string, FederatedProvider> = {
|
|
38
|
-
'google': 'google',
|
|
39
|
-
'apple': 'apple',
|
|
40
|
-
'facebook': 'facebook',
|
|
41
|
-
'github': 'github',
|
|
42
|
-
'microsoft': 'microsoft',
|
|
43
|
-
'azure-ad': 'microsoft',
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// 257255 / BAPert ruling v32(a): DEFAULT_SETTINGS DELETED.
|
|
47
|
-
//
|
|
48
|
-
// It was substituted on BOTH failure branches below, so a page kept rendering
|
|
49
|
-
// require2FA=true with methods ['email','sms'] whenever the fetch failed - a
|
|
50
|
-
// FABRICATED AUTHORIZATION POLICY, client-side. Hard-failing the endpoint alone
|
|
51
|
-
// does not fix that: it just moves the lie from the server to the browser.
|
|
52
|
-
//
|
|
53
|
-
// QAPert's measurement makes this a proof rather than a preference: the SAME
|
|
54
|
-
// client is require_2fa=TRUE on AKS and FALSE on dev-93, so any hardcoded
|
|
55
|
-
// fallback is wrong in at least one environment BY CONSTRUCTION.
|
|
56
|
-
//
|
|
57
|
-
// On failure `settings` stays NULL and `error` is set. Callers must render an
|
|
58
|
-
// honest "we could not load sign-in options" state and OFFER NOTHING.
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Hook to fetch public auth settings for login/signup pages.
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* ```tsx
|
|
65
|
-
* function SignupPage() {
|
|
66
|
-
* const { settings, isLoading } = usePublicAuthSettings();
|
|
67
|
-
*
|
|
68
|
-
* if (isLoading) return <Spinner />;
|
|
69
|
-
*
|
|
70
|
-
* return (
|
|
71
|
-
* <>
|
|
72
|
-
* {settings?.allowFederatedLogin && (
|
|
73
|
-
* <FederatedAuthSection providers={settings.enabledProviders} />
|
|
74
|
-
* )}
|
|
75
|
-
* {settings?.allowPublicRegistration && (
|
|
76
|
-
* <EmailSignupForm />
|
|
77
|
-
* )}
|
|
78
|
-
* </>
|
|
79
|
-
* );
|
|
80
|
-
* }
|
|
81
|
-
* ```
|
|
82
|
-
*/
|
|
83
|
-
export function usePublicAuthSettings(): UsePublicAuthSettingsResult {
|
|
84
|
-
const [settings, setSettings] = useState<PublicAuthSettings | null>(null);
|
|
85
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
86
|
-
const [error, setError] = useState<Error | null>(null);
|
|
87
|
-
|
|
88
|
-
useEffect(() => {
|
|
89
|
-
let mounted = true;
|
|
90
|
-
|
|
91
|
-
async function fetchSettings() {
|
|
92
|
-
try {
|
|
93
|
-
const response = await fetch('/api/auth/settings');
|
|
94
|
-
|
|
95
|
-
if (!mounted) return;
|
|
96
|
-
|
|
97
|
-
if (!response.ok) {
|
|
98
|
-
throw new Error(`Failed to fetch auth settings: ${response.status}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const data = await response.json();
|
|
102
|
-
|
|
103
|
-
if (data.success && data.data) {
|
|
104
|
-
// Map provider strings to FederatedProvider type
|
|
105
|
-
const providers = (data.data.enabledProviders || [])
|
|
106
|
-
.map((p: string) => PROVIDER_MAP[p.toLowerCase()])
|
|
107
|
-
.filter((p: FederatedProvider | undefined): p is FederatedProvider => p !== undefined);
|
|
108
|
-
|
|
109
|
-
setSettings({
|
|
110
|
-
...data.data,
|
|
111
|
-
enabledProviders: providers,
|
|
112
|
-
});
|
|
113
|
-
} else {
|
|
114
|
-
// The endpoint told us it could not read a policy (503 +
|
|
115
|
-
// success:false + code). Do NOT invent one - surface it.
|
|
116
|
-
const code = data?.error?.code ?? 'POLICY_UNAVAILABLE';
|
|
117
|
-
setSettings(null);
|
|
118
|
-
setError(new Error(`[auth-settings] ${code}: sign-in options unavailable`));
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
setError(null);
|
|
123
|
-
} catch (err) {
|
|
124
|
-
if (!mounted) return;
|
|
125
|
-
console.warn('[usePublicAuthSettings] Failed to fetch settings:', err);
|
|
126
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
127
|
-
setSettings(null); // 257255: never fabricate a policy
|
|
128
|
-
} finally {
|
|
129
|
-
if (mounted) {
|
|
130
|
-
setIsLoading(false);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
fetchSettings();
|
|
136
|
-
|
|
137
|
-
return () => {
|
|
138
|
-
mounted = false;
|
|
139
|
-
};
|
|
140
|
-
}, []);
|
|
141
|
-
|
|
142
|
-
return { settings, isLoading, error };
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Hook to check if federated (OAuth) login is enabled.
|
|
147
|
-
*/
|
|
148
|
-
export function useFederatedLoginEnabled(): boolean {
|
|
149
|
-
const { settings } = usePublicAuthSettings();
|
|
150
|
-
return settings?.allowFederatedLogin ?? false;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Hook to check if public registration is enabled.
|
|
155
|
-
*/
|
|
156
|
-
export function usePublicRegistrationEnabled(): boolean {
|
|
157
|
-
// 257255: was `?? true`, which OFFERED a sign-up lane the IDP may forbid -
|
|
158
|
-
// card 240447 measured exactly that on portal. The field is no longer served
|
|
159
|
-
// (it was never read from config), so this is now always fail-closed until
|
|
160
|
-
// the config document carries it.
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Hook to check if password reset is enabled.
|
|
166
|
-
*/
|
|
167
|
-
export function usePasswordResetEnabled(): boolean {
|
|
168
|
-
// 257255: was `?? true` and was never read from config. Fail-closed until
|
|
169
|
-
// the config document carries it.
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* usePublicAuthSettings Hook
|
|
3
|
+
*
|
|
4
|
+
* Fetches public auth settings for pre-login pages (signup, login).
|
|
5
|
+
* Does NOT require authentication - settings are fetched via API.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use client';
|
|
9
|
+
|
|
10
|
+
import { useState, useEffect } from 'react';
|
|
11
|
+
import type { FederatedProvider } from '../types/auth';
|
|
12
|
+
|
|
13
|
+
export interface PublicAuthSettings {
|
|
14
|
+
enabledProviders: FederatedProvider[];
|
|
15
|
+
allowFederatedLogin: boolean;
|
|
16
|
+
require2FA: boolean;
|
|
17
|
+
allowed2FAMethods: string[];
|
|
18
|
+
// OPTIONAL: present only when the IDP states them, never invented.
|
|
19
|
+
// 257255 removed these on the basis that "the config document does not
|
|
20
|
+
// carry them"; the 240447 loader fix has since made the document carry
|
|
21
|
+
// them, so routes/auth/settings.ts reads and returns them again. They stay
|
|
22
|
+
// OPTIONAL because an older IDP build may omit them, and `?? true` would
|
|
23
|
+
// re-create the exact permission claim this card exists to kill.
|
|
24
|
+
// (The @example below already assumed this field - it referenced
|
|
25
|
+
// settings?.allowPublicRegistration while the type had removed it.)
|
|
26
|
+
allowPublicRegistration?: boolean;
|
|
27
|
+
enablePasswordReset?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface UsePublicAuthSettingsResult {
|
|
31
|
+
settings: PublicAuthSettings | null;
|
|
32
|
+
isLoading: boolean;
|
|
33
|
+
error: Error | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Map provider strings to FederatedProvider type
|
|
37
|
+
const PROVIDER_MAP: Record<string, FederatedProvider> = {
|
|
38
|
+
'google': 'google',
|
|
39
|
+
'apple': 'apple',
|
|
40
|
+
'facebook': 'facebook',
|
|
41
|
+
'github': 'github',
|
|
42
|
+
'microsoft': 'microsoft',
|
|
43
|
+
'azure-ad': 'microsoft',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// 257255 / BAPert ruling v32(a): DEFAULT_SETTINGS DELETED.
|
|
47
|
+
//
|
|
48
|
+
// It was substituted on BOTH failure branches below, so a page kept rendering
|
|
49
|
+
// require2FA=true with methods ['email','sms'] whenever the fetch failed - a
|
|
50
|
+
// FABRICATED AUTHORIZATION POLICY, client-side. Hard-failing the endpoint alone
|
|
51
|
+
// does not fix that: it just moves the lie from the server to the browser.
|
|
52
|
+
//
|
|
53
|
+
// QAPert's measurement makes this a proof rather than a preference: the SAME
|
|
54
|
+
// client is require_2fa=TRUE on AKS and FALSE on dev-93, so any hardcoded
|
|
55
|
+
// fallback is wrong in at least one environment BY CONSTRUCTION.
|
|
56
|
+
//
|
|
57
|
+
// On failure `settings` stays NULL and `error` is set. Callers must render an
|
|
58
|
+
// honest "we could not load sign-in options" state and OFFER NOTHING.
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Hook to fetch public auth settings for login/signup pages.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* function SignupPage() {
|
|
66
|
+
* const { settings, isLoading } = usePublicAuthSettings();
|
|
67
|
+
*
|
|
68
|
+
* if (isLoading) return <Spinner />;
|
|
69
|
+
*
|
|
70
|
+
* return (
|
|
71
|
+
* <>
|
|
72
|
+
* {settings?.allowFederatedLogin && (
|
|
73
|
+
* <FederatedAuthSection providers={settings.enabledProviders} />
|
|
74
|
+
* )}
|
|
75
|
+
* {settings?.allowPublicRegistration && (
|
|
76
|
+
* <EmailSignupForm />
|
|
77
|
+
* )}
|
|
78
|
+
* </>
|
|
79
|
+
* );
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export function usePublicAuthSettings(): UsePublicAuthSettingsResult {
|
|
84
|
+
const [settings, setSettings] = useState<PublicAuthSettings | null>(null);
|
|
85
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
86
|
+
const [error, setError] = useState<Error | null>(null);
|
|
87
|
+
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
let mounted = true;
|
|
90
|
+
|
|
91
|
+
async function fetchSettings() {
|
|
92
|
+
try {
|
|
93
|
+
const response = await fetch('/api/auth/settings');
|
|
94
|
+
|
|
95
|
+
if (!mounted) return;
|
|
96
|
+
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
throw new Error(`Failed to fetch auth settings: ${response.status}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
|
|
103
|
+
if (data.success && data.data) {
|
|
104
|
+
// Map provider strings to FederatedProvider type
|
|
105
|
+
const providers = (data.data.enabledProviders || [])
|
|
106
|
+
.map((p: string) => PROVIDER_MAP[p.toLowerCase()])
|
|
107
|
+
.filter((p: FederatedProvider | undefined): p is FederatedProvider => p !== undefined);
|
|
108
|
+
|
|
109
|
+
setSettings({
|
|
110
|
+
...data.data,
|
|
111
|
+
enabledProviders: providers,
|
|
112
|
+
});
|
|
113
|
+
} else {
|
|
114
|
+
// The endpoint told us it could not read a policy (503 +
|
|
115
|
+
// success:false + code). Do NOT invent one - surface it.
|
|
116
|
+
const code = data?.error?.code ?? 'POLICY_UNAVAILABLE';
|
|
117
|
+
setSettings(null);
|
|
118
|
+
setError(new Error(`[auth-settings] ${code}: sign-in options unavailable`));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
setError(null);
|
|
123
|
+
} catch (err) {
|
|
124
|
+
if (!mounted) return;
|
|
125
|
+
console.warn('[usePublicAuthSettings] Failed to fetch settings:', err);
|
|
126
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
127
|
+
setSettings(null); // 257255: never fabricate a policy
|
|
128
|
+
} finally {
|
|
129
|
+
if (mounted) {
|
|
130
|
+
setIsLoading(false);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
fetchSettings();
|
|
136
|
+
|
|
137
|
+
return () => {
|
|
138
|
+
mounted = false;
|
|
139
|
+
};
|
|
140
|
+
}, []);
|
|
141
|
+
|
|
142
|
+
return { settings, isLoading, error };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Hook to check if federated (OAuth) login is enabled.
|
|
147
|
+
*/
|
|
148
|
+
export function useFederatedLoginEnabled(): boolean {
|
|
149
|
+
const { settings } = usePublicAuthSettings();
|
|
150
|
+
return settings?.allowFederatedLogin ?? false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Hook to check if public registration is enabled.
|
|
155
|
+
*/
|
|
156
|
+
export function usePublicRegistrationEnabled(): boolean {
|
|
157
|
+
// 257255: was `?? true`, which OFFERED a sign-up lane the IDP may forbid -
|
|
158
|
+
// card 240447 measured exactly that on portal. The field is no longer served
|
|
159
|
+
// (it was never read from config), so this is now always fail-closed until
|
|
160
|
+
// the config document carries it.
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Hook to check if password reset is enabled.
|
|
166
|
+
*/
|
|
167
|
+
export function usePasswordResetEnabled(): boolean {
|
|
168
|
+
// 257255: was `?? true` and was never read from config. Fail-closed until
|
|
169
|
+
// the config document carries it.
|
|
170
|
+
return false;
|
|
171
|
+
}
|